spring aop(MethodInterceptor), springmvc (HandlerInterceptor), servlet Filter有什么区别?

2023-10-27

在spring web mvc中实现拦截功能时,有三种方式

1. 使用功能servlet filter

2. 使用springmvc 提供的 HandlerInterceptor

3. 使用spring core 提供的 MethodInterceptor(spring aop)

 

1. servlet的过滤器Filter

我们自己写的Filter类,Filter是Servlet规范的一部分,是Servlet容器(如Tomcat)实现的。

在spring boot下注册一个filter的三种方式(servlet、listener也是如此)

方式1:可以使用@WebFilter+@ServletComponentScan的方式

方式2:可以使用FilterRegistrationBean 进行API级别的注册,注意,在这种情况下可以对Filter order进行设置,而使用spring @Order注解是无效的

@Bean
public ServletRegistrationBean asyncServletServletRegistrationBean(){
    ServletRegistrationBean registrationBean =  new ServletRegistrationBean(new AsyncServlet(),"/");
    registrationBean.setName("MyAsyncServlet");
    registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return registrationBean;
}

方式3:创建一个类去实现 ServletContextInitializer 接口,并把它注册为一个 Bean,Spring Boot 会负责调用这个接口的 onStartup 方法。

@Bean
public ServletContextInitializer servletContextInitializer() {
    return servletContext -> {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        FilterRegistration.Dynamic registration = servletContext.addFilter("filter", filter);
        registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/");
    };
}

FilterRegistrationBean其实也是通过 ServletContextInitializer 来实现的,它实现了 ServletContextInitializer 接口

 

特点:

可以拿到原始的http请求和响应的信息,但是拿不到真正处理这个请求的方法的信息

存在的问题:

通过Filter只能拿到http的请求和响应,只能从请求和响应中获得一些参数。当前发过来的这个请求实际上真正是由哪个控制器的哪个方法来处理的,在Filter里面是不知道的,因为javax.servlet.Filter是J2EE规范中定义的,J2EE规范里面实际上并不知道与spring相关的任何内容。而我们的controller实际上是spring mvc定义的一套机制。如果你需要这些信息,那么就需要使用拦截器Interceptor

2. springmvc的拦截器Interceptor

public class TimeInterceptor implements HandlerInterceptor {}

在我们真正访问的Controller的某个方法被调用之前,会调用preHandler方法,在Controller的方法调用之后,会调用postHandler方法,如果你的controller中的方法抛出了异常,那么postHandler这个方法不会被调用。但无论controller中的方法是否抛出异常,afterCompletion方法都是会被调用的。

参考:spring mvc 处理流程源码解析 中关于HandlerInterceptor部分

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){}

最后一个参数,Object handler,这个是我真正用来处理这个请求的Controller的方法声明

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 {}

其中的Exception就是表示其是否发生了异常

日志信息

注意:其不仅会打印出发生错误的controller的方法的异常信息,而且其还会拦截BasicErrorController的error方法

interceptor不仅会拦截我们自己写的controller,spring提供的controller也会被拦截

特点:

Filter是servlet提供的,所以其不知道spring及springmvc的任何内容。

在Filter中是不知道这个请求是哪个控制器的哪个方法来处理的。如果你需要这个信息的话,那么需要使用springmvc的interceptor。

存在的问题:

拦截器可以拿到原始的http请求和响应的信息,也能拿到真正处理这个请求的方法的信息,但是其拿不到这个方法被调用的时候真正调用的参数的值

LOGGER.info(((HandlerMethod) handler).getBean().getClass().getName());
LOGGER.info(((HandlerMethod) handler).getMethod().getName());

通过handler虽然可以拿到处理此请求的controller和method,但是其没办法拿到这个method的真正的参数的值,这个handler只是那个方法的声明,但实际调用的时候,比如说调用getInfo的时候,我的这个id传的是多少,在拦截器里面用handler是拿不到的

为什么会这样呢? 从源码上看一下

org.springframework.web.servlet.DispatcherServlet#doDispatch

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   return;
}

这个方法就是调用我们拦截器的preHandler方法

如果我们的interceptor的preHandler返回的是false,就直接return掉不进行处理,否则执行目标controller的目标method

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

而方法参数的拼装是在ha.handle这个方法中完成的,所谓的方法参数的拼装就是把我请求中的参数组装成我们controller的method中所要的参数/对象

另外,在interceptor中可以指定指定的url才需要拦截

springmvc 异步interceptor

配置拦截器的时候,开启异步支持

@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    super.configureAsyncSupport(configurer);
}

如果想拦截异步处理的请求,那么要通过registerCallableInterceptors和registerDeferredResultInterceptors来单独注册拦截器

  • CallableProcessingInterceptor
  • DeferredResultProcessingInterceptor

设置好下面的两个方法:

setDefaultTimeout:因为是开了另一个线程,这个线程有可能阻塞,有可能死掉,没有响应了,那么在多长时间内我的http请求就返回回去,连接释放掉。

setTaskExecutor:在默认情况下,使用Callable,spring会使用内部一个简单的异步线程池来进行处理。这个简单的异步线程池并不是真正意义上的池,其不会重用线程,而是每一次被调用的时候,都会新建一个线程。通过这个方法可以设置一个可重用的线程池。

3. spring aop

在spring中,Advice的实现接口就是Interceptor

注意,Advice和Interceptor都是在org.aopalliance包下,并非在spring包下,为spring引入的外部依赖

Interceptor接口在spring中的实现类MethodInterceptor,通过before, after, afterReturing, afterThrowing等增强器来对目标方法进行增强

spring aop源码解析参考:spring aop源码解析1: 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator

特点:

可以拿到方法被调用的时候真正调用的参数的值

存在的问题:

但是拿不到原始的http请求和响应的信息

4. 拦截起作用的顺序

  • Filter最先其作用

  • 之后是Interceptor

  • 再之后才是Aspect

  • 之后才会进入到Controller中去

 

可以看到springmvc中的拦截器是用来拦截请求的,在MethodInterceptor之前执行

而MethodInterceptor是spring AOP项目中的拦截器,它拦截的目标是方法,即使其不是Controller中的请求方法。

参考:SpringMVC项目中,什么情况在控制层使用的AOP,什么情况使用拦截器?

“HandlerInterceptor和servlet的Filter比较相似,是一个链式的处理模式,每个请求都会在这个链下跑一遍,实际上很多请求我们是不想去处理的,如果在方法里判断显得很不spring.而自己用AOP实现,一切皆可配置,不需要的方法不去拦截(配合annotation使用)”

 

当Controller中抛出异常时

  • 最先捕获到异常的是Aspect

  • 如果声明了ControllerAdvice,那么其会接收到的Aspect未处理的异常

  • 如果ControllerAdvice也不处理,那么就会继续向上抛,直到最后抛出到tomcat中

总结

总结来说:spring MethodInterceptor与springmvc HandlerInterceptor在功能上有区别,springmvc interceptor是拦截请求,而spring interceptor更为灵活

除了spring提供的拦截功能外,还有Servlet本身提供的Filter也可以实现拦截功能,在springmvc下使用Filter会拦截所有请求,可以使用其做全局的拦截。

另外,这三点在获取目标controller的目标method,以及获取目标方法的请求参数的能力上,也是有区别的

拦截方式 特点
servlet的过滤器Filter 可以拿到原始的http请求和响应的信息,但是拿不到真正处理这个请求的方法的信息
springmvc的interceptor 在Filter中是不知道这个请求是哪个控制器的哪个方法来处理的。如果你需要这个信息的话,那么需要使用springmvc的interceptor。 拦截器可以拿到原始的http请求和响应的信息,也能拿到真正处理这个请求的方法的信息,但是其拿不到这个方法被调用的时候真正调用的参数的值
spring的切片Aspect 可以拿到方法被调用的时候真正调用的参数的值,但是拿不到原始的http请求和响应的信息
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring aop(MethodInterceptor), springmvc (HandlerInterceptor), servlet Filter有什么区别? 的相关文章

  • Day31——单个拦截器中三个方法的执行顺序以及时机

    一 回顾 前面拦截器简介用实现HandlerInterceptor接口实现了自定义拦截器 可以知道它有三个需要实现的方法 分别是preHandle postHandle afterCompletion 二 知识储备 2 1 单个拦截器中三个
  • log4j:WARN No appenders could be found for logger 问题解决

    在springmvc的web项目中常常会在tomcat启动的时候出现这种提示 log4j WARN No appenders could be found for logger org springframework web context
  • Spring MVC中如何进行转发和重定向呢?

    转自 Spring MVC中如何进行转发和重定向呢 重定向 我们将用户的定向到另一个视图 jsp 中处理 此操作是一个客户端行为 类似与url的链接操作 转发 将用户的请求转发到另一个视图或controller处理 此操作是一个服务器端行为
  • spring mvc配置cas客户端

    1 在WEB INF lib中导入cas jar包 点击打开链接 2 导入证书 1 将证书server cer文件拷贝至业务系统所在服务器上的某路径下 如c盘根目录 在cmd命令界面切换至证书所在路径 执行以下命令 jdk路径自行修改 并信
  • SSM小技巧(一)、Controller中互相调用session中存储的内容

    首先 你需要在一个Controller中往session中存内容 取的名字必须含有大写字母 虽然博主也不清楚为什么 如果有知道的人请一定要通知博主 博主将感激不尽 Controller SessionAttributes Save 将Mod
  • Spring MVC教程第一篇

    转自 Spring MVC教程第一篇 Spring MVC是Java平台下的一个框架 Spring MVC是一个开源框架 它用于开发Java Web应用程序 Spring框架由Rod Johnson编写 在2003年6月采用Apache 2
  • springmvc有哪几种请求参数的方式呢?

    转自 springmvc有哪几种请求参数的方式呢 传送参数至后台 是每个系统都必须面对的事实 因为系统就是一个实现人机交互的工具 那么Spring MVC中如何在后台获取参数呢 下文将一一道来 如下所示 方式一 在Controller的形参
  • SpringMVC DispatcherServlet源码(2) 扫描Controller创建HandlerMapping流程

    Spring MVC向容器注册一个RequestMappingInfoHandlerMapping组件 他会扫描容器中的Controller组件 创建RequestMappingInfo并注册HandlerMethod映射关系 本文将阅读S
  • 7、Shiro+SpringMVC+oracle+maven整合

    本章节主要介绍Shiro SpringMVC oracle maven整合 并实现shiro的身份验证和授权 建表并插入数据 1 用户表 CREATETABLEusers Table user id number 10 primarykey
  • Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案

    http blog csdn net boonya article details 70157820 Mybatis与JDBC批量插入MySQL数据库性能测试 Author boonya Date 2017 04 13 1 背景 系统中需要
  • springmvc控制器的三种实现方式

    方式一 实现Controller接口 public class Test01 implements Controller Override public ModelAndView handleRequest HttpServletReque
  • springmvc中操作json,配置FastJson

    目前网络上传递数据大部分都是json和xml 但是xml使用的很少了 这里主要介绍json 一般来说json常用的场景是提供外部接口 请求内使用request域就足够了 springmvc对于json的支持 上图 1 请求json方式分析
  • Springmvc 学习心得

    1 三层架构的介绍和mvc的设计模式 Springmvc的特点 清晰的角色划分 每个功能模块对应一个组件 1 前端控制器 DispatchServlet 2 处理器映射器 HanderMapping 根据 requestMapping 找到
  • Spring MVC如何进行数据校验呢?

    转自 Spring MVC如何进行数据校验呢 在web开发中 我们需要保证用户输入的合法性 那么SpringMVC中如何保证web 应用的合法性呢 下文将一一道来 如下所示 下文只讲述SpringMVC后端的验证方法 前端验证 由用户自身采
  • springboot之乐观锁和悲观锁

    适用场景 悲观锁 比较适合写入操作比较频繁的场景 如果出现大量的读取操作 每次读取的时候都会进行加锁 这样会增加大量的锁的开销 降低了系统的吞吐量 乐观锁 比较适合读取操作比较频繁的场景 如果出现大量的写入操作 数据发生冲突的可能性就会增大
  • Spring MVC视图解析器简介说明

    转自 Spring MVC视图解析器简介说明 Spring MVC视图解析器简介说明 下文讲述 Spring MVC视图 的相关说明 如下所示 Spring 视图解析器 Spring视图解析器用于对Spring中的视图进行解析 如下配置所示
  • springmvc / /* /img/**等问题

    在配置springmvc的前端控制器 DispatcherServlet的时候有三种配置方式 action 访问以 action结尾 由DispatcherServlet进行解析 第二种 所以访问的地址都由DispatcherServlet
  • spring mvc 中对静态资源的访问配置

    在web xml中配置spring mc servlet 对url pattern设置时 排除在spring的servlet之外
  • dubbo zookeeper spring mvc简单整合的工程例子demo

    该demo只是简单的集成 包括了5个工程 都是maven结构的 如下图所示 服务端 dubbo demo server api 服务接口定义工程 dubbo demo server biz 服务接口实现工程 web dubbo server
  • Vue传递数据到后台SpringMVC接收解析返回

    最近在自学vue 开始以为跟angular大同小异 但是真正使用的时候发现还是很多不一样的地方 可能是因为刚刚开始理解的还不够深入O O 下面说说前端jsp怎么和后台交互 后台使用的是springMvc框架 html部分 div table

随机推荐