拦截的方法
- 过滤器 Filter 初始化 销毁 doFilter处理逻辑
- 拦截器 Interceptor 调用之前 控制器 调用之后 最终调用
- 切片 Aspect
过滤器
@Component
public class TimeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("time filter start"); //在执行 过滤
long start = new Date().getTime();
chain.doFilter(request, response); //放行到下一个过滤器,过滤器执行完,去执行action流程
System.out.println("time filter 耗时:"+ (new Date().getTime() - start));//流程执行完毕,打印时间
System.out.println("time filter finish"); //打印完成
}
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("time filter init"); //程序启动,执行初始化
}
@Override
public void destroy() {
System.out.println("time filter destroy");
}
}
不用Component 配置 bean
@Configuration //期初 不用继承 ,继承了可以添加拦截器
public class WebConfig extends WebMvcConfigurerAdapter {
@SuppressWarnings("unused")
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(timeInterceptor);
}
// @Bean
public FilterRegistrationBean timeFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
TimeFilter timeFilter = new TimeFilter();
registrationBean.setFilter(timeFilter);
List<String> urls = new ArrayList<>();
urls.add("/*"); //自定义URL
registrationBean.setUrlPatterns(urls);
return registrationBean;
}
}
缺点:是有哪个Action来处理的,filter是不知道的。filter是j2EE,resultController注解是mvc的
解决用 Interceptor(Spring框架提供的)
Interceptor
@Component //需要继承 HandlerInterceptor
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; //preHandle 必须返回true 才能继续
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
Long start = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("afterCompletion");
Long start = (Long) request.getAttribute("startTime");
System.out.println("time interceptor 耗时:"+ (new Date().getTime() - start));
System.out.println("ex is "+ex);
//@ControllerAdvice
public class ControllerExceptionHandler //控制器的异常处理器 在interceptor之前
//拦截器会拦截所有的控制器
}
}
之后还需要添加到interceptor中 才能用
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@SuppressWarnings("unused")
@Autowired
private TimeInterceptor timeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(timeInterceptor);
}
拦截器可以拿到 请求 响应 以及处理方法的对象(action)
缺点 ,无法拿到 方法的参数 (源码组model的代码是在执行的下面)
解决 用切片 Aspect
切片 Aspect
//依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.imooc.web.controller.UserController.*(..))")
public Object handleControllerMethod(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 start = new Date().getTime();
Object object = pjp.proceed();
System.out.println("time aspect 耗时:"+ (new Date().getTime() - start));
System.out.println("time aspect end");
return object;
}
}
切片拿不到原始的http请求和响应
拦截顺序
出了异常,最先捕获异常的是 Aspect ,之后有Advice 异常处理器 处理 ,如果继续抛,继续往上
不出 异常 没有ControllerAdvice
@ControllerAdvice
public class ControllerExceptionHandler {
@ExceptionHandler(UserNotExistException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Map<String, Object> handleUserNotExistException(UserNotExistException ex) {
Map<String, Object> result = new HashMap<>();
result.put("id", ex.getId());
result.put("message", ex.getMessage());
return result;
}
}