使用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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章