了解 Spring MVC 的切入点

…衆ロ難τιáo~ 提交于 2019-12-22 18:05:10

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:
在这里插入图片描述

控制台输出为:
在这里插入图片描述
我们可以看到,控制台打印出一系列的数据。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!