JavaWeb - Filter過濾器、Listener監聽器
阿新 • • 發佈:2020-08-06
1.Filter過濾器
1. 作用:
* 一般用於完成通過的操作。如:登入驗證、統一編碼處理、敏感字元的過濾。。。
2. 快速入門
1. 步驟:
1. 定義一個類,實現介面Filter
2. 複寫方法
3. 配置攔截路徑
1. web.xml
2. 註解
package web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(demo01"/*") //訪問資源之前,都會執行該過濾器 public class FilterDemo01 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("過濾器被執行了...."); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
3. 過濾器細節
1. web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocationweb.xml="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>demo01</filter-name> <filter-class>web.filter.FilterDemo01</filter-class> </filter> <filter-mapping> <filter-name>demo01</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
2. 過濾器執行流程
1. 執行過濾器
2. 執行放行後的資源
3. 回來執行過濾器放行程式碼下的程式碼
3. 過濾器生命週期方法
4. 過濾器配置詳解
* 攔截路徑配置:
1. 具體的資源路徑:/index.jsp 只有訪問index.jsp資源時,過濾器才會被執行
2. 目錄攔截: / user / * 訪問/ user下的所有資源時,過濾器都會被執行
3. 字尾名攔截:* . jsp 訪問所有後綴名為jsp資源時,過濾器都會被執行
4. 攔截所有資源: / *
* 攔截方式配置:資源被訪問的方式
* 註解配置:
* 設定dispatcherTypes屬性
1. REQUEST:預設值。瀏覽器直接請求資源
2. FORWARD:轉發訪問資源
3. INCLUDE:包含訪問資源
4. ERROR:錯誤跳轉資源
5. ASYNV:非同步訪問資源
web.xml配置:
* 設定<dispatcher></dispatcher>標籤即可
5. 過濾器鏈(配置多個過濾器)
* 執行順序:瀏覽器 - 過濾器1 - 過濾器2 - 資源執行 - 過濾器2 - 過濾器1 - 瀏覽器
* 過濾器先後順序問題:
1. 註解配置:按照類名的字串比較規則比較,值小的先執行
* 如:AFilter 和 BFilter,AFilter先執行
2. web.xml配置:<FilterMapping>誰定義在上面,誰先執行
4. 案例1:登入驗證
* 需求:
1. 訪問某一資源頁面,驗證其是否登入,登入了直接放行
2. 如果沒有登入,則跳轉到登入頁面,提示“您尚未登入,請先登入”。
package web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** * 完成登入驗證的過濾器 */ @WebFilter("/*") public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //0. 強制轉換 HttpServletRequest request = (HttpServletRequest) req; //1. 獲取資源的請求路徑 String uri = request.getRequestURI(); //2. 判斷是否包含登入相關資源路徑,要注意排除掉 css/js/圖片/驗證碼等資源 if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts.") || uri.contains("/checkCodeServlet")){ //包含,證明使用者就是想登入 chain.doFilter(req,resp); }else { // 不包含,需要去驗證使用者是否登入 //3. 從session中獲取user Object user = request.getSession().getAttribute("user"); if(user != null){ // 登陸了,放行 chain.doFilter(req, resp); }else { // 沒有登入。跳轉登入頁面 request.setAttribute("login_msg","您尚未登入,請登入"); request.getRequestDispatcher("/login.jsp").forward(req,resp ); } } } public void init(FilterConfig config) throws ServletException { } public void destroy() { } }登入過濾器實現
5. 案例2:敏感詞彙過濾
* 需求:
1. 對錄入的資料進行敏感詞彙過濾
2. 敏感詞彙參考(敏感詞彙.txt)
3. 如果是敏感詞彙,替換為 ***
* 分析:
1. 對request物件進行增強。增強獲取引數的相關方法
2. 放行,傳遞代理物件
* 增強物件的功能:
* 設計模式:一些通用的解決固定問題的方式
* 裝飾模式
* 代理模式:
* 概念:
1. 真實物件:被代理的物件
2. 代理物件
3. 代理模式:代理物件代理真實物件,來達到增強真實物件功能的目的
* 實現方式:
1. 靜態代理:有一個類檔案來描述代理模式
2. 動態代理:在記憶體中形成代理類
* 實現步驟:
1. 代理物件和真實物件實現相同的介面
2. 代理物件 = Proxy.newProxyInstance();
三個引數:
1. 類載入器:真實物件 . getClass(). getClassLoader()
2. 介面陣列:真實物件 . getClass(). getInterfaces()
3. 處理器:new InvocationHandler()
3. 使用代理物件呼叫方法:
* invoke 代理邏輯編寫的方法:代理物件呼叫的所有方法都會觸發該方法的執行
引數:
1. proxy:代理物件
2. method:代理物件呼叫的方法被封裝成的物件
3. args:代理物件呼叫的方法時,傳遞的實際引數
4. 增強方式:
1. 增強引數列表
2. 增強返回值型別
3. 增強方法體執行邏輯
package web.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { //1. 建立真實物件 Lenovo lenovo = new Lenovo(); //2. 動態代理增強Lenova SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() { /* invoke 代理邏輯編寫的方法:代理物件呼叫的所有方法都會觸發該方法的執行 引數: 1. proxy:代理物件 2. method:代理物件呼叫的方法被封裝成的物件 3. args:代理物件呼叫的方法時,傳遞的實際引數 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //判斷是否是sale方法 if(method.getName().equals("sale")){ //1. 增強引數 double money = (double) args[0]; money = money * 0.85; // 使用真實物件呼叫該方法 String obj = (String) method.invoke(lenovo, money); //2. 增強返回值 return obj + "送滑鼠墊"; }else { Object obj = method.invoke(lenovo,args); return obj; } } }); String computer = proxy_lenovo.sale(8000); System.out.println(computer); } }
package web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; /** * 敏感詞彙過濾器 */ @WebFilter("/*") public class SensitiveWordsFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //1. 建立代理物件,增強getParameter方法 ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 增強getParameter方法 // 判斷是否是getParameter方法 if(method.getName().equals("getParameter")){ // 增強返回值 // 獲取返回值 String value = (String) method.invoke(req, args); if(value != null){ for (String str : list) { if(value.contains(str)){ //表示包含敏感字元 value = value.replaceAll(str,"***"); } } } return value; } // 如果不是這個方法 就該怎麼執行就怎麼執行 return method.invoke(req,args); } }); //2. 放行 chain.doFilter(proxy_req, resp); } // 裝敏感詞彙的集合 List<String> list = new ArrayList<String>(); public void init(FilterConfig config) throws ServletException { try { // 載入檔案,獲取檔案的真實路徑 ServletContext servletContext = config.getServletContext(); String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感詞彙.txt"); // 讀取檔案 BufferedReader br = new BufferedReader(new FileReader(realPath)); // 將檔案的每一行資料新增到list中 String line = null; while ((line = br.readLine())!=null){ list.add(line); } br.close(); System.out.println(list); }catch (Exception e){ e.printStackTrace(); } } public void destroy() { } }敏感詞彙過濾器實現