1. 程式人生 > 其它 >過濾器、攔截器入門,看這一篇就夠了

過濾器、攔截器入門,看這一篇就夠了

實際專案開發過程中,肯定有這樣的需求:

  1. 記錄每個rest請求耗費的時間,入參,出參
  2. 某些請求需要判斷是否有許可權,某些請求是不需要許可權也可以執行的

這個需求太普遍了。今天我們就一起來學習這個需求的兩種實現方式:

  1. 攔截器
  2. 過濾器

攔截器

話不多說,咱們上程式碼,新建日誌攔截器:

@Component
public class LogInterceptor implements HandlerInterceptor {
    //在請求rest介面之前呼叫
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
Object
handler) throws Exception { System.out.println("請求url:"+request.getRequestURL()); Map<String, String[]> parameterMap = request.getParameterMap(); Enumeration<String> parameterNames = request.getParameterNames(); System.out.println("請求引數:"); while (parameterNames.hasMoreElements()) { String name = (String) parameterNames.nextElement(); String value = request.getParameter(name); System.out.println(name+"==>"+value); } //假設引數a傳遞的如果是1的話,是不合法的請求,不繼續往下執行 if("1".equals(request.getParameter("a"))){ return false; } return true;//如果返回false則不會繼續往下執行,不會真正的進入到controller } //請求處理之後進行呼叫,但是在檢視被渲染之前(Controller方法呼叫之後) @Override public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object
handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle is called..."); } //在整個請求結束之後被呼叫 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion is called..."); } }

WebMvcConfigurer中註冊該攔截器,並告訴spring哪些路徑需要攔截,哪些路徑不需要攔截

@Configuration
public class InterceperConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //新增攔截器
        InterceptorRegistration interceptorRegistration = registry.addInterceptor(new LogInterceptor() {
        });
        //如下的路徑不攔截,多個路徑用逗號分隔
        interceptorRegistration.excludePathPatterns("/demo/test2");
        //攔截如下路徑
        interceptorRegistration.addPathPatterns("/**");
    }
}

好了,攔截器就做完了,so easy。下面我們寫個controller來測試下吧!

@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("test1")
    public String test1(){
        System.out.println("rest.test1 is called");
        return "test1";
    }

    @GetMapping("test2")
    public String test2(){
        System.out.println("rest.test2 is called");
        return "test2";
    }

    @GetMapping("test3")
    public String test3(@RequestParam("a")String a){
        System.out.println("rest.test3 is called");
        return "test3";
    }
}

測試的結果基本可以預期到

  1. demo/test1 和 demo/test3會被攔截,進攔截器
  2. demo/test2 不會進攔截器
  3. demo/test3?a=1 這個請求會進攔截器,但是進不了controller。

過濾器

@WebFilter(urlPatterns = "/*", filterName = "LogFilter")
public class LogFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("logfilter.init is called...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter中列印的請求引數:");
        Enumeration<String> parameterNames = servletRequest.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String key = parameterNames.nextElement();
            String value = servletRequest.getParameter(key);
            System.out.println(key+"==>"+value);
        }

        long bgn = System.currentTimeMillis();
        //一定要呼叫鏈式呼叫傳遞,否則也進不了controller
        filterChain.doFilter(servletRequest,servletResponse);
        long end = System.currentTimeMillis();
        System.out.println("filter中記錄耗時:"+(end-bgn)+"ms");
    }

    @Override
    public void destroy() {
        System.out.println("logfilter.destroy is called...");
    }
}

注意:@WebFilter這個註解是Servlet3.0的規範,並不是Spring boot提供的。除了這個註解以外,我們還需在配置類中加另外一個註解:@ServletComponetScan,指定掃描的包。

總結

攔截器、過濾器執行順序,預設先執行過濾器,再執行攔截器。

如果過濾器有多個會根據過濾器的名詞按照A-Z的排序先後執行。這是因為@WebFilter這個註解不支援執行順序。當然你也可以通過寫一個配置檔案解決。

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean reqResFilter1() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        LogFilter logFilter = new LogFilter();
        filterRegistrationBean.setFilter(logFilter);
        filterRegistrationBean.addUrlPatterns("/demo/test1","/demo/test3");//配置過濾規則
        filterRegistrationBean.addInitParameter("name","spingboot");//設定init引數
        filterRegistrationBean.setName("logFilter");//設定過濾器名稱
        filterRegistrationBean.setOrder(2);//執行次序

        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean reqResFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        Log1Filter log1Filter = new Log1Filter();
        filterRegistrationBean.setFilter(log1Filter);
        filterRegistrationBean.addUrlPatterns("*");//配置過濾規則
        filterRegistrationBean.setName("Log1Filter");//設定過濾器名稱
        filterRegistrationBean.setOrder(1);//執行次序

        return filterRegistrationBean;
    }
}
更多java原創閱讀:https://javawu.com