SpringBoot之HandlerInterceptor攔截器的使用 ——(一)


HandlerInterceptor簡介
攔截器我想大家都並不陌生,最常用的登錄攔截、或是權限校驗、或是防重復提交、或是根據業務像12306去校驗購票時間,總之可以去做很多的事情。
我仔細想了想
這里我分三篇博客來介紹HandlerInterceptor的使用,從基本的使用、到自定義注解、最后到讀取body中的流解決無法多次讀取的問題。

1、定義實現類
定義一個Interceptor 非常簡單方式也有幾種,我這里簡單列舉兩種
1、類要實現Spring 的HandlerInterceptor 接口
2、類繼承實現了HandlerInterceptor 接口的類,例如 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter

2、HandlerInterceptor方法介紹

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

preHandle:在業務處理器處理請求之前被調用。預處理,可以進行編碼、安全控制、權限校驗等處理;
postHandle:在業務處理器處理請求執行完成后,生成視圖之前執行。后處理(調用了Service並返回ModelAndView,但未進行頁面渲染),有機會修改ModelAndView (這個博主就基本不怎么用了);
afterCompletion:在DispatcherServlet完全處理完請求后被調用,可用於清理資源等。返回處理(已經渲染了頁面);
接下來讓我們來實現一個登陸 and 訪問權限校驗的攔截器吧

 

攔截器實現

  • 新建TestFilter
  • package com.xxx.core.filter;
    
    import com.xxx.common.exception.FastRuntimeException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    public class TestFilter extends HandlerInterceptorAdapter {
        private final Logger logger = LoggerFactory.getLogger(TestFilter.class);
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            logger.info("request請求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI());
            //request.getHeader(String) 從請求頭中獲取數據
            //從請求頭中獲取用戶token(登陸憑證根據業務而定)
            Long userId= getUserId(request.getHeader("H-User-Token"));
            if (userId != null && checkAuth(userId,request.getRequestURI())){
                return true;
            }
            //這里的異常是我自定義的異常,系統拋出異常后框架捕獲異常然后轉為統一的格式返回給前端, 其實這里也可以返回false
            throw new FastRuntimeException(20001,"No access");
        }
    
        /**
         * 根據token獲取用戶ID
         * @param userToken
         * @return
         */
        private Long getUserId(String userToken){
            Long userId = null;
            return userId;
        }
    
        /**
         * 校驗用戶訪問權限
         * @param userId
         * @param requestURI
         * @return
         */
        private boolean checkAuth(Long userId,String requestURI){
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {}
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {}
    }

     

  • 新建WebAppConfigurer 實現WebMvcConfigurer接口

其實以前都是繼承WebMvcConfigurerAdapter類 不過springBoot2.0以上 WebMvcConfigurerAdapter 方法過時,有兩種替代方案:
1、繼承WebMvcConfigurationSupport
2、實現WebMvcConfigurer
但是繼承WebMvcConfigurationSupport會讓Spring-boot對mvc的自動配置失效。根據項目情況選擇。現在大多數項目是前后端分離,並沒有對靜態資源有自動配置的需求所以繼承WebMvcConfigurationSupport也未嘗不可。

@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 可添加多個
        registry.addInterceptor(new TestFilter()).addPathPatterns("/**");
    }

    ....
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM