1. 程式人生 > >使用Filter和Interceptor攔截REST服務(四)

使用Filter和Interceptor攔截REST服務(四)

在某些情況下,我們需要對REST API 做一些統一的處理 ,最常用的場景是我希望記錄所有的REST API 處理的時間 ,那麼如何的來實現這種需求呢?就需要用到這種RESTful API的攔截
過濾器( Filter )
攔截器( Interceptor)
切片( Aspect)

記錄所有服務的處理時間

/**
 * 記錄所有服務處理的時間
 * Created by ZhuPengWei on 2017/11/22.
 */
@Component
public class TimeFilter implements Filter {
    @Override
    public void
init(FilterConfig filterConfig) throws ServletException { System.out.println("Filter初始化成功了"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { Long time = new
Date().getTime(); System.out.println("Filter方法執行前時間:" +time); filterChain.doFilter(servletRequest,servletResponse); System.out.println("Filter方法執行後時間:"+new Date().getTime()+ ",共耗時:"+(new Date().getTime()-time)); } @Override public void destroy() { System.out.println("Filter銷燬了"
); } }

(1)、啟動伺服器時載入過濾器的例項,並呼叫init()方法來初始化例項;
(2)、每一次請求時都只調用方法doFilter()進行處理;
(3)、停止伺服器時呼叫destroy()方法,銷燬例項。

如果引用了第三方的過濾器,並且沒有Conponent註解 怎麼把第三方的過濾器引入到專案之中來呢?在傳統的專案中一般有web.xml這個配置檔案,在springboot之中一般是沒有這個配置檔案的

/**
 * Created by ZhuPengWei on 2017/11/22.
 */
@Configuration
public class WebConfig {
    @Bean
    public FilterRegistrationBean timeFilter() {
             // 過濾器註冊
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
              // 時間過濾器
        TimeFilter timeFilter = new TimeFilter();
                 // 設定
        filterRegistrationBean.setFilter(timeFilter);
             List<String> urls = new ArrayList<String>();
               // 設定攔截路徑
         urls.add("/*");
             filterRegistrationBean.setUrlPatterns(urls);
            return filterRegistrationBean;
    }
}

過濾器來攔截REST API 這種方式一般會有一個問題,這個問題是它只能拿到HTTP 的請求和響應,只能從請求和響應中獲取一些引數,這些發過來的請求實際上是由哪一個控制器的哪一個方法來處理的在Filter中是不知道的,因為Filter這個介面是J2EE規範來定義的 在J2EE中實際上是不能瞭解到和Spring相關的任何東西。而自定義的比如說UserController實際上是springmvc自己定義的一些東西。
如果需要知道這些資訊的話 我們需要第二個機制 攔截器 ,攔截器這個東西本身是spring框架提供的

/**
 * 時間攔截器
 * Created by ZhuPengWei on 2017/11/22.
 */
@Component
public class TimeInterceptor implements HandlerInterceptor {

// 1呼叫前
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle!!");
        System.out.println("攔截的類名稱:"+ ((HandlerMethod)o).getBean().getClass().getName());
        System.out.println("攔截的方法名稱:"+((HandlerMethod)o).getMethod().getName());
        // 設定攔截開始時間
        httpServletRequest.setAttribute("time",new Date().getTime());
        return true;
  }

// 2呼叫後
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        Long nowTime = new Date().getTime();
        long preTime = (long) httpServletRequest.getAttribute("time");
        System.out.println("Interceptor耗時:" +(nowTime-preTime));
}

// 丟擲異常 則 2不會被呼叫了  不管有沒有丟擲異常 3總是會被呼叫
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion");
        Long nowTime = new Date().getTime();
        long preTime = (long) httpServletRequest.getAttribute("time");
        System.out.println("Interceptor耗時:" +(nowTime-preTime));
        System.out.println(e);
        System.out.println("攔截之後");
    }
}
/**
 * 自定義過濾器 攔截器
 * 攔截器需要繼承 WebMvcConfigurerAdapter
 * Created by ZhuPengWei on 2017/11/22.
 */
@Configuration
public class WebConfig  extends WebMvcConfigurerAdapter{

    @Autowired
    private TimeInterceptor timeInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(timeInterceptor);
    }


    @Bean
    public FilterRegistrationBean timeFilter() {
        // 過濾器註冊
     FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        // 時間過濾器
     TimeFilter timeFilter = new TimeFilter();
        // 設定
     filterRegistrationBean.setFilter(timeFilter);
        List<String> urls = new ArrayList<String>();
        // 設定攔截路徑
        urls.add("/*");
        filterRegistrationBean.setUrlPatterns(urls);
        return filterRegistrationBean;
    }
}