美文网首页SpringBoot
SpringBoot HandlerInterceptor 拦截

SpringBoot HandlerInterceptor 拦截

作者: 当当一丢丢 | 来源:发表于2018-01-18 01:15 被阅读1107次

环境

  • SpringBoot 环境

相关

  • spring-boot在web层面使用了spring mvc的拦截器功能,并没有做其他处理,故我们只要熟悉mvc的拦截器,自然而然可以将拦截器加入到spring-boot上
  • 已知request 请求处理顺序,Filter -> HandlerInterceptor 拦截器 -> AOP
  • Filter 过滤器属于 Servlet 范畴的API, 与Spring 没什么关系
  • HandlerInterceptor 拦截器 属于Spring 的范畴
  • 只有经过 dispatchservlet 的请求,才会走拦截器chain,我们自定义的的servlet 请求是不会被拦截的
  • 但过滤器会拦截所有请求

拦截器提供更精细的控制-时间段区分

  • 在request被controller 响应之前,只有返回true 才会进入后续interceptor 和 controller
  • 在request被响应之后-dispatcherServlet进行视图渲染之前,可以在此处对Controller 处理后的ModelAndView对象进行处理
  • 视图渲染之后,用于资源清理

特点

我们不能通过修改拦截器修改request内容,但可以通过抛出异常(或者返回false)暂停request执行

案例

基础
Spring MVC 中拦截器顶层是 HandlerInterceptor, 它有3个方法

public interface HandlerInterceptor {

    //controller 方法执行前执行,当return TRUE 时进入下一个 拦截器 或直接进入 Controller 方法
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

    
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

通常情况下继承 HandlerInterceptorAdapter 抽象类 来实现自定义拦截器

public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {

    /**
     * This implementation always returns  true
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        return true; //硬编码为TRUE,自定义拦截器 可以覆盖
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
            //空实现
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
            //空实现
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }

}

AsyncHandlerInterceptor接口代码

public interface AsyncHandlerInterceptor extends HandlerInterceptor {

    /**
     * Called instead of {@code postHandle} and {@code afterCompletion}, when
     * the a handler is being executed concurrently.
     * <p>Implementations may use the provided request and response but should
     * avoid modifying them in ways that would conflict with the concurrent
     * execution of the handler. A typical use of this method would be to
     * clean up thread-local variables.
     * @param request the current request
     * @param response the current response
     * @param handler the handler (or {@link HandlerMethod}) that started async
     * execution, for type and/or instance examination
     * @throws Exception in case of errors
     */
    void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

}

  • HandlerInterceptorAdapter 是 适配器 模式的一种
    • 实现适配器模式有两种方式:继承 和 组合
  • 实现接口时,可以将某些接口方法写死,然后让继承类覆盖
  • AsyncHandlerInterceptor 接口只增添了一个接口,这种设计模式可以留意下

自定义拦截器

@Slf4j
public class MyHandlerInterceptor1 extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("handler interceptor1 preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("handler interceptor1 postHandle");
        //super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("handler interceptor1 afterComplete");
        //super.afterCompletion(request, response, handler, ex);
    }
}
@Slf4j
public class MyHandlerInterceptor2 extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("handler interceptor2 preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("handler interceptor2 postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("handler interceptor2 afterComplete");
    }
}

注册拦截器

@Configuration //标记为配置类,本质上是将该类纳入上下文从而执行addInterceptor动作,故@Component注解亦可
public class MyInterceptorConfigure extends WebMvcConfigurerAdapter {
    //继承WebMVCConfigureAdapter,并覆盖 addInterceptror 方法
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyHandlerInterceptor1());
        registry.addInterceptor(new MyHandlerInterceptor2()); //添加顺序决定了拦截顺序
        super.addInterceptors(registry);
    }
}

controller

@RestController
@RequestMapping("/interceptor")
public class MyInterceptorController {

    @RequestMapping("") //没有主method属性,表示接受任意method请求
    public String testIntercept(String param) {  //未加 @RequestParam() 同样也可绑定方法参数param 
        System.out.println("param: " + param);
        return param;
    }

}

运行结果

2018-01-17 01:16:50.993  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 preHandle
2018-01-17 01:16:50.993  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 preHandle
param: test
2018-01-17 01:16:51.029  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 postHandle
2018-01-17 01:16:51.030  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 postHandle
2018-01-17 01:16:51.032  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 afterComplete
2018-01-17 01:16:51.032  INFO 568 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 afterComplete

添加Aspect后的运行结果
Aspect 代码

@Component
@Aspect
@Slf4j
public class TestAspect {

    @Pointcut(("execution(public * com.lance.spring.controller.*.*(..))"))
    public void restPoint() {

    }

    @Before("restPoint()")
    public void before(JoinPoint joinPoint) {
        log.info("aspect before pointcut");
    }

    @After("restPoint()")
    public void after(JoinPoint joinPoint) {
        log.info("aspect after pointcut");
    }

    @Around("restPoint()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("aspect around before target method");
        joinPoint.proceed();
        log.info("aspect around after target method");
    }
}

结果

2018-01-17 01:19:42.860  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 preHandle
2018-01-17 01:19:42.860  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 preHandle
2018-01-17 01:19:42.889  INFO 6256 --- [           main] com.lance.spring.aop.TestAspect          : aspect around before target method
2018-01-17 01:19:42.889  INFO 6256 --- [           main] com.lance.spring.aop.TestAspect          : aspect before pointcut
param: test
2018-01-17 01:19:42.899  INFO 6256 --- [           main] com.lance.spring.aop.TestAspect          : aspect around after target method
2018-01-17 01:19:42.899  INFO 6256 --- [           main] com.lance.spring.aop.TestAspect          : aspect after pointcut
2018-01-17 01:19:42.915  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 postHandle
2018-01-17 01:19:42.916  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 postHandle
2018-01-17 01:19:42.916  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor2  : handler interceptor2 afterComplete
2018-01-17 01:19:42.916  INFO 6256 --- [           main] c.l.s.interceptor.MyHandlerInterceptor1  : handler interceptor1 afterComplete
参考:http://jinnianshilongnian.iteye.com/blog/1675504

相关文章

  • SpringBoot HandlerInterceptor 拦截

    环境 SpringBoot 环境 相关 spring-boot在web层面使用了spring mvc的拦截器功能,...

  • 配置拦截器(HandlerInterceptor)

    1. HandlerInterceptor 定义拦截器必须实现HandlerInterceptor接口. 这对所有...

  • SpringBoot之HandlerInterceptor拦截器

    简介 拦截器,最常用的登录拦截、权限校验、防重复提交、打印日志、出入参参数处理,可以说拦截器+解析器最佳拍档。 实...

  • SpringMVC--07拦截器

    一、通过实现HandlerInterceptor接口来定义拦截器 1、通过实现HandlerInterceptor...

  • Spring-mvc 中的Interceptor:

    Interceptor : 1.可以继承HandlerInterceptor 拦截 2.自定义拦截器 拦截器,拦截...

  • SpringMVC拦截器

    SpringMVC拦截器;全局拦截和局部拦截 在拦截类中实现HandlerInterceptor,中3个抽象方法 ...

  • Spring-boot 使用HandlerInterceptor

    一个最简单HandlerInterceptor实现如下 编写一个拦截器实现HandlerInterceptor接口...

  • 拦截器

    一 拦截器 定义拦截器,实现HandlerInterceptor接口 二 springMVC 拦截器配置 1 针对...

  • Spring15-拦截器

    定义拦截器 定义拦截器需要实现HandlerInterceptor 配置拦截器 注意:spring mvc的拦截器...

  • SpringMVC-拦截器

    SpringMVC提供了两种拦截:HandlerInterceptor和WebRequestInterceptor...

网友评论

    本文标题:SpringBoot HandlerInterceptor 拦截

    本文链接:https://www.haomeiwen.com/subject/itipoxtx.html