Spring Boot中使用拦截器

Spring Boot中使用拦截器

13.1)应用场景:

拦截器是 AOP 的一种实现,专门拦截对动态资源的后台请求,即拦截对控制层的请 求。使用场景比较多的是判断用户是否有权限请求后台,更拔高一层的使用场景也有,比如拦截器可以 结合 websocket 一起使用,用来拦截 websocket 请求,然后做相应的处理等等。拦截器不会拦截静态 资源,Spring Boot 的默认静态目录为 resources/static,该目录下的静态页面、js、css、图片等等, 不会被拦截.

13.2定义拦截器

定义拦截器,只需要实现 HandlerInterceptor 接口, 该接口中有三个方法:

preHandle(……) 、 postHandle(……) 和 afterCompletion(……) 。

preHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某

个方法,且在这个方法执行之前。所以 preHandle(……) 方法可以决定是否将请求放行,这是通

过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。

postHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某

个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。所以在这个方法中有

个 ModelAndView 参数,可以在此做一些修改动作。

afterCompletion(……) 方法:顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执

行,这时做一些资源的清理工作,这个方法只有在 preHandle(……) 被成功执行后并且返回 true

才会被执行。

13.2.1)自定义拦截类实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
    private Logger logger = LoggerFactory.getLogger(MyInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        logger.info("方法{}被拦截", methodName);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.info("方法被执行,但是视图还未渲染");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        logger.info("方法执行完毕,进行资源清理");
    }
}
13.2.2)实现WebMvcConfigurer接口进行拦截配置

实现WebMvcConfigurer的这种配置会自动过滤静态资源;

@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}

省略controller类

测试结果

10:52:16.316 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法test被拦截
10:52:16.344 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法被执行,但是视图还未渲染
10:52:16.344 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法执行完毕,进行资源清理

定义哪些不用拦截

取消拦截操作

如果我要拦截所有 /admin 开头的 url 请求的话,需要在拦截器配置中添加这个前缀,但是 在实际项目中,可能会有这种场景出现:某个请求也是 /admin 开头的,但是不能拦截,比如 /admin/login 等等

解决方案:

1.使用excludePathPatterns("/adminUser/login")
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/adminUser/login");
    }
2.可以定义一个注解

该注解专门用来取消拦截操作,如果某个 Controller 中的方法我们 不需要拦截掉,即可在该方法上加上我们自定义的注解即可,下面先定义一个注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UnInterception {
}
测试
controller类
@RestController
@RequestMapping("/intercept")
public class IntercepController {

    @UnInterception
    @RequestMapping("/hello")
    public String test() {
        return "success";
    }
interceptor拦截类
   @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        if (method.getAnnotation(UnInterception.class)!=null) {
            logger.info("方法{}不被拦截", methodName);
            return true;
        }
        logger.info("方法{}被拦截", methodName);
        return false;
    }

访问 http://localhost:8080/intercept/hello

结果

11:34:24.648 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法test不被拦截
11:34:24.676 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法被执行,但是视图还未渲染
11:34:24.679 [http-nio-8080-exec-1] INFO  c.e.h.interceptors.MyInterceptor - 方法执行完毕,进行资源清理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值