Filter

新建 TimeFilter

@Component
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("time filter init");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("time filter start");
long startTime = System.currentTimeMillis(); filterChain.doFilter(servletRequest, servletResponse); long endTime = System.currentTimeMillis();
System.out.println("time filter consume " + (endTime - startTime) + " ms");
System.out.println("time filter end");
} @Override
public void destroy() {
System.out.println("time filter init");
}
}

启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom

可以在控制台输出如下结果:

time filter start

name: tom

time filter consume 3 ms

time filter end

可以看到,filter 先执行,再到真正执行 HelloController.sayHello() 方法。

通过 TimeFilter.doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 方法的参数可以看出,我们只能得到原始的 request 和 response对象,不能得到这个请求被哪个 Controller 以及哪个方法处理了,使用Interceptor 就可以获得这些信息。

Interceptor

新建 TimeInterceptor

@Component
public class TimeInterceptor extends HandlerInterceptorAdapter { private final NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("startTimeThreadLocal"); @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("time interceptor preHandle"); HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取处理当前请求的 handler 信息
System.out.println("handler 类:" + handlerMethod.getBeanType().getName());
System.out.println("handler 方法:" + handlerMethod.getMethod().getName()); MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
for (MethodParameter methodParameter : methodParameters) {
String parameterName = methodParameter.getParameterName();
// 只能获取参数的名称,不能获取到参数的值
//System.out.println("parameterName: " + parameterName);
} // 把当前时间放入 threadLocal
startTimeThreadLocal.set(System.currentTimeMillis()); return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("time interceptor postHandle");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 从 threadLocal 取出刚才存入的 startTime
Long startTime = startTimeThreadLocal.get();
long endTime = System.currentTimeMillis(); System.out.println("time interceptor consume " + (endTime - startTime) + " ms"); System.out.println("time interceptor afterCompletion");
}
}

注册 TimeInterceptor

把 TimeInterceptor 注入 spring 容器

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter { @Autowired
private TimeInterceptor timeInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(timeInterceptor);
}
}

启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom

可以在控制台输出如下结果:

time filter start
time interceptor preHandle
handler 类:com.nextyu.demo.web.controller.HelloController
handler 方法:sayHello
name: tom
time interceptor postHandle
time interceptor consume 40 ms
time interceptor afterCompletion
time filter consume 51 ms
time filter end

可以看到,filter 先于 interceptor 执行,再到真正执行 HelloController.sayHello() 方法。通过 interceptor 方法上的 handler 参数,我们就可以得到这个请求被哪个 Controller 以及哪个方法处理了。但是不能直接获取到这个方法上的参数值(在这里就是 HelloController.sayHello(String name) 方法参数 name 的值),通过 Aspect 就可以获取到。

Aspcet

新建 TimeAspect

@Aspect
@Component
public class TimeAspect { @Around("execution(* com.nextyu.demo.web.controller.*.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); Object[] args = pjp.getArgs();
for (Object arg : args) {
System.out.println("arg is " + arg);
} long startTime = System.currentTimeMillis(); Object object = pjp.proceed(); long endTime = System.currentTimeMillis();
System.out.println("time aspect consume " + (endTime - startTime) + " ms"); System.out.println("time aspect end"); return object;
} }

启动服务器,在浏览器输入:http://localhost:8080/hello?name=tom

可以在控制台输出如下结果:

time filter start
time interceptor preHandle
handler 类:com.nextyu.demo.web.controller.HelloController
handler 方法:sayHello
time aspect start
arg is tom
name: tom
time aspect consume 0 ms
time aspect end
time interceptor postHandle
time interceptor consume 2 ms
time interceptor afterCompletion
time filter consume 4 ms
time filter end

可以看到,filter 先执行,再到 interceptor 执行,再到 aspect 执行,再到真正执行 HelloController.sayHello() 方法。

我们也获取到了 HelloController.sayHello(String name) 方法参数 name 的值

请求拦截过程图

graph TD
httprequest-->filter
filter-->interceptor
interceptor-->aspect
aspect-->controller

spring里的三大拦截器的更多相关文章

  1. Spring AOP原理及拦截器

    原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...

  2. Spring Boot2(七):拦截器和过滤器

    一.前言 过滤器和拦截器两者都具有AOP的切面思想,关于aop切面,可以看上一篇文章.过滤器filter和拦截器interceptor都属于面向切面编程的具体实现. 二.过滤器 过滤器工作原理 从上图 ...

  3. spring boot 过滤器、拦截器的区别与使用

    原文:https://blog.csdn.net/heweimingming/article/details/79993591 拦截器与过滤器的区别: 1.过滤器和拦截器触发时机不一样,过滤器是在请求 ...

  4. spring mvc中的拦截器小结 .

    在spring mvc中,拦截器其实比较简单了,下面简单小结并demo下. preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Control ...

  5. spring boot 实现mybatis拦截器

    spring boot 实现mybatis拦截器 项目是个报表系统,服务端是简单的Java web架构,直接在请求参数里面加了个query id参数,就是mybatis mapper的query id ...

  6. Spring的一种拦截器SimpleUrlHandlerMapping

    spring的一种拦截器,用于在XML文件中配置以拦截url,它是以map映射的方式进行拦截.映射是从前台urls到具体后台的beans.同时支持到bean实例和bean名称的映射,后者要求非单实例控 ...

  7. Spring MVC中的拦截器/过滤器HandlerInterceptorAdapter的使用

    一般情况下,对来自浏览器的请求的拦截,是利用Filter实现的 而在Spring中,基于Filter这种方式可以实现Bean预处理.后处理. 比如注入FilterRegistrationBean,然后 ...

  8. spring boot中注册拦截器

    拦截器是动态拦截Action调用的对象.它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重 ...

  9. Spring Mvc 的自定义拦截器

     spring mvc的拦截器 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户 ...

随机推荐

  1. QM3_Statistics Concepts and Market Returns

    Basic Concepts Terms Descriptive Statistics Describes the important aspects of large data sets. 统计 概 ...

  2. 【最小生成树】UVA1494Qin Shi Huang's National Road System秦始皇修路

    Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven ki ...

  3. 记录遭遇挖矿程序kthrotlds的失败处理经历

    1 发现问题 在腾讯云上购买了一个centos7的服务器,平时用来练手,偶尔也安装一些程序进行测试,上面安装了mysql和redis,前段时间数据库经常掉线,连不上,到腾讯云后台进行查看,通过服务器实 ...

  4. 兄弟俩畅游Tomcat城市的SpringMVC科技园区

    Tomcat城市 Tomcat这座城市的历史相当悠久了,经历过几次大的变迁后,呈现出非常明显的地域特征. 从城市往西走,过了城乡结合部以后,可以说是满目疮痍.一片破败,这就是Servlet地区,这座城 ...

  5. Linux学习_012_Centos 6.8 安装 Netcat

    测试中,需要通过 Netcat 发送数据. 配置环境:CentOS 6.8 1.下载安装包到指定目录,例如本博主的是:/opt/software/ wget https://sourceforge.n ...

  6. 从壹开始前后端 [vue后台] 之一 || 权限后台系统 1.0 正式上线

    缘起 哈喽各位小伙伴周三好,春节已经过去好多天了,群里小伙伴也各种催搞了,新年也接了新项目,比较忙,不过还是终于赶上这个二月的尾巴写了这篇文章,也把 vue 权限后台上线了(项目地址:http://1 ...

  7. pandas和spark的dataframe互转

    pandas的dataframe转spark的dataframe from pyspark.sql import SparkSession # 初始化spark会话 spark = SparkSess ...

  8. entity cannot be tracked

    背景:EF Core项目中使用InMemory作为数据库提供程序,编写单元测试. 报错:“The instance of entity type 'Movie' cannot be tracked b ...

  9. flex 布局实现固定头部和底部,中间滚动布局

    关键词:display: flex,flex: 1,  overflow-y: scroll; 实现:head 和footer 固定,中间body多了滚动,少了撑满: head和footer宽度根据内 ...

  10. U盘制作微pe工具箱(实战)

    分享人:广州华软 浩言 前言 相信大家平时生活中还是工作上使用电脑的时间还是比较多的,有时候电脑出现故障,比如系统文件损坏,没办法正常开机,或者是开机密码忘了,想要重装系统等,下面我推荐一个U盘启动项 ...