自定义过滤器(filter)
//@Component
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("my filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("my filter start");
long start = new Date().getTime();
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("my filter 耗时:" + (new Date().getTime() - start));
System.out.println("my filter finish");
}
@Override
public void destroy() {
System.out.println("my filter destroy");
}
}
自定义的filter可以不加上@Componet注解,就比如我们开发中经常需要增加第三方的过滤器,但是引入的第三方包里的过滤器又不能修改源码,在以前ssm框架中开发时,可以将filter配置在web.xml文件中,而Springboot中并没有web.xml文件,所以需要单独写配置文件配置:
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean timeFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
MyFilter myFilter = new MyFilter();
filterRegistrationBean.setFilter(myFilter);
// 设置MyFile在指定url起作用
List<String> urlList = new ArrayList<>();
urlList.add("/*");
filterRegistrationBean.setUrlPatterns(urlList);
return filterRegistrationBean;
}
}
使用配置文件配置我们自己写的filter时,可以配置filter在指定的url生效,如果直接使用@Compnent注解,则filter在所有的的url都生效。
自定义拦截器(interceptor)
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
request.setAttribute("startTime", new Date().getTime());
System.out.println(((HandlerMethod) handler).getBean().getClass().getName()); // 获取处理请求的类名称
System.out.println(((HandlerMethod) handler).getMethod().getName()); // 获取处理请求的方法名
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
long startTime = (long) request.getAttribute("startTime");
System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
long startTime = (long) request.getAttribute("startTime");
System.out.println("my interceptor 耗时:" + (new Date().getTime() - startTime));
System.out.println("ex is " + e);
}
}
自定义拦截器后,还需要单独写配置文件进行配置:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private MyInterceptor myInterceptor;
// 重写WebMvcConfigurerAdapter类的addInterceptors方法,添加自己的拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor);
}
}
切片(aspect)
引入maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class MyAspect {
@Around("execution(* com.sinosoft.controller.UserController.*(..))")
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("my 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("my aspect 耗时:" + (new Date().getTime() - startTime));
System.out.println("my aspect end");
return object;
}
}
定义过滤器、拦截器、切片后运行结果,测试其执行顺序:
my filter start
preHandle
com.sinosoft.controller.UserController$$EnhancerBySpringCGLIB$$89062ea2
getInfo
my aspect start
arg is “自己输入的参数”
进入controller服务 // controller调用方法中打印
my aspect 耗时:2
my aspect end
postHandle
my interceptor 耗时:41
afterCompletion
my interceptor 耗时:41
ex is null
my filter 耗时:55
my filter finish
从执行结果可以看出,执行顺序如图:
总结:
1、过滤器能够拿到原始的http请求和响应的信息,但是拿不到真正处理请求的方法的信息;
2、拦截器既能拿到原始的http请求和响应的信息,也能拿到真正处理请求的方法的信息,但是拿不到方法被调用的时候,那个被调用方法的参数的值;
3、切片可以拿到方法被调用的时候,方法参数传进来的值,但是拿不到原始的http请求和响应的对象。