攔截的方法
- 過濾器 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
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CXzUFVNhXTq50dJRVT4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMwcDO1QTM1ETNykDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
//依賴
<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;
}
}