Springboot中的自定義攔截器及原理詳解
攔截器機(jī)制
攔截器主要是用于在用戶請(qǐng)求控制中,對(duì)于請(qǐng)求識(shí)別,鑒權(quán),以及區(qū)分資源是否可以被目標(biāo)方法調(diào)用的安全機(jī)制。 要實(shí)現(xiàn)攔截器,SpringMvc 已經(jīng)幫我集成好了,只需要實(shí)現(xiàn) HandlerInterceptor 的接口,如果我們要寫(xiě)一個(gè)攔截器,就要實(shí)現(xiàn)這個(gè) HandlerInterceptor 這個(gè)攔截器的標(biāo)準(zhǔn)接口;
攔截器使用場(chǎng)景
我們常用于購(gòu)物網(wǎng)站,比如說(shuō)京東商城中,加入購(gòu)物車(chē)之后,如果要結(jié)算,就會(huì)跳轉(zhuǎn)到登錄界面,這個(gè)就是攔截器的作用,判斷是否已經(jīng)登錄成功,區(qū)別訪問(wèn)的路徑,細(xì)節(jié)就在接口的三個(gè)方法中; 適用場(chǎng)景:登錄,鑒權(quán),靜態(tài)資源訪問(wèn)等 我們就以登錄舉例子,如果說(shuō)用戶要訪問(wèn)個(gè)人信息,驗(yàn)證當(dāng)前是否已經(jīng)登錄,可以是 token 是否合法然后沒(méi)有就要攔截器到未登錄的頁(yè)面,開(kāi)始登錄操作;
package com.atspring.config; import com.atspring.intercepter.LoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * 配置web請(qǐng)求中的設(shè)置 */ @Configuration public class AdminWebConfig implements WebMvcConfigurer { /** * 1.編寫(xiě)一個(gè)攔截器,注冊(cè)到容器中,addInterceptors * 2.指定攔截規(guī)則,如果攔截所有,所有資源包括靜態(tài)資源都會(huì)被攔截 * @param registry */ //webconfig中的增加攔截器的方法,只需要重寫(xiě)就可以 @Override public void addInterceptors(InterceptorRegistry registry) { // LoginInterceptor loginInterceptor=new LoginInterceptor(); // registry.addInterceptor(loginInterceptor); registry.addInterceptor(new LoginInterceptor()) //添加攔截器攔截的路徑,/**全部放行,但在實(shí)際項(xiàng)目中可能是域名 /lucas/** .addPathPatterns("/**") //放行靜態(tài)資源,以及登錄 .excludePathPatterns("/login","/css/**","/image/**","/js/**"); } }
配置攔截器:
package com.atspring.intercepter; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * 登錄檢查 * 1.配置攔截器攔截哪些請(qǐng)求, * 2.把配置放在容器中Aop */ public class LoginInterceptor implements HandlerInterceptor { /** * 處理方法之前,資源請(qǐng)求, * 檢查等 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //登錄檢查,這里就利用session簡(jiǎn)單的存儲(chǔ)了 HttpSession session=request.getSession(); Object loginUser = session.getAttribute("loginUser"); if (loginUser!=null){ //放行 return true; } //攔截成功 request.setAttribute("message","請(qǐng)先登錄"); //轉(zhuǎn)發(fā)到登錄頁(yè)面去登錄,并且返回 request.getRequestDispatcher("/login").forward(request,response); return false; } /** * 處理方法之后,未返回頁(yè)面之前 * 對(duì)于數(shù)據(jù)處理 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } /** * 請(qǐng)求執(zhí)行完成之后, * 對(duì)資源的關(guān)閉等 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
攔截器原理
- 根據(jù)當(dāng)前請(qǐng)求,找到 HandlerExecutionChain【可以處理請(qǐng)求的 handler 以及 handler 的所有 攔截器】
- 先來(lái)順序執(zhí)行 所有攔截器的 preHandle 方法
- 如果當(dāng)前攔截器 prehandler 返回為 true。則執(zhí)行下一個(gè)攔截器的 preHandle
- 如果當(dāng)前攔截器返回為 false。直接 倒序執(zhí)行所有已經(jīng)執(zhí)行了的攔截器的 afterCompletion;
- 如果任何一個(gè)攔截器返回 false。直接跳出不執(zhí)行目標(biāo)方法
- 所有攔截器都返回 True。執(zhí)行目標(biāo)方法
- 倒序執(zhí)行所有攔截器的 postHandle 方法。
- 前面的步驟有任何異常都會(huì)直接倒序觸發(fā) afterCompletion
- 頁(yè)面成功渲染完成以后,也會(huì)倒序觸發(fā) afterCompletion
Sprinboot添加自定義攔截器后視圖解析失敗問(wèn)題
我在使用Springboot2.0通過(guò)重載WebMvcConfigurationSupport和使用注解@Configuration的方法添加自定義攔截器后會(huì)出現(xiàn)一個(gè)bug,就是我們?cè)赼pplication.properties配置的視圖解析失效 我在application.properties的配置如下:
server.port=8086 server.servlet.context-path=/ spring.mvc.view.prefix=/views/ spring.mvc.view.suffix=.jsp
我的InterceptorConfig 代碼如下:
@Configuration public class InterceptorConfig extends WebMvcConfigurationSupport { @Autowired private LoginHandlerInterceptor loginHandlerInterceptor; @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("forward:/index"); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); super.addViewControllers(registry); } @Override public void addInterceptors(InterceptorRegistry registry) { // 判斷用戶是否登錄的攔截器 registry.addInterceptor(loginHandlerInterceptor).addPathPatterns("/*/*"); super.addInterceptors(registry); } }
我推測(cè)應(yīng)當(dāng)是WebMvcConfigurationSupport 中創(chuàng)建了新的視圖解析器,既然如此,我就直接自定義一個(gè)ViewResolver 放到WebMvcConfigurationSupport中,問(wèn)題得到解決。
private static final String VIEW_PREFIX = "/views/";// 視圖前綴 private static final String VIEW_SUFFIX = ".jsp";// 視圖后綴 private static final String VIEW_CONTENT_TYPE = "text/html;charset=UTF-8";//視圖的內(nèi)容類(lèi)型。 /** * 配置 視圖解析器 * @return */ @Bean public ViewResolver viewResolver(){ InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setCache(true); resolver.setPrefix(VIEW_PREFIX); resolver.setSuffix(VIEW_SUFFIX); resolver.setExposeContextBeansAsAttributes(true); resolver.setContentType(VIEW_CONTENT_TYPE); return resolver; }
到此這篇關(guān)于Springboot中的自定義攔截器及原理詳解的文章就介紹到這了,更多相關(guān)Springboot自定義攔截器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jdk8?FunctionalInterface注解源碼解讀
這篇文章主要介紹了jdk8?FunctionalInterface注解源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11java 漢諾塔Hanoi遞歸、非遞歸(仿系統(tǒng)遞歸)和非遞歸規(guī)律 實(shí)現(xiàn)代碼
漢諾塔(Hanoi) 算法Java實(shí)現(xiàn)。通過(guò)三個(gè)函數(shù),分別對(duì)Hanoi進(jìn)行遞歸、非遞歸和非遞歸規(guī)律實(shí)現(xiàn)。2013-05-05一文帶你學(xué)習(xí)Java多維數(shù)組的使用技巧
Java作為一門(mén)廣泛應(yīng)用于各行各業(yè)的開(kāi)發(fā)語(yǔ)言,具有豐富的數(shù)據(jù)類(lèi)型支持,其中多維數(shù)組是其重要的一種,多維數(shù)組可以更加方便地組織數(shù)據(jù),提高Java應(yīng)用程序的效率,本文將為大家介紹Java中多維數(shù)組的基本概念和常用操作,助力讀者更好地掌握多維數(shù)組的使用技巧2023-11-11java數(shù)據(jù)結(jié)構(gòu)排序算法之歸并排序詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)排序算法之歸并排序,結(jié)合具體實(shí)例形式詳細(xì)分析了歸并排序的原理、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-05-05elasticsearch+logstash并使用java代碼實(shí)現(xiàn)日志檢索
這篇文章主要介紹了elasticsearch+logstash并使用java代碼實(shí)現(xiàn)日志檢索,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02關(guān)于后綴表達(dá)式的java實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了關(guān)于后綴表達(dá)式的java實(shí)現(xiàn)過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07MyBatis-Plus自定義通用的方法實(shí)現(xiàn)
MP自帶的條件構(gòu)造器雖然很強(qiáng)大,有時(shí)候也避免不了寫(xiě)稍微復(fù)雜一點(diǎn)業(yè)務(wù)的sql,本文主要介紹了MyBatis-Plus自定義通用的方法實(shí)現(xiàn),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05關(guān)于Java錯(cuò)誤提示之找不到或無(wú)法加載主類(lèi)的問(wèn)題及正確處理方法
當(dāng)我們?cè)诔鯇W(xué)Java的是時(shí)候,類(lèi)文件中是不設(shè)定包名(package)的,這種情況下注意classpath,基本上沒(méi)有問(wèn)題,?本文主要說(shuō)明classpath和系統(tǒng)環(huán)境變量PATH都沒(méi)問(wèn)題的情況下出錯(cuò)原因和正確處理方法,感興趣的朋友一起看看吧2022-01-01Spring Batch讀取txt文件并寫(xiě)入數(shù)據(jù)庫(kù)的方法教程
這篇文章主要給大家介紹了Spring Batch讀取txt文件并寫(xiě)入數(shù)據(jù)庫(kù)的方法,SpringBatch 是一個(gè)輕量級(jí)、全面的批處理框架。這里我們用它來(lái)實(shí)現(xiàn)文件的讀取并將讀取的結(jié)果作處理,處理之后再寫(xiě)入數(shù)據(jù)庫(kù)中的功能。需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-04-04