1. 程式人生 > >五十、Filter過濾器,Interceptor攔截器,ControllerAdvice,Aspect切片

五十、Filter過濾器,Interceptor攔截器,ControllerAdvice,Aspect切片

Filter過濾器,Interceptor攔截器,ControllerAdvice,Aspect切片

上圖為在web專案中,在處理request請求時得處理順序

在專案中我們改怎麼使用呢?

 Filter過濾器

/**
 * Created by GAOMINGQIAN on 2017/12/10.
 *<pr>
 *     Filter只能獲取到請求的request和response。獲取不到其他的資訊
 *     因為Filter屬於J2EE的內容,不知道spring
 *      會攔截所有的請求
 *</pr>
 *
 */
//@Component
public class TimeFilter implements Filter {
    //初始化的時候呼叫
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("time filter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("time filter start");
        long start=new Date().getTime();
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("time filter end:"+(new Date().getTime()-start));
        System.out.println("time filter finsh");
    }

    //銷燬時呼叫
    @Override
    public void destroy() {
        System.out.println("time filter destory");
    }
}

上述內容中有一個@Component註解,當我們不想使用時或者更細的粒度攔截,需要在config類中進行註冊

//配置一個過濾器
@Bean
public FilterRegistrationBean timeFilter() {
    //filter註冊用的bean
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    TimeFilter timeFilter = new TimeFilter();
    filterRegistrationBean.setFilter(timeFilter);
    List<String> urls = new ArrayList<>();
    urls.add("/*");
    //設定filter對那些請求有作用,這裡設定的是對所有的請求都有作用
    filterRegistrationBean.setUrlPatterns(urls);
    return filterRegistrationBean;
}

Interceptor攔截器

/**
 * Created by GAOMINGQIAN on 2017/12/10.
 */
public class TimeInterceptor implements HandlerInterceptor {
    //該方法的返回值決定後續的方法是否執行(controller中的方法)
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle");
        //獲取controller類名稱
        System.out.println(((HandlerMethod) o).getBean().getClass().getName());
        //獲取執行method的名字
        System.out.println(((HandlerMethod)o).getMethod().getName());
        httpServletRequest.setAttribute("startTime", new Date().getTime());
        return true;
    }

    //當controller丟擲異常時,該方法不會被呼叫
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        long start = (Long) httpServletRequest.getAttribute("startTime");
        System.out.println("time interceptor耗時" + (new Date().getTime() - start));
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion");
        long start = (Long) httpServletRequest.getAttribute("startTime");
        System.out.println("time interceptor耗時" + (new Date().getTime() - start));
        //當無異常的時候,e的值為null,有自定義異常時,也會為Null
        System.out.println(e);
    }
}

需要在配置類中宣告才能使用,繼承WebMvcConfigurerAdapter

//告訴spring這是一個配置類 
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
  
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       //註冊當前的攔截器
       registry.addInterceptor(new TimeInterceptor());
    }
}

Aspect切片使用

/**
 * Created by GAOMINGQIAN on 2017/12/10.
 */
@Aspect
@Component
public class TimeAspect {
   //around中的execution中的內容代表對哪些方法進行攔截
    @Around("execution(* study.security.web.controller.UserController.*(..))")
    public Object handlerControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("time aspect start");
        //獲取執行方法的引數
        Object[] args = pjp.getArgs();
        long start = new Date().getTime();
        //執行攔截的方法  result為攔截方法的返回值
        Object result = pjp.proceed();
        System.out.println("time aspect 耗時:" + (new Date().getTime() - start));
        return result;
    }
}

ControllerAdvice,主要用於異常處理的控制器

/**
 * Created by GAOMINGQIAN on 2017/12/10.
 */
@ControllerAdvice
public class ControllerHandlerException {
    @ExceptionHandler(UserNotExistException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, Object> handleUserNotExistException(UserNotExistException ex) {
        Map<String, Object> result = new HashedMap();
        //放置需要響應的內容
        result.put("message",ex.getMessage());
        return result;
    }
}

優缺點介紹:

   Filter過濾器:可以拿到request,response但是拿不到處理方法的資訊

   Interceptor攔截器:可以拿到request,response,也可以拿到處理方法的資訊,但是拿不到處理方法引數的值

   Aspect切片:可以拿到處理方法的所有資訊,但是拿不到request,response