SpringBoot 集成拦截器

一、拦截器简介

拦截器是 AOP 的一种实现,专门拦截对动态资源的后台请求,即拦截对 controller 层的请求拦截器不会拦截静态资源,Spring Boot 的默认静态目录为 resources/static,该目录下的静态页面、JS、CSS、图片等不会被拦截

1、拦截器使用场景

在Spring Boot中使用拦截器,可在以下情况下执行操作:

1)在将请求发送到控制器之前;
2)在将响应发送给客户端之前;

例如,使用拦截器在将请求发送到控制器之前添加请求标头,并在将响应发送到客户端之前添加响应标头。

常见的使用场景包括判断用户是否有权限请求后台,再高级的使用场景,比如拦截器可以结合 WebSocket 一起使用,用来拦截 WebSocket 请求,并做相应的处理等等。

2、过滤器和拦截器的区别

在这里插入图片描述
(1)过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入 servlet 之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
(2)拦截器可以获取 IOC 容器中的各个 bean,而过滤器就不行,因为拦截器是 spring 提供并管理的,spring 的功能可以被拦截器使用,在拦截器里注入一个 service,可以调用业务逻辑。而过滤器是 JavaEE 标准,只需依赖 servlet api ,不需要依赖 spring。
(3)过滤器的实现基于回调函数,而拦截器(代理模式)的实现基于反射。
(4)Filter 是依赖于 Servlet 容器,属于 Servlet 规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
(5)Filter 的执行由 Servlet 容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行
(6)Filter 的生命周期由 Servlet 容器管理,而拦截器则可以通过 IoC 容器来管理,因此可以通过注入等方式来获取其他 Bean 的实例,因此使用会更方便
(7)过滤器可以修改 request,而拦截器不能过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
在这里插入图片描述

过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。

拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。

切片(Aspect): 可以拿到方法的参数,但是却拿不到http请求和响应的对象。
在这里插入图片描述

二、SpringBoot 使用拦截器——登录验证

使用拦截器很简单,只需要两步即可:定义拦截器和配置拦截器。

1、定义拦截器

定义拦截器,只需要实现 HandlerInterceptor 接口HandlerInterceptor 接口是所有自定义拦截器或者 Spring Boot 提供的拦截器的鼻祖,该接口中有三个方法,分别为 preHandle、postHandle 和 afterCompletion 。

(1)preHandle

该方法的执行时机是,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在这个方法执行之前。所以 preHandle 方法可以决定是否将请求放行,这是通过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。

(2)postHandle

该方法的执行时机是,当某个 URL 已经匹配到对应的 Controller 中的某个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。所以在这个方法中有个 ModelAndView 参数,可以在此做一些修改动作。

(3)afterCompletion

顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执行,这时做一些资源的清理工作,这个方法只有在 preHandle 被成功执行后并且返回 true 才会被执行。

登录验证拦截器定义如下:

public class UserLoginInterceptor implements HandlerInterceptor {
    
    

    /***
     * 在请求处理之前进行调用(Controller方法调用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        System.out.println("执行了拦截器的preHandle方法");
        try {
    
    
        	// 查看session
        	// 注意 getSession 的参数设置为 false,避免 Session 为 null 再新建
            HttpSession session = request.getSession(false);
            //统一拦截(查询当前session是否存在user)(这里user会在每次登录成功后,写入session)
            User user = (User) session.getAttribute("user");
            if (user != null) {
    
    
                return true;
            }
            // 不存在则重新登陆
            response.sendRedirect(request.getContextPath() + "login");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return false;
        //如果设置为false时,被请求时,拦截器执行到此处将不会继续操作
        //如果设置为true时,请求将会继续执行后面的操作
    }

    /***
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("执行了拦截器的postHandle方法");
    }

    /***
     * 整个请求结束之后被调用,也就是在DispatchServlet渲染了对应的视图之后执行(主要用于进行资源清理工作)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        System.out.println("执行了拦截器的afterCompletion方法");
    }
}

preHandle 在 Controller 之前执行,因此拦截器的功能主要就是在这个部分实现:检查 session 中是否有 user 对象存在;如果存在,就返回true,那么Controller就会继续后面的操作;如果不存在,就会重定向到登录界面。

2、配置拦截器

实现 WebMvcConfigurer 接口,然后重写 addInterceptors 方法来注册拦截器。

在 Spring Boot 2.0 之前,我们都是直接继承 WebMvcConfigurerAdapter 类,然后重写 addInterceptors 方法来实现拦截器的配置。但是在 Spring Boot 2.0 之后,该方法已经被废弃了(当然,也可以继续用),取而代之的是 WebMvcConfigurationSupport 方法。但是 WebMvcConfigurationSupport 又会导致默认的静态资源被拦截,这就需要我们手动将静态资源放开

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
        //注册TestInterceptor拦截器
        InterceptorRegistration registration = registry.addInterceptor(new UserLoginInterceptor());
        registration.addPathPatterns("/**"); 	//所有路径都被拦截
        registration.excludePathPatterns(    	//添加不拦截路径
                "/login",                    	//登录路径
                "/**/*.html",                	//html静态资源
                "/**/*.js",                  	//js静态资源
                "/**/*.css"                  	//css静态资源
        );
    }
}

将拦截器注册到了拦截器列表中,并且指明了拦截哪些访问路径,不拦截哪些访问路径,不拦截哪些资源文件;最后再以 @Configuration 注解将配置注入。

猜你喜欢

转载自blog.csdn.net/IT__learning/article/details/120200356