Spring中常见的全局过滤方式有三种:Filter、Conterceptor、Aspect。
属于 javax.servlet.Filter 技术。
public class XxxxFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { /*前置过滤逻辑*/ filterChain.doFilter(servletRequest, servletResponse); /*后置过滤逻辑*/ } }
// 1、 web.xml方式配置 <filter> // filter名,随便起 <filter-name>AdminFilter</filter-name> // 实现filter的类 <filter-class>cn.kihyou.b2c.filter.AdminFilter</filter-class> // 初始化参数 <init-param></init-param> </filter> <filter-mapping> // 对应的filter名 <filter-name>AdminFilter</filter-name> // 要进行拦截过滤的目录 <url-pattern>/api/admin/*</url-pattern> </filter-mapping> // 2、注解的形式配置 在 Filter 的实现类上添加 @WebFilter 注解 eg. @WebFilter(filterName="log",urlPatterns={"/*"})
属于 org.springframework.web.servlet.HandlerInterceptor 技术。
public class XxxxInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception { /*前置过滤逻辑*/ return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception { // 其中 handler参数为处理该请求的 Controller 方法 /*后置过滤逻辑1*/ } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) throws Exception { /*后置过滤逻辑2,常用于清理资源*/ } }
// 1、 SpringMVC的配置文件中 <!-- 配置拦截器 --> <mvc:interceptors> <!-- 配置一个全局拦截器,拦截所有请求 --> <bean class="interceptor.TestInterceptor" /> <mvc:interceptor> <!-- 配置拦截器作用的路径 --> <mvc:mapping path="/**" /> <!-- 配置不需要拦截作用的路径 --> <mvc:exclude-mapping path="" /> <!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 --> <bean class="interceptor.Interceptor1" /> </mvc:interceptor> </mvc:interceptors>
// 2、注解的形式配置 @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private XxxxInterceptor xxxxInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(xxxxInterceptor); registration.addPathPatterns("/**"); //所有路径都被拦截 registration.excludePathPatterns("/static/*.html","/static/*.js",) //添加不拦截的路径 } }
项目中到底使用的是哪一种,需要在在web.xml中查看 <servlet></servlet>配置。
// 1、 指定位置 <servlet> <servlet-name>dispatcherSerlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> // 指定SpringMVC的配置文件是 classess文件夹下的springmvc.xml文件 </init-param> </servlet> // 2、默认位置 <servlet> <servlet-name>dispatcherSerlet</servlet-name> // 默认SpringMVC的配置文件是:在WEB-INF文件夹下的 {此处的servlet-name}-servlet.xml <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet>
属于 org.aspectj.lang.annotation.Aspect 技术。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface XxxxXxx { }
@Aspect @Component public class XxxxAop{ //定义切点 @Pointcut("@annotation(com.xxx.annotation.XxxxXxx)") public void audit() { } @Around("audit()") public Object handleControllerMethod(ProceedingJoinPoint point) throws Throwable { /*前置过滤逻辑*/ Object returnValue = point.proceed() /*后置过滤逻辑*/ } @Before("audit()") public void before(JoinPoint joinPoint) { /*前置过滤逻辑*/ } @After("audit()") public void after(JoinPoint joinPoint) { /*后置过滤逻辑*/ } @AfterReturning() public void afterReturning(JoinPoint joinPoint, Object result) {} @AfterThrowing() public void afterThrowing(JoinPoint joinPoint, Throwable exception) {} }
// 1、xml文件配置 <!-- 声明类 ,此类作为切面类使用 --> <bean id="logInterceptor" class="com.aop.LogInterceptor" /> <aop:config> <!-- 设置切面名,及切面类 --> <aop:aspect id="logAspect" ref="logInterceptor"> <!-- 运行前方法配置,先择要执行的方法 ,并设置切入点 --> <aop:before method="before" pointcut="execution(public * com.userService.*.add(..))" /> <!-- 先设置切入点,待使用 --> <aop:pointcut id="servicePointcut" expression="execution(public * com.userService.*.add(..))" /> <!-- 运行后方法配置,先择要执行的方法,参考预先设置好的切入点 --> <aop:after method="after" pointcut-ref="servicePointcut" /> </aop:aspect> </aop:config> // 2、启动注解配置, Spring默认不支持@Aspect风格的切面声明,通过如下配置开启@Aspect支持 <aop:aspectj-autoproxy/>
属于 org.springframework.web.method.support.HandlerMethodArgumentResolver 技术。
对于大型项目,通常会有很多引用包,其中封装了一些自定义注解,具体的实现逻辑就需要好好翻翻。
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface XxxxXxx { }
public class XxxxHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter methodParameter) { // 用于判定是否需要处理该参数,返回 true 为需要,并会去调用下面的方法resolveArgument。 return methodParameter.getParameterType().isAssignableFrom(UserParam.class) && methodParameter.hasParameterAnnotation(XxxxXxx.class); } @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { // 具体的得到参数值的逻辑,return 返回参数值 return value; } }
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new XxxxXxxHandlerMethodArgumentResolver()); } }
当前项目声明的自定义参数实现逻辑通过在当前项目文件夹搜索HandlerMethodArgumentResolver 便可快速定位。
关注公众号获取更多干货