springboot自定義攔截器的方法
攔截器應(yīng)該分屬于web框架的組件,每個(gè)框架提供的自己的支持,實(shí)現(xiàn)方式也就不同。例如Struts和Spring,以下是Spring 的攔截器總結(jié),它是基于動(dòng)態(tài)代理(反射)實(shí)現(xiàn)的。
Spring 中聲明攔截器需要實(shí)現(xiàn) HandlerInterceptor 接口,當(dāng)然也可以通過(guò)繼承HandlerInterceptorAdapter 抽象類,HandlerInterceptorAdapter也是實(shí)現(xiàn)了HandlerInterceptor 接口。
攔截器中有四個(gè)方法:
preHandle:在Controller中的方法之前執(zhí)行,決定是否放行,return true表示放行。一旦放行其對(duì)應(yīng)的afterCompletion就一定會(huì)執(zhí)行。
postHandle:Controller中的方法處理完之后,DispatcherServlet進(jìn)行視圖的渲染之前,也就是說(shuō)在這個(gè)方法中你可以對(duì)ModelAndView進(jìn)行操作
afterCompletion:DispatcherServlet進(jìn)行視圖的渲染之后
afterConcurrentHandlingStarted:與異步相關(guān)
下面通過(guò)代碼實(shí)踐,備注了是否放行和異常對(duì)攔截器內(nèi)方法執(zhí)行的影響結(jié)論。其實(shí)只需對(duì)方法執(zhí)行的時(shí)機(jī)進(jìn)行分析,我們就可以得出相同的結(jié)論。
如果想深入了解每個(gè)方法的執(zhí)行時(shí)機(jī),可以閱讀SpringMVC的 DispatcherServlet 源碼
@Component public class InterceptorTwo extends HandlerInterceptorAdapter { ? ? ? /** ? ? * handler 對(duì)應(yīng)@RequestMapping對(duì)應(yīng)的controller對(duì)象 ? ? */ ? ? @Override ? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ? ? ? ? //這里我們是沒(méi)辦法拿到方法參數(shù)的,parameters是空的,但是可以拿到controller種注入的bean ? ? ? ? //可以斷點(diǎn)驗(yàn)證 ? ? ? ? HandlerMethod handlerMethod = (HandlerMethod)handler; ? ? ? ? MethodParameter [] parameters = handlerMethod.getMethodParameters(); ? ? ? ? return true;//放行 ? ? } ? ? ? @Override ? ? public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { ? ? ? ? //在攔截器鏈中,只要有一個(gè)不放行的,所有的postHandle都不會(huì)執(zhí)行 ? ? ? ? //如果Controller方法拋異常了,所有的postHandle也不會(huì)執(zhí)行 ? ? ? ? System.out.println("postHandle"); ? ? } ? ? ? @Override ? ? public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { ? ? ? ? //只要對(duì)應(yīng)的preHandle放行了就一定會(huì)執(zhí)行,Controller方法拋異常也不會(huì)影響 ? ? ? ? System.out.println("afterCompletion"); ? ? } ? ? ? @Override ? ? public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ? ? ? ? System.out.println("afterConcurrentHandlingStarted"); ? ? } }
使攔截器生效
//Springboot 是1.x版本的項(xiàng)目中是extends WebMvcConfigurerAdapter ,代碼也是一樣的 @Configuration public class InterceptorConfig implements WebMvcConfigurer { ? ? ? @Autowired ? ? private SourceAccessInterceptor interceptor; ? ? @Autowired ? ? private InterceptorOne interceptorOne; ? ? @Override ? ? public void addInterceptors(InterceptorRegistry interceptorRegistry) { ? ? ? ? //1.加入的順序就是攔截器執(zhí)行的順序,設(shè)置@Order也不會(huì)影響 ? ? ? ? //2.按順序執(zhí)行所有攔截器的preHandle ? ? ? ? //3.所有的preHandle 執(zhí)行完再反向執(zhí)行全部postHandle 最后是反向執(zhí)行afterCompletion, ? ? ? ? //如果其中有一個(gè)未放行,或者拋異常了會(huì)影響執(zhí)行順序嗎?怎樣影響 ? ? ? ? interceptorRegistry.addInterceptor(interceptor).addPathPatterns("/**"); ? ? ? ? interceptorRegistry.addInterceptor(interceptorOne); ? ? } }
應(yīng)用示例
這個(gè)攔截器是用來(lái)攔截請(qǐng)求是否有攜帶token的,如果請(qǐng)求未攜帶token,將會(huì)302重定向到登錄界面。
@Component public class AuthInterceptor extends HandlerInterceptorAdapter {? ?? ? ? @Autowired ? ? private JwtUtil jwtUtil; ? ? ? @Value("${login.url}") ? ? private String loginUrl; ? ? ? /** ? ? ?* 驗(yàn)證access_token ? ? ?* ? ? ?* @param request ?請(qǐng)求 ? ? ?* @param response 響應(yīng) ? ? ?* @param handler ?處理器controller ? ? ?*/ ? ? @Override ? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ? ? ? ? ? HandlerMethod handlerMethod = (HandlerMethod) handler; ? ? ? ? //WithoutToken是我自定義的注解,標(biāo)注在方法上,表示不需要驗(yàn)證token ? ? ? ? if (handlerMethod.getMethod().isAnnotationPresent(WithoutToken.class)) { ? ? ? ? ? ? //不需要驗(yàn)證token ? ? ? ? ? ? return true; ? ? ? ? } else { ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? //校驗(yàn)jwt ? ? ? ? ? ? ? ? String access_token = request.getHeader("access_token"); ? ? ? ? ? ? ? ? jwtUtil.verifierToken(access_token); ? ? ? ? ? ? ? ? //獲取用戶信息 ? ? ? ? ? ? ? ? final String account = jwtUtil.getAccount(access_token); ? ? ? ? ? ? ? ? //TODO 可以在這里查詢用戶信息,然后將用戶信息設(shè)置到線程變量 ? ? ? ? ? ? ? ?? ? ? ? ? ? ? } catch (NullPointerException | JWTVerificationException e) { ? ? ? ? ? ? ? ? //TODO 重定向到登陸頁(yè) ? ? ? ? ? ? ? ? response.sendRedirect(loginUrl); ? ? ? ? ? ? ? ? return false; ? ? ? ? ? ? } ? ? ? ? ? ? return true; ? ? ? ? ? } ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
java中Sources目錄Resources目錄的區(qū)別解讀
這篇文章主要介紹了java中Sources目錄Resources目錄的區(qū)別解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12一文徹底弄懂零拷貝原理以及java實(shí)現(xiàn)
零拷貝(英語(yǔ): Zero-copy) 技術(shù)是指計(jì)算機(jī)執(zhí)行操作時(shí),CPU不需要先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個(gè)特定區(qū)域,下面這篇文章主要給大家介紹了關(guān)于零拷貝原理以及java實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2021-08-08Java多線程中的ReentrantLock可中斷鎖詳細(xì)解讀
這篇文章主要介紹了Java多線程中的ReentrantLock可中斷鎖詳細(xì)解讀,ReentrantLock中的lockInterruptibly()方法使得線程可以在被阻塞時(shí)響應(yīng)中斷,比如一個(gè)線程t1通過(guò)lockInterruptibly()方法獲取到一個(gè)可重入鎖,并執(zhí)行一個(gè)長(zhǎng)時(shí)間的任務(wù),需要的朋友可以參考下2023-12-12java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序
這篇文章主要介紹了java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03解決idea每次新建項(xiàng)目都需要重新指定maven目錄
這篇文章主要介紹了解決idea每次新建項(xiàng)目都需要配置maven,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Java實(shí)現(xiàn)自定義LinkedList類的示例代碼
LinkedList類跟ArrayList類不同,它通過(guò)指針以及結(jié)點(diǎn)的操作對(duì)鏈表進(jìn)行增刪改查。本文就來(lái)和大家分享下Java如何為實(shí)現(xiàn)自定義LinkedList類,需要的可以參考一下2022-08-08