过滤器
Filter
过滤器并不是标准的Servlet
,它只是对Web
容器和Servlet
之间的过滤器。主要是对ServletRequest
预处理和ServletResponse
的后处理。
graph LR
webBrowser[web浏览器] --请求--> webContainer[web容器]
webContainer --请求--> filter[过滤器]
filter --请求--> servlet
servlet --响应--> filter
filter --响应--> webContainer
webContainer --响应--> webBrowser
springboot实现
//编写Filter
public class Filter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//主要是为了打印看的清楚
System.err.println("Filter1");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.err.println("请求URL:" + httpServletRequest.getRequestURI());
System.err.println("Filter1");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
//编写Filter
public class Filter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.err.println("Filter2");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.err.println("请求URL:" + httpServletRequest.getRequestURI());
System.err.println("Filter2");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
//注册Filter
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean filter1(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new Filter1());
//过滤器名称
registration.setName("filter1");
//拦截路径
registration.addUrlPatterns("/*");
//设置顺序
registration.setOrder(10);
return registration;
}
@Bean
public FilterRegistrationBean filter2(){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new Filter2());
//过滤器名称
registration.setName("filter2");
//拦截路径
registration.addUrlPatterns("/*");
//设置顺序
registration.setOrder(1);
return registration;
}
}
@GetMapping("/say")
public String hello() {
System.err.println("say hello");
return "hello boot";
}
执行结果
result.png查看发现过滤器已经生效了,spring-boot使用
order
设置过滤器的执行顺序,从小到大。
备注
Servlet3.0
增加了通过@WebFilter
注册过滤器。但是使用注解方式实现无法配置执行顺序。
拦截器
过滤器为
Servlet
内的Api。HandlerInterceptor
为Spring 提供的拦截器。
//编写拦截器
public class Interceptor1 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("Interceptor1 请求前");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.err.println("Interceptor1 请求后");
super.postHandle(request, response, handler, modelAndView);
}
}
public class Interceptor2 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.err.println("Interceptor2 请求前");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.err.println("Interceptor2 请求后");
super.postHandle(request, response, handler, modelAndView);
}
}
//拦截器配置
//注册拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
// 直接 new 不能注入组件
@Bean
public Interceptor1 interceptor1(){
return new Interceptor1();
}
@Bean
public Interceptor2 interceptor2(){
return new Interceptor2();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器 拦截规则
//多个拦截器时 以此添加 执行顺序按添加顺序
registry.addInterceptor(interceptor1()).addPathPatterns("/**").order(2);
registry.addInterceptor(interceptor2()).addPathPatterns("/**").order(1);
}
}
执行结果
result.png
order
设置执行顺序,从小到大。
RequestBodyAdvice/ResponseBodyAdvice
RequestBodyAdvice
可拦截@RequestBody
请求体参数的方法。
ResponseBodyAdvice
对于返回内容做拦截处理。
@RestControllerAdvice
public class RequestAdvice implements RequestBodyAdvice {
//判断是否支持
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
//在请求体未读取(转换)时调用
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
System.err.println("RequestAdvice beforeBodyRead");
return new TestHttpInputMessage(inputMessage);
}
//在请求体完成读取后调用
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
System.err.println("RequestAdvice afterBodyRead");
System.err.println(body);
return body;
}
//当请求体为空时调用
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
System.err.println("RequestAdvice handleEmptyBody");
return body;
}
class TestHttpInputMessage implements HttpInputMessage {
private HttpHeaders headers;
private InputStream body;
public TestHttpInputMessage(HttpInputMessage httpInputMessage) throws IOException {
this.headers = httpInputMessage.getHeaders();
this.body = httpInputMessage.getBody();
}
@Override
public InputStream getBody() throws IOException {
return body;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
}
}
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
//判断是否支持
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
System.err.println("ResponseAdvice");
System.err.println(body);
return body;
}
}
返回结果
result.png备注
使用情况很少,场景多是对请求参数加密,返回结果加密。
区别
result.png- 过滤器在拦截器之前执行。
- 过滤器是
Servlet
规范,所以拦截器只可用于web程序,拦截器是Spring
规范,所以拦截器内可注Spring
对象。 - 拦截器比过滤器更加精细,可在请求前后,视图渲染后拦截,而过滤器只可在
Servlet
前后。 -
RequestBodyAdvice
只可拦截参数注解@RequestBody
的post请求。 - 拦截器,过滤器中使用
HttpServletRequst
获取body
中的数据时只能使用输入流读取,但是输入流只能读取一次,所以需要将HttpServletRequest
再次包装缓存body
内容。Advice
则可多次读取。
网友评论