【转】Spring 之 Interceptor

2022-07-10  本文已影响0人  AlphaHinex

原文地址:https://wyiyi.github.io/amber/2022/07/01/interceptor/


description: "在 Spring Web MVC 中,拦截器(Interceptor)同 Servlet 中的过滤器(Filter)类似,都可以实现对用户的请求做出相应的处理。"
date: 2022.07.10 10:26
categories:
- Spring
tags: [Spring, Servlet, Java]
keywords: Web MVC, interceptor, filter


什么是拦截器

在 Spring Web MVC 中,拦截器(Interceptor)同 Servlet 中的过滤器(Filter) 类似,都可以实现对用户的请求做出相应的处理。

所有 HandlerMapping 的实现都支持处理程序拦截器,当想将特定功能应用于某些请求时很有用 —— 例如检查权限。
拦截器必须实现 org.springframework.web.servlet 包中 HandlerInterceptor 接口的三个方法,
这些方法能够提供足够的灵活性来进行各种预处理和后处理:

preHandle(..): Before the actual handler is run // 在实际 handler 之前运行

postHandle(..): After the handler is run // 在 handler 之后运行

afterCompletion(..): After the complete request has finished // 在整个请求完成后运行

preHandle 方法返回一个布尔值,可以用该方法中断或者继续执行链的处理。

【注意】:postHandle 对于 @ResponseBodyResponseEntity 方法的用处不大,因为这些方法的响应是在 HandlerAdapter 中和 postHandle 之前写入和提交的。
这意味着对响应进行任何更改都为时已晚,例如添加额外的请求头。
对于此类场景,您可以实现 ResponseBodyAdvice 并将其声明为 Controller Advice bean 或直接在 RequestMappingHandlerAdapter 上进行配置。

自定义拦截器

1、定义拦截器:监控请求时间

@Component
public class TimeTrackingInterceptor implements HandlerInterceptor {

    private static Logger log = LoggerFactory.getLogger(TimeTrackingInterceptor.class);
    private static final ThreadLocal<Long> logTimeThreadLocal = new NamedThreadLocal<>("ThreadLocal StartTime");

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long beginTime = System.currentTimeMillis();
        logTimeThreadLocal.set(beginTime);
        log.info(request.getRequestURI() + " 开始执行时间:" + beginTime);
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        long beginTime = logTimeThreadLocal.get();
        long endTime = System.currentTimeMillis();
        log.info(request.getRequestURI() + " 执行结束时间:" + endTime);
        log.info("耗时:" + (endTime - beginTime) + "ms");
    }
}

2、controller 类

@RestController
public class InterceptorController {

    @RequestMapping("/index")
    public Map<String,String> hello(Model model){
        Map<String,String> response=new HashMap<>();
        response.put("msg","hello");
        return response;
    }
}

配置拦截器

有关如何配置拦截器的示例,可参阅 MVC 配置部分中的拦截器

能够使 TimeTrackingInterceptor 拦截到 /index 生效,将 TimeTrackingInterceptor 注册拦截器配置中即可。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    private final TimeTrackingInterceptor timeTrackingInterceptor;

    public InterceptorConfig(TimeTrackingInterceptor timeTrackingInterceptor) {
        this.timeTrackingInterceptor = timeTrackingInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(timeTrackingInterceptor).addPathPatterns("/index");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/my/");
    }

}

启动应用,运行效果

启动后通过访问 http://127.0.0.1:8080/index ,发现已经拦截到请求,在控制台日志中打印了上述日志信息。

参考资料

上一篇 下一篇

猜你喜欢

热点阅读