詳解java中spring里的三大攔截器
Filter
新建 TimeFilter
@Component public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("time filter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("time filter start"); long startTime = System.currentTimeMillis(); filterChain.doFilter(servletRequest, servletResponse); long endTime = System.currentTimeMillis(); System.out.println("time filter consume " + (endTime - startTime) + " ms"); System.out.println("time filter end"); } @Override public void destroy() { System.out.println("time filter init"); } }
啟動(dòng)服務(wù)器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺(tái)輸出如下結(jié)果:
time filter start
name: tom
time filter consume 3 ms
time filter end
可以看到,filter 先執(zhí)行,再到真正執(zhí)行 HelloController.sayHello() 方法。
通過(guò) TimeFilter.doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 方法的參數(shù)可以看出,我們只能得到原始的 request 和 response對(duì)象,不能得到這個(gè)請(qǐng)求被哪個(gè) Controller 以及哪個(gè)方法處理了,使用Interceptor 就可以獲得這些信息。
Interceptor
新建 TimeInterceptor
@Component public class TimeInterceptor extends HandlerInterceptorAdapter { private final NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("startTimeThreadLocal"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("time interceptor preHandle"); HandlerMethod handlerMethod = (HandlerMethod) handler; // 獲取處理當(dāng)前請(qǐng)求的 handler 信息 System.out.println("handler 類(lèi):" + handlerMethod.getBeanType().getName()); System.out.println("handler 方法:" + handlerMethod.getMethod().getName()); MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); for (MethodParameter methodParameter : methodParameters) { String parameterName = methodParameter.getParameterName(); // 只能獲取參數(shù)的名稱(chēng),不能獲取到參數(shù)的值 //System.out.println("parameterName: " + parameterName); } // 把當(dāng)前時(shí)間放入 threadLocal startTimeThreadLocal.set(System.currentTimeMillis()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("time interceptor postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 從 threadLocal 取出剛才存入的 startTime Long startTime = startTimeThreadLocal.get(); long endTime = System.currentTimeMillis(); System.out.println("time interceptor consume " + (endTime - startTime) + " ms"); System.out.println("time interceptor afterCompletion"); } }
注冊(cè) TimeInterceptor
把 TimeInterceptor 注入 spring 容器
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private TimeInterceptor timeInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }
啟動(dòng)服務(wù)器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺(tái)輸出如下結(jié)果:
time filter start time interceptor preHandle handler 類(lèi):com.nextyu.demo.web.controller.HelloController handler 方法:sayHello name: tom time interceptor postHandle time interceptor consume 40 ms time interceptor afterCompletion time filter consume 51 ms time filter end
可以看到,filter 先于 interceptor 執(zhí)行,再到真正執(zhí)行 HelloController.sayHello() 方法。通過(guò) interceptor 方法上的 handler 參數(shù),我們就可以得到這個(gè)請(qǐng)求被哪個(gè) Controller 以及哪個(gè)方法處理了。但是不能直接獲取到這個(gè)方法上的參數(shù)值(在這里就是 HelloController.sayHello(String name) 方法參數(shù) name 的值),通過(guò) Aspect 就可以獲取到。
Aspcet
新建 TimeAspect
@Aspect @Component public class TimeAspect { @Around("execution(* com.nextyu.demo.web.controller.*.*(..))") public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); Object[] args = pjp.getArgs(); for (Object arg : args) { System.out.println("arg is " + arg); } long startTime = System.currentTimeMillis(); Object object = pjp.proceed(); long endTime = System.currentTimeMillis(); System.out.println("time aspect consume " + (endTime - startTime) + " ms"); System.out.println("time aspect end"); return object; } }
啟動(dòng)服務(wù)器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺(tái)輸出如下結(jié)果:
time filter start time interceptor preHandle handler 類(lèi):com.nextyu.demo.web.controller.HelloController handler 方法:sayHello time aspect start arg is tom name: tom time aspect consume 0 ms time aspect end time interceptor postHandle time interceptor consume 2 ms time interceptor afterCompletion time filter consume 4 ms time filter end
可以看到,filter 先執(zhí)行,再到 interceptor 執(zhí)行,再到 aspect 執(zhí)行,再到真正執(zhí)行 HelloController.sayHello() 方法。
我們也獲取到了 HelloController.sayHello(String name) 方法參數(shù) name 的值。
請(qǐng)求攔截過(guò)程圖
graph TD httprequest-->filter filter-->interceptor interceptor-->aspect aspect-->controller
- Java中過(guò)濾器 (Filter) 和 攔截器 (Interceptor)的使用
- 聊聊java 過(guò)濾器、監(jiān)聽(tīng)器、攔截器的區(qū)別(終結(jié)篇)
- 通過(guò)實(shí)例解析java過(guò)濾器和攔截器的區(qū)別
- Java中的攔截器、過(guò)濾器、監(jiān)聽(tīng)器用法詳解
- 淺析JAVA中過(guò)濾器、監(jiān)聽(tīng)器、攔截器的區(qū)別
- 了解java Struts攔截器的相關(guān)操作
- Java中的Struts2框架攔截器之實(shí)例代碼
- 應(yīng)用市場(chǎng)中Java攔截器和切面的使用實(shí)例詳解
- Java攔截器和過(guò)濾器的區(qū)別分析
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)排序算法之樹(shù)形選擇排序詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)排序算法之樹(shù)形選擇排序,結(jié)合具體實(shí)例形式分析了java樹(shù)形選擇排序的原理、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-05-05struts2如何使用攔截器進(jìn)行用戶(hù)權(quán)限控制實(shí)例
本篇文章主要介紹了struts2如何使用攔截器進(jìn)行用戶(hù)權(quán)限控制實(shí)例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05Java實(shí)現(xiàn)Excel表單控件的添加與刪除
本文通過(guò)Java代碼示例介紹如何在Excel表格中添加表單控件,包括文本框、單選按鈕、復(fù)選框、組合框、微調(diào)按鈕等,以及如何刪除Excel中的指定表單控件,需要的可以參考一下2022-05-05Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法
這篇文章主要介紹了Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java和scala實(shí)現(xiàn) Spark RDD轉(zhuǎn)換成DataFrame的兩種方法小結(jié)
今天小編就為大家分享一篇Java和scala實(shí)現(xiàn) Spark RDD轉(zhuǎn)換成DataFrame的兩種方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06Intellij IDEA 旗艦版創(chuàng)建 Spring MVC 項(xiàng)目踩過(guò)的坑
IDEA旗艦版可以直接創(chuàng)建Spring MVC項(xiàng)目,但創(chuàng)建后的項(xiàng)目并不是直接就可以運(yùn)行,還需要進(jìn)行一些配置。這篇文章主要介紹了Intellij IDEA 旗艦版創(chuàng)建 Spring MVC 項(xiàng)目踩坑記 ,需要的朋友可以參考下2020-03-03Hadoop?MapReduce實(shí)現(xiàn)單詞計(jì)數(shù)(Word?Count)
這篇文章主要為大家詳細(xì)介紹了如何利用Hadoop實(shí)現(xiàn)單詞計(jì)數(shù)(Word?Count)的MapReduce,文中的示例代碼講解詳細(xì),感興趣的可以跟隨小編一起學(xué)習(xí)一下2023-05-05Spring?MVC??接受請(qǐng)求參數(shù)的方法
了解HTTP請(qǐng)求的GET和POST方法中如何攜帶參數(shù),以及SpringMVC中如何接收這些參數(shù),GET方法通過(guò)URL傳遞參數(shù),而POST方法通常在請(qǐng)求體中傳遞,SpringMVC使用注解如@RequestParam和@RequestBody來(lái)綁定參數(shù)到控制器方法2024-09-09