过滤器和拦截器

过滤器 MyFilter.java

@Component
public class MyFilter implements Filter {

    public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
        System.out.println("filter init");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter before");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter after");
    }

    public void destroy() {
        System.out.println("filter destroy");
    }
}

拦截器 MyInterceptor.java

@Component
public class MyInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("interceptor preHandle");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("interceptor postHandle");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("interceptor afterCompletion");
    }
}

拦截器注册 WebMvcConfig.java

@Component
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor interceptor;

    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(interceptor)
                .addPathPatterns("/run");
    }
}

App.java

@RestController
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }

    @RequestMapping(value = "/run")
    public String run() {
        System.out.println("business code running...");
        return "OK";
    }
}

执行结果

[服务器启动]
...
filter init
...
[请求api]
filter before
interceptor preHandle
business code running...
interceptor postHandle
interceptor afterCompletion
filter after

 

过滤器(Filter)

是JavaEE的标准,依赖于Servlet容器。随web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当web应用停止或重新部署的时候才销毁。

用途
设置字符集、控制权限、控制转向、做一些业务逻辑判断等。

切入点
对用户请求进行预处理,对响应进行后处理,是个典型的处理链:
在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest:
根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
在HttpServletResponse到达客户端之前,拦截HttpServletResponse:
根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

种类
用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求;
日志Filter:详细记录某些特殊的用户请求;
负责解码的Filter:包括对非标准编码的请求解码;
能改变XML内容的XSLTFilter等。

主要接口
init(FilterConfig config):
用于完成Filter的初始化。
destory():
用于Filter销毁前,完成某些资源的回收。
doFilter(ServletRequest request,ServletResponse response,FilterChain chain):
实现过滤功能,该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request),也可实现对服务器响应进行后处理(ServletResponse response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。


拦截器(Interceptor)

不依赖Servlet容器,依赖Spring等Web框架,是AOP的一种应用,底层采用Java的反射机制来实现的。与过滤器一个很大的区别是在拦截器中可以注入Spring的Bean,能够获取到各种需要的Service来处理业务逻辑,而过滤器则不行。

主要接口
preHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandle):
在handler执行之前,返回boolean值,true表示继续执行,false为停止执行并返回。SpringMVC中的Interceptor是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor。每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean类型的,当它返回为false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法。
postHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandle,ModelAndViewmodelAndView):
在handler执行之后,可以在返回之前对返回的结果进行修改。该方法(/afterCompletion方法)都只能是在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用。postHandle方法在Controller方法调用之后执行,但是它会在DispatcherServlet进行视图返回渲染之前被调用,所以可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明的Interceptor的postHandle方法反而会后执行。
afterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandle,Exceptionex):
在请求完全结束后调用,可以用来统计请求耗时等等。
方法,该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

执行顺序
request -> DispatcherServlet -> Interceptor -> preHandle -> Controller -> postHandle -> response

posted @ 2020-10-16 11:43  c3p4501  阅读(80)  评论(0)    收藏  举报