Spring MVC 的拦截器
核心接口
- HandlerInteceptor
• boolean preHandle()
• void postHandle()
• void afterCompletion()
拦截器主要以HandlerInteceptor接口实现,在这个接口当中,有这三个方法。preHandle方法,我在方法处理前,做预处理,会返回一个boolean 类型的返回值,当我返回true的时候,进行接下来的方法处理,如果是false,终止方法的处理;在方法执行之后,会调用postHandle和afterCompletion,差异为是在方法视图呈现前后的差别,一个在前,一个在后面。
Spring MVC 的拦截器
针对 @ResponseBody 和 ResponseEntity 的情况
- ResponseBodyAdvice
针对 @ResponseBody 返回 ResponseEntity 的情况,提供了一个ResponseBodyAdvice
针对异步请求的接口
在JAVA平台,实现异步调用的角色有如下三个角色:调用者,取货凭证,真实数据 异步调用就是:一个调用者在调用耗时操作,不能立即返回数据时,先返回一个取货凭证.然后在过一断时间后凭取货凭证来获取真正的数据.
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率 只有一个马桶 很多人上厕所 要排队 这叫同步迅雷一次可以下载很多东西 这叫异步
- AsyncHandlerInterceptor
• void afterConcurrentHandlingStarted()
如果是一个异步请求,它提供了AsyncHandlerInterceptor接口,有一个在方法并发执行开始之后,做一些方法的处理。如果是一个异步方法,postHandle和afterCompletion操作。
拦截器的配置方式
常规方法
- WebMvcConfigurer.addInterceptors()
Spring Boot 中的配置
• 创建一个带 @Configuration 的 WebMvcConfigurer 配置类
• 不能带 @EnableWebMvc(想彻底自己控制 MVC 配置除外)
配置拦截器,用的是WebMvcConfigurer里面的addInterceptors方法,我们可以自己去实现,并做interceptor的添加的动作。在springboot中,我们只需要自己去创建一个带 @Configuration 注解的的类,让这个类实现WebMvcConfigurer 配置类,我自己去实现里面的方法,如果不想彻底自己控制 MVC 配置,请不要加 @EnableWebMvc注解,只需要加 @Configuration注解。
具体实例
目录结构如下:
需要修改的代码:
@Slf4j
public class PerformanceInteceptor implements HandlerInterceptor {
private ThreadLocal<StopWatch> stopWatch = new ThreadLocal<>();//StopWatch:springmvc提供的记录运行时间的工具类
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
StopWatch sw = new StopWatch();
stopWatch.set(sw);
sw.start(); //做一个启动 开始记录时间
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
stopWatch.get().stop();//在我方法调用完成之后,停止,记录一个时间点
stopWatch.get().start();//记录后面整个呈现的耗时
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
StopWatch sw = stopWatch.get();
sw.stop();
String method = handler.getClass().getSimpleName();
if (handler instanceof HandlerMethod) {
String beanType = ((HandlerMethod) handler).getBeanType().getName();
String methodName = ((HandlerMethod) handler).getMethod().getName();
method = beanType + "." + methodName;
} //通过处理 取得了这个springmvc请求是哪个URL的请求,具体用的是什么方法,返回的http响应码,和异常,和总耗时
log.info("{};{};{};{};{}ms;{}ms;{}ms", request.getRequestURI(), method,
response.getStatus(), ex == null ? "-" : ex.getClass().getSimpleName(),
sw.getTotalTimeMillis(), sw.getTotalTimeMillis() - sw.getLastTaskTimeMillis(),
sw.getLastTaskTimeMillis());
stopWatch.remove();
}
}
@SpringBootApplication
@EnableJpaRepositories
@EnableCaching
public class WaiterServiceApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(WaiterServiceApplication.class, args);
}
@Override
public void addInterceptors(InterceptorRegistry registry) { //重写addInterceptors方法
registry.addInterceptor(new PerformanceInteceptor())
.addPathPatterns("/coffee/**").addPathPatterns("/order/**"); //拦截/coffee/和/order/的URL调用
}
@Bean
public Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonBuilderCustomizer() {
return builder -> {
builder.indentOutput(true); //json做一个缩进处理
builder.timeZone(TimeZone.getTimeZone("Asia/Shanghai"));//整个日期做格式化时候 用的时区
};
}
}
测试效果
使用URL查询咖啡1:
控制台输出为:
我们可以看到,控制台打印出一系列的数据。
来源:CSDN
作者:L# S@
链接:https://blog.csdn.net/weixin_43790623/article/details/103654374