詳解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"); } }
啟動服務器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺輸出如下結(jié)果:
time filter start
name: tom
time filter consume 3 ms
time filter end
可以看到,filter 先執(zhí)行,再到真正執(zhí)行 HelloController.sayHello() 方法。
通過 TimeFilter.doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 方法的參數(shù)可以看出,我們只能得到原始的 request 和 response對象,不能得到這個請求被哪個 Controller 以及哪個方法處理了,使用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; // 獲取處理當前請求的 handler 信息 System.out.println("handler 類:" + handlerMethod.getBeanType().getName()); System.out.println("handler 方法:" + handlerMethod.getMethod().getName()); MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); for (MethodParameter methodParameter : methodParameters) { String parameterName = methodParameter.getParameterName(); // 只能獲取參數(shù)的名稱,不能獲取到參數(shù)的值 //System.out.println("parameterName: " + parameterName); } // 把當前時間放入 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"); } }
注冊 TimeInterceptor
把 TimeInterceptor 注入 spring 容器
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private TimeInterceptor timeInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }
啟動服務器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺輸出如下結(jié)果:
time filter start time interceptor preHandle handler 類: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() 方法。通過 interceptor 方法上的 handler 參數(shù),我們就可以得到這個請求被哪個 Controller 以及哪個方法處理了。但是不能直接獲取到這個方法上的參數(shù)值(在這里就是 HelloController.sayHello(String name) 方法參數(shù) name 的值),通過 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; } }
啟動服務器,在瀏覽器輸入:http://localhost:8080/hello?name=tom
可以在控制臺輸出如下結(jié)果:
time filter start time interceptor preHandle handler 類: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 的值。
請求攔截過程圖
graph TD httprequest-->filter filter-->interceptor interceptor-->aspect aspect-->controller
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)排序算法之樹形選擇排序詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)排序算法之樹形選擇排序,結(jié)合具體實例形式分析了java樹形選擇排序的原理、實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下2017-05-05struts2如何使用攔截器進行用戶權(quán)限控制實例
本篇文章主要介紹了struts2如何使用攔截器進行用戶權(quán)限控制實例,非常具有實用價值,需要的朋友可以參考下2017-05-05Java對世界不同時區(qū)timezone之間時間轉(zhuǎn)換的處理方法
這篇文章主要介紹了Java對世界不同時區(qū)timezone之間時間轉(zhuǎn)換的處理方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07Java和scala實現(xiàn) Spark RDD轉(zhuǎn)換成DataFrame的兩種方法小結(jié)
今天小編就為大家分享一篇Java和scala實現(xiàn) Spark RDD轉(zhuǎn)換成DataFrame的兩種方法小結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06Intellij IDEA 旗艦版創(chuàng)建 Spring MVC 項目踩過的坑
IDEA旗艦版可以直接創(chuàng)建Spring MVC項目,但創(chuàng)建后的項目并不是直接就可以運行,還需要進行一些配置。這篇文章主要介紹了Intellij IDEA 旗艦版創(chuàng)建 Spring MVC 項目踩坑記 ,需要的朋友可以參考下2020-03-03Hadoop?MapReduce實現(xiàn)單詞計數(shù)(Word?Count)
這篇文章主要為大家詳細介紹了如何利用Hadoop實現(xiàn)單詞計數(shù)(Word?Count)的MapReduce,文中的示例代碼講解詳細,感興趣的可以跟隨小編一起學習一下2023-05-05