Filter、Interceptor、Aspect 区别及实现
Fliter 过滤器
请求在到达Controller之前进行与返回去之后 调用 入参为 reuqest,response,chian,过滤器获取不了具体调用哪一个类,哪一个方法。
实现:
1、继承 Filter 接口
import java.io.IOException; import java.util.Date; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.stereotype.Component; //@Component public class TimeFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("TimeFilter init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("TimeFilter in"); long startTime = new Date().getTime(); chain.doFilter(request, response); System.out.println("TimeFilter out 耗时:" + (new Date().getTime() - startTime)); } @Override public void destroy() { System.out.println("TimeFilter destroy"); } }
2、声明:两种方式,一是在类前加入@Component ,不能指定拦截的路径;二是 对于SSM 在web.xml中进行声明,对于 SpringBoot 在webConfig中声明
web.xml
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
SpringBoot:
package com.maple.web.config; import java.util.ArrayList; import java.util.List;import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import com.maple.web.filter.TimeFilter; import com.maple.web.interceptor.TimeInterceptor; @Configuration public class WebConfig{
@Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter(); registrationBean.setFilter(timeFilter); List<String> url = new ArrayList<>(); url.add("/*"); registrationBean.setUrlPatterns(url); return registrationBean; } }
Interceptor 拦截器
请求在到达Controller之前进行与返回去之后 调用 入参为 reuqest,response,handler,在过滤器之后调用,能够知道调用哪一个类,但是获取不了参数
1、继承HandlerInterceptor ,perHandler 在进入Controller前执行,若返回false则不进入Controller ,true进入Controller ,postHandler处理完Controller后进入此方法,若发生异常,则不进入postHandler。afterCompletion 都会进入此方法,无论是否发生异常都会进入。
package com.maple.web.interceptor; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; /** * @author hzc * */ @Component public class TimeInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); System.out.println(((HandlerMethod)handler).getBean().getClass().getName()); System.out.println(((HandlerMethod)handler).getMethod().getName()); request.setAttribute("startTime", new Date().getTime()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); long startTime = (long) request.getAttribute("startTime"); System.out.println("time interceptor 耗时: " + (new Date().getTime() - startTime)); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); long startTime = (long) request.getAttribute("startTime"); System.out.println("time interceptor 耗时: " + (new Date().getTime() - startTime)); System.out.println("ex is " + ex); } }
2、声明,在SSM中需要在spring配置文件中声明,在Springboot中在Config中声明。
SSM:
<mvc:interceptors> <!-- 对公众用户进行拦截 --> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 拦截所有路径 --> <bean id="userinterceptor" class="org.sz.source.schedul.common.BaseOrgUserInterceptor"> <property name="excludedUrls"><!-- 以下路径不拦截 --> <list> <value>/login.do</value> </list> </property> </bean> </mvc:interceptor> </mvc:interceptors>
SpringBoot:
package com.maple.web.config; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebConfig extends WebMvcConfigurerAdapter{ @Autowired private TimeInterceptor timeInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }
Aspect 切面
使用切面,可前置增强,后置增强,环绕增强,在拦截器之后执行,可获取参数信息
1、编写切面方法类
import java.util.Date; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; /** * @author hzc * */ @Aspect @Component public class TimeAspect { @Around("execution(* com.maple.web.controller.UserController.*(..))") public Object handlerControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); Object[] args = pjp.getArgs(); // 获取参数 for (Object arg : args) { System.out.println("arg is " + arg); } long startTime = new Date().getTime(); Object object = pjp.proceed(); System.out.println("time aspect 耗时: " + (new Date().getTime() - startTime)); return object; } }
Filter、Interceptor、Aspect的作用范围如下: