Spring拦截器实现及请求链路说明
1.拦截器与过滤器的区别
1.1 JavaWeb三大组件
“ javaWeb有三大组件,分别是:servlet,Filter,Listener
1.1.1 Servlet
广义:Servlet是一个运行在web服务器或者应用服务器上的一个应用程序,用来动态处理客户端请求的资源。
狭义:Servlet是一个继承了GenericServlet类的子类。该类中的service方法用来处理相关的资源请求。
1.1.2 Listener
在Servlet规范中定义了多种类型的监听器。主要是三种域对象的监听ServletContext,HttpSession,HttpRequest,根据其功能可以划分为两类
三个域对象的销毁与创建
ServletContextListener
HttpServletListener
ServletRequestListener
域对象中的属性的变化
ServletContextAttributeListener
HttpServletAttributeListener
ServletRequestAttributeListener
1.1.3 Filter
Filter和Servlet类似。Servlet用来处理请求,而Filter用来拦截和放行请求。
作用:
在执行请求之前执行一段代码
是否让客户端访问目标资源
调用目标资源以后执行一段代码(通过生命周期函数完成)
Filter存在四种拦截方式
REQUESR 默认值,代表直接访问某个servlet
ERROR 发生错误时进行跳转
INCLUDE 包含资源时执行filter
FORWARD 转发时执行filter
1.2 Spring拦截器
spring拦截器是spring Aop的一种应用,在不修改源码的情况下,执行一段代码,以增强现有方法。
实现方式:
通过实现HandlerInterceptor接口,重写内部的三个方法
preHandler。在访问Controller之前执行,可以用来拦截请求
postHandler。在视图跳转或数据返回之前执行(return之前)
afterCompletion。在视图加载完成或数据返回完成以后执行
1.3.Filter和Interceptor的区别
规范不同:Filter是Servlet规范中组件,在Servlet容器中生效,Interceptor是Spring框架支持的,在Spring上下文中生效。
作用范围不同:Servlet容器比Spring容器作用范围大
使用资源不同:Interceptor可以使用SpringIOC容器里面注入的Bean,Filter不可以使用注入的Bean。
粒度不同:过滤器范围更大,在拦截器外层对请求进行处理 适用系统级别的对所有API进行处理,如权限验证。
拦截器适合分模块,分业务的统一处理。
Filter是基于函数回调的,而Interceptor则是基于Java反射的。
Filter依赖于Servlet容器,而Interceptor不依赖于Servlet容器。
Filter对几乎所有的请求起作用,而Interceptor只能对action请求起作用。
Interceptor可以访问Action的上下文,值栈里的对象,而Filter不能。
在action的生命周期里,Interceptor可以被多次调用,而Filter只能在容器初始化时调用一次。
1.4过滤器和拦截器的执行步骤
过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。
拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。
切片 (Aspect) : 可以拿到方法的参数,但是却拿不到http请求和响应的对象
2.SpringBoot使用拦截器
“ SpringBoot对MVC进行了自动配置,当需要使用拦截器的时候,需要在WebMvcConfigurer实现类中添加自定义的拦截器,并定义拦截路径和排除路径
使用@Component注解 进行依赖注入
com.zhl.springbootservlet.config.CustomHandlerInterceptor
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class CustomHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandler:请求前调用");
/*返回False 则请求中断*/
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
log.info("postHandler:请求后调用");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
log.info("afterCompletion:请求调用完成后回调方法,即在视图渲染完成后回调");
}
}
拦截器需要注册到配置类中
com.zhl.springbootservlet.config.MyWebMvcConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
//老版本已废弃:public class MyWebMvcConfiguer extendx WebMvcConfigurerAdapter
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Resource
CustomHandlerInterceptor customHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*
* 注册拦截器 拦截规则
* 多个拦截器时 依次添加,执行顺序按添加顺序
* */
registry.addInterceptor(customHandlerInterceptor).addPathPatterns("/*");
}
}
访问测试:
E:\09_JAVACODES_X>curl localhost:8080/hello
Hello World
2020-12-18 11:30:40.261 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CustomFilter : customFilter 请求处理之前--doFilter方法之前过滤请求
......
2020-12-18 11:30:40.273 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CustomHandlerInterceptor : preHandler:请求前调用
......
2020-12-18 11:30:40.289 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CumtomListener : session 创建
......
2020-12-18 11:30:40.315 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CustomHandlerInterceptor : postHandler:请求后调用
2020-12-18 11:30:40.316 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CustomHandlerInterceptor : afterCompletion:请求调用完成后回调方法,即在视图渲染完成后回调
2020-12-18 11:30:40.318 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CustomFilter : customFilter 请求处理之后--doFilter方法之后处理响应
2020-12-18 11:30:40.319 INFO 15200 --- [nio-8080-exec-1] c.z.s.config.CumtomListener : request 销毁