SpringBoot/Spring-拦截机制
SpringBoot的拦截机制不是特有的,他和Spring是一致的,都可以使用下面三种技术来实现拦截机制:
-
过滤器(Filter)
-
拦截器(Interceptor)
-
切片(Aspect)
本质上他们都是AOP的体现。
1. 过滤器和拦截器的区别
- 过滤器可以修改request(继承HttpServletRequestWrapper重新装饰request),而拦截器不能。
- 过滤器需要在Servlet容器中实现,而拦截器是在Spring容器下实现的。
- 拦截器可以调用IOC容器中的各种依赖,而过滤器不能。
- 过滤器只能在请求的前后使用,而拦截器可以具体到某个(Controller)方法。
过滤器就是筛选出想要的东西,比如request那部分数据。而拦截器在安全控制方面用的比较多,比如终止一些流程。
请求先走过滤器,再走拦截器!
Filter过滤器需要在web.xml中配置,依赖于Servlet;
Interceptor拦截器需要在SpringMvc中配置,依赖于框架;
2. 过滤器详解
过滤器在过滤器链中的顺序与它在web.xml中的配置有关。在doFilter()方法中,chain.doFilter()前一般对request执行过滤操作,chain.doFilter一般对response执行过滤操作。
Filter的生命周期
-
Filter的创建和销毁由web服务器负责,web应用启动的时候,web服务器将创建Filter实例,并调用其init方法,完成对象的初始化功能,filter只会创建一次,init方法也只会执行一次。
-
web容器调用destroy方法销毁Filter。destroy方法在Filter的生命周期中仅执行一次。在destroy方法中,可以释放过滤器使用的资源。
FilterConfig接口
用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了 filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
- String getFilterName():得到filter的名称。
- String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null。
- Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
- public ServletContext getServletContext():返回Servlet上下文对象的引用。
CORS跨域资源共享过滤器:
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
3. 拦截器
@Component
public class LogInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
- preHandle在被拦截方法执行之前回调。
- postHandle方法在被拦截方法执行之后,跳转页面之前回调。
- afterCompletion方法在跳转页面之后执行。
3. 切面拦截
AOP切面编程需要引入的jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
AOP切面通知的执行顺序:
进入环绕通知
前置通知
Object result=(boolean)jointPoint.proceed(); //执行该方法
退出环绕通知
后置通知
返回通知
@Component
@Aspect
public class ServiceAspect {
private static final Logger logger = LoggerFactory.getLogger(ServiceAspect.class);
//定义切点com.tellme.controller.PersonController
private final String POINT_CUT = "execution(public * com.tellme.controller.*.*(..))";
@Pointcut(POINT_CUT)
public void pointCut() {
}
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint) {
logger.info("前置通知");
}
}
文章参考
spring boot入门(七) springboot的拦截器Interceptor。最完整、简单易懂、详细的spring boot教程。