1.实现拦截器

1.写一个拦截器

继承HandlerInterceptor

preHandle:

  • 调用时间: Controller方法处理之前【也就是路径跳转之前】;

  • 执行顺序: 链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行;

  • 返回值: 返回值为true,则继续执行,false中断执行,生成时默认false;

  • 应用场景:登陆验证之类的

postHandle:

  • 调用前提: preHandle返回true;

  • 调用时间: Controller方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作

  • 执行顺序: 链式Intercepter情况下,Intercepter按照声明的顺序倒着执行。

  • 备注: postHandle虽然post打头,但post、get方法都能处理

afterCompletion:

  • 调用前提:preHandle返回true

  • 调用时间:DispatcherServlet进行视图的渲染之后

  • 应用场景:多用于清理资源,统一日志处理,统一异常处理

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取session
        HttpSession session = request.getSession();
        //获取session中的用户
        UserDTO user = (UserDTO) session.getAttribute("user");
        //判断用户是否存在
        if(user == null){
            //不存在并;拦截
            response.setStatus(401);
            return false;
        }
        //存在,保存用户到TheadLocal放行
        UserHolder.saveUser(user);
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}

2.开启拦截器

WebMvcConfigurer

order:决定拦截器执行的顺序

初始值都为0,不设置按照添加顺序执行

添加后,最先执行的是order(0)

@Configuration
public class MVCConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(new LoginInterceptor())
               .excludePathPatterns("/user/code",
                       "/user/login",
                       "/shop/**",
                       "/upload/**",
                       "/shop-type/**",
                       "/shop/**",
                       "/blog/hot",
                       "/voucher/**",
                       "/user/me"
               ).order(1);}
}

2.拦截器类型(有待考证)

HandlerInterceptor类: 三个方法都必须继承

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
}

多个拦截器的执行顺序:

拦截器一二三

HandlerInterceptorAdapter类:可以选择性继承三个方法中的一个

public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {
     //选择需要的方法 
}  

3.拦截器和spring容器的先后执行顺序

拦截器一二三

4.过滤器和拦截器的区别

原文链接:https://blog.csdn.net/nigulasizp/article/details/125322507

1、实现原理不同 过滤器和拦截器底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。

2、使用范围不同 我们看到过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。 而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application、Swing等程序中。

3、触发时机不同 过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。

4、拦截的请求范围不同 过滤器Filter执行了两次,拦截器Interceptor只执行了一次。这是因为过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。

5、注入Bean情况不同 这是因为加载顺序导致的问题,拦截器加载的时间点在springcontext之前,而Bean又是由spring进行管理。(所以拦截器中注入不了Bean)

6、控制执行顺序不同 过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行。 拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行

Filter的执行顺序在Interceptor之前,具体的流程见下图
拦截器一二三

5.拦截器的原理

拦截器Interceptor 的拦截功能是基于Java的反射机制(动态代理)实现的。

原文地址:http://hzhcontrols.com/new-1239027.html