拦截器笔记

拦截器

Spring MVC中所有的拦截器都实现/继承自HandlerInterceptor接口。自定义拦截器,就需要实现/继承HandlerInterceptor接口或其子接口/实现类。下图为Spring MVC中拦截器的类图。
拦截器的类图
HandlerInterceptor接口的源码:

public interface HandlerInterceptor {

	//处理器执行前被调用
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
	//处理器执行后、视图渲染前被调用
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
	//视图渲染完成后调用
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

拦截器的执行流程:
拦截器的执行流程
新建一个LogInterceptor类并实现HandlerInterceptor接口:

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

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

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

新建一个WebConfigurer类并实现WebMvcConfigurer接口,用于注册自定义的拦截器:

public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    private LogInterceptor logInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logInterceptor);
    }

在HelloController类的hello方法中添加一条日志打印代码:

public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        log.info("hello");
        return "Hello Spring Boot";
    }

}

启动工程,访问http://localhost:8080/hello,会在控制台看到如下输出:
在这里插入图片描述

多个拦截器的执行顺序:
多个拦截器的执行顺序
preHandle方法与afterCompletion方法总是成对出现的,一个拦截器的preHandle方法被调用后,afterCompletion方法必然也会被调用。
再创建一个拦截器,用来记录程序执行消耗的时间,并创建一个TimeInterceptor类,同样实现HandlerInterceptor接口,代码如下:

public class TimeInterceptor implements HandlerInterceptor {

    private final ThreadLocal<LocalTime> threadLocalStart = new ThreadLocal<>();
    private final ThreadLocal<LocalTime> threadLocalEnd = new ThreadLocal<>();
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");

    // 记录开始时间
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        LocalTime startTime = LocalTime.now();
        threadLocalStart.set(startTime);
        log.info("开始时间:{}", startTime.format(formatter));
        return true;
    }

    // 记录结束时间
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        LocalTime endTime = LocalTime.now();
        threadLocalEnd.set(endTime);
        log.info("结束时间:{}", endTime.format(formatter));
    }

    // 计算接口执行时间
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        LocalTime startTime = threadLocalStart.get();
        LocalTime endTime = threadLocalEnd.get();
        log.info("接口执行时间:{} 毫秒", Duration.between(startTime, endTime).getNano() / 1000000);
    }
}

然后将TimeInterceptor类配置到WebConfigurer类中,完成拦截器的注册。

@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    private LogInterceptor logInterceptor;
    @Autowired
    private TimeInterceptor timeInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(logInterceptor).addPathPatterns("/*");
        registry.addInterceptor(timeInterceptor);
    }
}

启动工程并再次访问hello接口,我们会看到控制台输出如下日志:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值