整合 Springboot 攔截器和過濾器的使用


Springboot

1:攔截器(Interceptor)

java中的攔截器是動態攔截action調用的對象。依賴於web框架,在springmvc中依賴於SpringMVC框架,在實現上基於Java的反射機制,屬於AOP的一種應用,作用類似於過濾器,但是攔截器只能對Controller請求進行攔截,對其他的直接訪問靜態資源的請求無法攔截處理。

攔截器可以攔截前端請求,定義攔截器需要實現 HandlerInterceptor 接口,然后根據需求重寫preHandle,postHandle,afterCompletion三個方法。

 

 

/** * 攔截器 * * @program: myspringboot * @author: syt * @create: 2020-03-05 21:11 */ @Component @Slf4j public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("前置攔截器****"); //返回true表示通過請求,返回false表示請求被攔截 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("后置攔截器****"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("攔截器執行完成****"); } } 復制代碼

想要讓自己的攔截器生效需要進行webmvc配置,自定義一個配置類實現WebMvcConfigurer接口,然后重寫addInterceptors方法添加需要攔截的路徑,JDK1.8以前都是繼承於WebMvcConfigurerAdapter然后重新其中的方法,但是JDK1.8支持接口默認方法,官方就定義了可以不用繼承WebMvcConfigurerAdapter直接實現WebMvcConfigurer即可。

**
 * 配置攔截器和過濾器
 *
 * @program: myspringboot * @author: syt * @create: 2020-03-05 21:16 */ @Configuration public class MyConfig implements WebMvcConfigurer { @Autowired private MyInterceptor myInterceptor; /** * 添加攔截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { //addPa-thPatterns 用於添加攔截規則 //excludePathPatterns 用於排除攔截 /*要執行的攔截器*/ registry.addInterceptor(myInterceptor). addPathPatterns("/**"). excludePathPatterns("/**/login", "/**/esProductinfo/**"); } /** * 解決跨域問題 * 源(origin)就是協議、域名和端口號。 * URL由協議、域名、端口和路徑組成,如果兩個URL的協議、域名和端口全部相同, * 則表示他們同源。否則,只要協議、域名、端口有任何一個不同,就是跨域 * * @param registry */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/*") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH") .maxAge(3600); } } 復制代碼

自定義自己的配置類也可以繼承WebMvcConfigurationSupport類。這個類有許多默認的配置,但是如果繼承了WebMvcConfigurationSupport這個類,SpringBoot的mvc自動裝配就好失效,默認配置都需要自己定義,如靜態文件地址 /**,需要重新addResourceHandlers方法添加靜態文件地址

/** * 配置攔截器和過濾器 * * @program: myspringboot * @author: syt * @create: 2020-03-05 21:16 */ @Configuration public class MyConfig extends WebMvcConfigurationSupport { @Autowired private MyInterceptor myInterceptor; /** * 靜態資源 * * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); registry.addResourceHandler("/static/**").addResourceLocations("classpath:/META-INF/resources/static/"); } /** * 添加攔截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { //addPa-thPatterns 用於添加攔截規則 //excludePathPatterns 用於排除攔截 /*要執行的攔截器*/ registry.addInterceptor(myInterceptor). addPathPatterns("/**"). excludePathPatterns("/**/login", "/**/esProductinfo/**"); } /** * 解決跨域問題 * 源(origin)就是協議、域名和端口號。 * URL由協議、域名、端口和路徑組成,如果兩個URL的協議、域名和端口全部相同, * 則表示他們同源。否則,只要協議、域名、端口有任何一個不同,就是跨域 * * @param registry */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/*") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH") .maxAge(3600); } } 復制代碼

2:過濾器(filter)

方式一

對目標資源的請求和響應進行過濾截取。在請求到達servlet之前,進行邏輯判斷,判斷是否放行到servlet;也可以在一個響應response到達客戶端之前進行過濾,判斷是否允許返回客戶端。

定義過濾器需要實現Filter接口

@Slf4j public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("MyFilter的init方法"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("MyFilter的doFilter方法"); //這里可以加一個判斷,在過濾器請求不通過時可以返回自己的信息 if (false) { filterChain.doFilter(servletRequest, servletResponse); return; } else { servletResponse.setContentType("text/html;charset=UTF-8;"); PrintWriter out = servletResponse.getWriter(); out.write("過濾器不通過"); log.info("過濾器不通過"); out.flush(); out.close(); return; } } @Override public void destroy() { log.info("MyFilter的destroy方法"); } } 復制代碼

想要讓過濾器生效需要進行配置

@Configuration public class MyConfig{ /** * 添加filter * * @return */ @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); //該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理 registration.addInitParameter("targetFilterLifecycle", "true"); registration.setEnabled(true); //filter的執行順序,數字小先執行 registration.setOrder(1); //需要攔截的url路徑 registration.addUrlPatterns("/demand/*", "/notice/*", "/query/*"); return registration; } } 復制代碼

方式二

可以直接用@WebFilter注解加@Component注解直接就可以創建過濾器了

@Slf4j @Component @WebFilter(filterName = "myFilter",urlPatterns = "/*") public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("MyFilter的init方法"); } /** * 這里是過濾請求的方法 */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.info("MyFilter的doFilter方法"); if (false) { filterChain.doFilter(servletRequest, servletResponse); return; } else { servletResponse.setContentType("text/html;charset=UTF-8;"); PrintWriter out = servletResponse.getWriter(); out.write("過濾器不通過"); log.info("過濾器不通過"); out.flush(); out.close(); return; } } @Override public void destroy() { log.info("MyFilter的destroy方法"); } } 復制代碼

感覺攔截器和過濾器很像,都是可以攔截請求做相應的處理。接下來說下他倆的具體區別。

①:攔截器是基於java的反射機制,而過濾器基於函數回調。 ②:過濾器依賴於servlet容器,攔截器不依賴於servlet容器。 ③:攔截器只能對action請求起作用,而過濾器幾乎對所有的請求都起作用。 ④:攔截器可以訪問action上下文,值棧里的對象,而過濾器不能。 ⑤:在action的生命周期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。 ⑥:攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,(在攔截器里注入一個service,可以調用業務邏輯)。 ⑦:過濾器是在請求進入容器后,但進入servlert前進行預處理的。響應請求也是,在servlet處理結束后,返回給客戶端前觸發。而攔截器提供了三個方法支持(1)preHandle:預處理回調方法,實現處理器的預處理(如登錄檢查),第三個參數為響應的處理器(如我們上一章的Controller實現); 返回值:true表示繼續流程(如調用下一個攔截器或處理器);false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;postHandle:后處理回調方法,實現處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能為null。 afterCompletion:整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間並輸出消耗時間,還可以進行一些資源清理,類似於try-catch-finally中的finally,但僅調用處理器執行鏈中preHandle返回true的攔截器的afterCompletion。

碼雲地址:gitee.com/sytsuccess/…

參考鏈接:blog.csdn.net/u013806366/…


作者:着迷。
鏈接:https://juejin.im/post/5e639f33f265da570829f63c
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM