javascript
【转载】Spring Boot 过滤器、监听器、拦截器的使用
關注“Java后端技術全棧”
回復“面試”獲取全套大廠面試資料
在開發中用到過濾器、監聽器、攔截器的場景非常多,今天就來聊聊這三者在日常開發中是如何使用的。
概念和使用場景
監聽器
listener是servlet規范中定義的一種特殊類。用于監聽servletContext、HttpSession和servletRequest等域對象的創建和銷毀事件。
實現方式:實現接口javax.servlet.http.HttpSessionListener
其主要可用于以下方面:
統計在線人數和在線用戶
系統啟動時加載初始化信息
統計網站訪問量
記錄用戶訪問路徑
過濾器
Filter是Servlet技術中最實用的技術,Web開發人員通過Filter技術,對web服務器管理的所有web資源。過濾器是在請求進入tomcat容器后,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完后,返回給前端之前。
例如Jsp, Servlet, 靜態圖片文件或靜態 html 文件等進行攔截,從而實現一些特殊的功能
例如實現URL級別的權限訪問控制、過濾敏感詞匯、壓縮響應信息等一些高級功能
它主要用于對用戶請求進行預處理,也可以對HttpServletResponse進行后處理。使用Filter的完整流程:Filter對用戶請求進行預處理,接著將請求交給Servlet進行處理并生成響應,最后Filter再對服務器響應進行后處理。過濾器只在servlet前后起作用,所以它既不能捕獲異常,獲得bean對象等
實現方式:實現接口javax.servlet.Filter
攔截器
攔截器中用于在某個方法或字段被訪問之前,進行攔截然后,在之前或之后加入某些操作。比如日志,安全等。一般攔截器方法都是通過動態代理的方式實現。可以通過它來進行權限驗證,或者判斷用戶是否登陸,或者是像12306 判斷當前時間是否是購票時間。通常在項目開發中基本上都會做一個異常統一攔截處理的地方。對比一下其實我們可以發現,過濾器能做的事攔截器都能做,二攔截器做的事過濾器不一定做的了。
實現方式:實現org.springframework.web.servlet.HandlerInterceptor
三者對比
攔截器和過濾器:過濾前->攔截前->action/controller執行->攔截后->過濾后
為了讓大家更好的理解,這里借用網上幾張圖:
實戰
項目繼續使用之前文章中用到的項目。
添加過濾器
import?java.io.IOException;import?javax.servlet.Filter; import?javax.servlet.FilterChain; import?javax.servlet.FilterConfig; import?javax.servlet.ServletException; import?javax.servlet.ServletRequest; import?javax.servlet.ServletResponse; import?javax.servlet.http.HttpServletRequest; import?javax.servlet.http.HttpServletResponse; import?javax.servlet.http.HttpServletResponseWrapper;public?class?UserFilter?implements?Filter?{@Overridepublic?void?doFilter(ServletRequest?servletRequest,?ServletResponse?servletResponse,?FilterChain?filterChain)?throws?IOException,?ServletException?{System.out.println(servletRequest.getParameter("name"));HttpServletRequest?hrequest?=?(HttpServletRequest)?servletRequest;HttpServletResponseWrapper?wrapper?=?new?HttpServletResponseWrapper((HttpServletResponse)?servletResponse);//過濾URI存在部分關鍵字的if?(hrequest.getRequestURI().indexOf("/index")?!=?-1?||hrequest.getRequestURI().indexOf("/online")?!=?-1?||hrequest.getRequestURI().indexOf("/login")?!=?-1)?{filterChain.doFilter(servletRequest,?servletResponse);}?else?{wrapper.sendRedirect("/login");}}@Overridepublic?void?destroy()?{}@Overridepublic?void?init(FilterConfig?filterConfig)?throws?ServletException?{} }自定義Filter還可以 使用Servlet3.0的注解進行配置第三步的@WebFilter就是3.0的注解
1)啟動類里面增加 @ServletComponentScan,進行掃描
2)新建一個Filter類,implements Filter,并實現對應的接口
3) @WebFilter 標記一個類為filter,被spring進行掃描
urlPatterns:攔截規則,支持正則
4)控制chain.doFilter的方法的調用,來實現是否通過放行不放行,web應用resp.sendRedirect("/index.html");場景:權限控制、用戶登錄(非前端后端分離場景)等
添加監聽器
監聽器就會聯想到監聽器設計模式。就相當于于考試的時候,考官一直盯著你們,一旦有人有動靜,考官就一直監督者你們,一旦有人作弊,考官馬上將其拿下。
import?javax.servlet.http.HttpSessionEvent; import?javax.servlet.http.HttpSessionListener;public?class?UserHttpSessionListener?implements?HttpSessionListener?{//監控在線人數public?static?int?online?=?0;@Overridepublic?void?sessionCreated(HttpSessionEvent?se)?{System.out.println("創建session");online++;}@Overridepublic?void?sessionDestroyed(HttpSessionEvent?se)?{System.out.println("銷毀session");} }添加攔截器
import?org.springframework.web.servlet.HandlerInterceptor; import?org.springframework.web.servlet.ModelAndView;import?javax.servlet.http.HttpServletRequest; import?javax.servlet.http.HttpServletResponse; import?java.io.PrintWriter;public?class?UserInterceptor?implements?HandlerInterceptor?{//進入controller方法之前@Overridepublic?boolean?preHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o)?throws?Exception?{System.out.println("preHandle被調用");System.out.println(httpServletRequest.getParameter("username"));if(httpServletRequest.getParameter("username").equals("zhangsan"))?{return?true;???}else?{//如果false,停止流程,api被攔截//通常驗證是都登錄,如果沒有登錄則進行登錄操作PrintWriter?printWriter?=?httpServletResponse.getWriter();printWriter.write("please?login?again!");return?false;}}//調用完controller之后,視圖渲染之前@Overridepublic?void?postHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?ModelAndView?modelAndView)?throws?Exception?{System.out.println("postHandle被調用");}//整個完成之后,通常用于資源清理@Overridepublic?void?afterCompletion(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?Exception?e)?throws?Exception?{System.out.println("afterCompletion被調用");} }preHandle方法是在我們的controller方法執行之前調用的。
添加配置類
package?com.example.demo.config;import?com.example.demo.filter.UserFilter; import?com.example.demo.listener.UserHttpSessionListener; import?org.springframework.boot.web.servlet.FilterRegistrationBean; import?org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import?org.springframework.context.annotation.Bean; import?org.springframework.context.annotation.Configuration; import?org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import?org.springframework.web.servlet.config.annotation.WebMvcConfigurer;//主攔截器,根據攔截不同路徑跳轉不同自定義攔截器? @Configuration public?class?UserWebConfig?implements?WebMvcConfigurer?{@Overridepublic?void?addViewControllers(ViewControllerRegistry?registry)?{registry.addViewController("/index").setViewName("login");}@SuppressWarnings({?"rawtypes",?"unchecked"?})@Beanpublic?FilterRegistrationBean?filterRegist()?{FilterRegistrationBean?frBean?=?new?FilterRegistrationBean();frBean.setFilter(new?UserFilter());frBean.addUrlPatterns("/*");System.out.println("filter");return?frBean;}@SuppressWarnings({?"rawtypes",?"unchecked"?})@Beanpublic?ServletListenerRegistrationBean?listenerRegistry()?{ServletListenerRegistrationBean?srb?=?new?ServletListenerRegistrationBean();srb.setListener(new?UserHttpSessionListener());System.out.println("listener");return?srb;} }測試類,寫個controller來測試
package?com.example.demo;import?java.util.Date; import?java.util.Map; import?java.util.UUID;import?javax.servlet.http.HttpServletRequest; import?javax.servlet.http.HttpSession;import?com.example.demo.listener.UserHttpSessionListener; import?org.slf4j.Logger; import?org.slf4j.LoggerFactory; import?org.springframework.stereotype.Controller; import?org.springframework.web.bind.annotation.GetMapping; import?org.springframework.web.bind.annotation.PathVariable; import?org.springframework.web.bind.annotation.RequestMapping; import?org.springframework.web.bind.annotation.ResponseBody;@Controller public?class?UserController?{private?final?Logger?logger?=?LoggerFactory.getLogger(UserController.class);@GetMapping("/welcome")public?String?welcome(Map<String,?Object>?model)?{model.put("time",?new?Date());model.put("message",?"hello?world");return?"welcome";}@RequestMapping("/login")@ResponseBodypublic?Object?login()?{logger.info("-----login---");return?"login";}@RequestMapping("/index/{name}")@ResponseBodypublic?Object?index(@PathVariable?String?name,?HttpServletRequest?request)?{HttpSession?session?=?request.getSession(true);session.setAttribute(UUID.randomUUID().toString(),?name);return?"index";}@RequestMapping("/online")@ResponseBodypublic?Object?online()?{return?"當前在線人數:"?+?UserHttpSessionListener.online?+?"人";} }以上便是今天分享的監聽器、過濾器、攔截器的相關知識。建議大家手動試試~
紙上得來終覺淺,絕知此事要躬行。
IT技術分享社區
個人博客網站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識
總結
以上是生活随笔為你收集整理的【转载】Spring Boot 过滤器、监听器、拦截器的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的xmgrace无法运行,科学
- 下一篇: java安全相关类 (java.secu