“ 在Java Web开发中,始终离不开Filter,Interceptor,Aspect三个部分,本文将对此进行介绍。”
Filter 是servlet层面的,由Servlet容器(如Tomcat)支持,只能在web程序中使用,实现了javax.servlet.Filter接口
Interceptor 是Spring Web层面的(Structs也有), 它是由Spring容器进行管理,并不依赖Tomcat等容器,既可以应用在web程序中,也可以应用在非web程序中,实现了org.springframework.web.servlet接口
Aspect 是Spring层面的,由Spring容器进行管理,有Spring的地方都可以使用
一、过滤器 (Filter)
过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。
init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。
doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。
destroy():当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次
第一部分的正文内容从这里开始。
@Component
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("Filter 前置");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Filter 处理中");filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("Filter 后置");}
}
二、拦截器 (Interceptor)
拦截器它是链式调用,一个应用中可以同时存在多个拦截器Interceptor, 一个请求也可以触发多个拦截器 ,而每个拦截器的调用会依据它的声明顺序依次执行。
首先编写一个简单的拦截器处理类,请求的拦截是通过HandlerInterceptor 来实现,看到HandlerInterceptor 接口中也定义了三个方法。
preHandle()
:这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。
postHandle()
:只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。
afterCompletion()
:只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。
@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Interceptor 前置");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor 处理中");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Interceptor 后置");}
}
将自定义好的拦截器处理类进行注册,并通过addPathPatterns、excludePathPatterns等属性设置需要拦截或需要排除的 URL。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");}
}
三、Aspect(切面)
spring通知有五种类型,分别是:
前置通知(@Before):在目标方法调用之前调用通知
后置通知(@After):在目标方法完成之后调用通知
环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法
返回通知(@AfterReturning):在目标方法成功执行之后调用通知
异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知
@Aspect
@Component
public class AopAdvice {@Pointcut("execution (* com.xxx.xxx.controller.*.*(..))")public void test() {}@Before("test()")public void beforeAdvice() {System.out.println("beforeAdvice...");}@After("test()")public void afterAdvice() {System.out.println("afterAdvice...");}@Around("test()")public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {System.out.println("before");try {proceedingJoinPoint.proceed();} catch (Throwable t) {t.printStackTrace();}System.out.println("after");}
}
Filter(过滤器),Interceptor(拦截器) 和 Aspect(切面)的区别:
参考🔗
https://mp.weixin.qq.com/s/uBA345GU2anrNmYDbpHXvQ
原创 拥有必珍惜 码农笑江湖