玩轉(zhuǎn) SpringBoot 2 快速整合攔截器

概述

首先聲明一下,這里所說的攔截器是 SpringMVC 的攔截器 HandlerInterceptor。使用SpringMVC 攔截器需要做如下操作:

  1. 創(chuàng)建攔截器類需要實現(xiàn) HandlerInterceptor
  2. 在 xml 配置文件中配置該攔截器,具體配置代碼如下:
<mvc:interceptors>
    <mvc:interceptor>
    <!-- /test/** 這個是攔截路徑以/test開頭的所有的URL-->
    <mvc:mapping path="/**"/><!—這個是攔截說有的路徑-->
    <!-- 配置攔截器類路徑-->
    <bean class="cn.ljk.springmvc.controller.MyInterceptor"></bean>
    <!-- 配置不攔截器URL路徑-->
    <mvc:exclude-mapping path="/fore/**"/>
    </mvc:interceptor>
</mvc:interceptors>

因為在SpringBoot 中沒有 xml 文件,所以SpringBoot 為我們提供 Java Config 的方式來配置攔截器。配置方式有2種:

  1. 繼承 WebMvcConfigurerAdapter (官方已經(jīng)不建議使用)
  2. 實現(xiàn) WebMvcConfigurer

接下來開始 SpringBoot 整合攔截器操作詳細(xì)介紹!

整合攔截器實戰(zhàn)操作

第一步:聲明攔截器類

通過實現(xiàn) HandlerInterceptor 來完成。具體代碼如下:

public class LoginInterceptor implements HandlerInterceptor{}

第二步:實現(xiàn) HandlerInterceptor 3 個攔截方法

  • preHandle:Controller邏輯執(zhí)行之前進(jìn)行攔截
  • postHandle:Controller邏輯執(zhí)行完畢但是視圖解析器還為進(jìn)行解析之前進(jìn)行攔截
  • afterCompletion:Controller邏輯和視圖解析器執(zhí)行完畢進(jìn)行攔截

實際開發(fā)中 preHandle使用頻率比較高,postHandle 和 afterCompletion操作相對比較少。

在下面的代碼中 preHandle 方法中定義攔截所有訪問項目 URL并進(jìn)行日志信息記錄。postHandle 中在視圖解析前進(jìn)行攔截,通過 Model 在次添加數(shù)據(jù)Request域中。

afterCompletion 暫時沒有想到使用場景,如果有使用過的場景可以在下面評論區(qū)中進(jìn)行評論。

攔截器詳細(xì)代碼如下:

public class LoginInterceptor implements HandlerInterceptor{
    
    private Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
    
    //ControllerController邏輯執(zhí)行之前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandle....");
        String uri = request.getRequestURI();
        log.info("uri:"+ uri);
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            log.info("攔截 Controller:"+ handlerMethod.getBean().getClass().getName());
            log.info("攔截方法:"+handlerMethod.getMethod().getName());
        }
        
        return true;
    }
    
    //Controller邏輯執(zhí)行完畢但是視圖解析器還為進(jìn)行解析之前
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        log.info("postHandle....");
        Map<String,Object>map=modelAndView.getModel();
        map.put("msg","postHandle add msg");
    }
    
    //Controller邏輯和視圖解析器執(zhí)行完畢
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        log.info("afterCompletion....");
    }
}

第三步:Java Config 的方式來配置攔截器

繼承 WebMvcConfigurerAdapter 方式

通過繼承 WebMvcConfigurerAdapter并重寫 addInterceptors方法,通過其參數(shù) InterceptorRegistry將攔截器注入到 Spring的上下文中。

另外攔截路徑和不攔截的路徑通過InterceptorRegistry 的 addPathPatterns和 excludePathPatterns方法進(jìn)行設(shè)置。

這種方式官方已經(jīng)不建議使用,因為官方已將 WebMvcConfigurerAdapter 標(biāo)記為@Deprecated 了。

@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {

繼承 WebMvcConfigurerAdapter 方式具體代碼如下:

@Configuration
    public class InterceptorConfigByExtendsWebMvcConfigurerAdapter extends  WebMvcConfigurerAdapter{

    @Bean
        public LoginInterceptor loginInterceptor(){
                return new LoginInterceptor();
        }

        public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
        }
}

實現(xiàn) WebMvcConfigurer 方式

通過實現(xiàn) WebMvcConfigurer 接口并實現(xiàn) addInterceptors方法,其他操作和繼承 WebMvcConfigurerAdapter方式一樣。具體代碼如下:

```java
@Configuration
public class InterceptorConfigByImplWebMvcConfigurer implements WebMvcConfigurer{
    
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }
     @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
    }
}
```

測試

編寫普通Controller,具體代碼如下:

@Controller
public class IndexController {
    
    @GetMapping("/index")
    public String index(ModelAndView modelAndView){
        
        return "index";
    }
}

在 src/main/resource 下的 templates目錄下創(chuàng)建 IndexController訪問頁面 index.ftl, 代碼如下:

<h1>${msg}</h1>

由于我這里使用的是 Freemarker當(dāng)頁面使用,說以需要引入 Freemarker starter依賴,具體點如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

通過游覽器訪問 localhost:8080/sbe/index,具體訪問效果如下:

在這里插入圖片描述

如上圖所示在視圖解析前通過 Model在次添加數(shù)據(jù)到 Request域中的msg 成功顯示出來了!

日志輸出信息如下:攔截地址和攔截Controller 和具體方法進(jìn)行日志輸出

2019-09-24 15:53:04.144  INFO 7732 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/sbe]    : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-09-24 15:53:04.145  INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-09-24 15:53:04.153  INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : preHandle....
2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : uri:/sbe/index
2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : 攔截 Controller:cn.lijunkui.controller.IndexController
2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : 攔截方法:index
2019-09-24 15:53:04.156  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : postHandle....
2019-09-24 15:53:04.161  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : afterCompletion....

小結(jié)

SpringBoot 2 整合攔截器和整合 Filter的操作很像,都是通過一個注冊類將其注入到Spring的上下文中,只不過Filter使用的是 FilterRegistrationBean 而 攔截器使用的是 InterceptorRegistry。

個人覺得比使用 xml 配置的方式更為簡單了,如果你還沒有在 SpringBoot 項目中使用過攔截器,趕快來操作一下吧!

代碼示例

具體代碼示例請在我的GitHub 倉庫 springbootexamples 中模塊名為 spring-boot-2.x-interceptor 項目中進(jìn)行查看

GitHub:https://github.com/zhuoqianmingyue/springbootexamples

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容