1. 程式人生 > >Filter&Listener

Filter&Listener

Filter&Listener

今日內容

  • Filter:過濾器
  • Listener:監聽器

Filter:過濾器

  • 概念 *web中的過濾器:當訪問伺服器資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。

  • 過濾器的作用 *一般用於完成通用的操作。如:登入驗證、統一編碼處理、敏感字元過濾…

  • 快速入門 *步驟:

    1. 定義一個類,實現介面Filter
    2. 複寫方法
    3. 配置攔截路徑 i. web.xml ii. 註解

    *程式碼 :

    @WebFilter("/*")//訪問所有資源之前,都會執行該過濾器
    	public class FilterDemo1 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
    ("filterDemo1被執行了...."); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
  • 過濾器細節:

    1. web.xml配置
    <filter>
            <filter-name>demo1</filter-name>
            <filter-class>cn.itcast.web.filter.FilterDemo1</
    filter-class
    >
    </filter> <filter-mapping> <filter-name>demo1</filter-name> <!-- 攔截路徑 --> <url-pattern>/*</url-pattern> </filter-mapping>
  • 過濾器執行流程

    1. 執行過濾器
    2. 執行放行後的資源
    3. 回來執行過濾器放行程式碼下邊的程式碼
  • 過濾器生命週期方法

    1. init:在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次。用於載入資源。
    2. doFilter:每一次請求被攔截資源時,會執行多次。
    3. destroy:在伺服器關閉後,Filter物件被銷燬。如果伺服器是被正常關閉的,會執行destroy方法,只執行一次,用於釋放資源。
  • 過濾器配置詳解 *攔截路徑配置:

    1. 具體資源路徑:/index.jsp 只有訪問index,jsp資源時,過濾器才會被執行。
    2. 攔截目錄:/user/* 訪問/user下的所有資源時,過濾器都會被執行
    3. 字尾名攔截:*.jsp 訪問所有後綴名為jsp資源時,過濾器才會被執行
    4. 攔截所有資源:/* 訪問所有資源時,過濾器都會被執行

    *攔截方式配置: i. 註解配置:設定dispatcherTypeshux 1. REQUEST:預設值。瀏覽器直接請求資源。 2. FORWARD:轉發訪問資源。 3. INCLUDE:包含訪問資源。 4. ERROR:錯誤跳轉資源。 5. ASYNC:非同步訪問資源。 ii. web.xml配置 *設定<dispatcher></dispatcher>標籤即可

  • 過濾器鏈(配置多個過濾器) *執行順序:如果有兩個過濾器:過濾器1和過濾器2

    1. 過濾器1
    2. 過濾器2
    3. 資源執行
    4. 過濾器2
    5. 過濾器1

*過濾器先後順序問題: 1. 註解和配置:按照類名的字串比較規則比較,較小的先執行 2. web.xml配置<filter-mapping>誰定義在上邊,誰先執行

  • 案列
  1. 案例1_登入驗證 * 需求: 1. 訪問day17_case案例的資源。驗證其是否登入 2. 如果登入了,則直接放行。 3. 如果沒有登入,則跳轉到登入頁面,提示"您尚未登入,請先登入"。
package web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter("/*")
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request=(HttpServletRequest)req;
        String uri = request.getRequestURI();
        if (uri.contains("/login.jsp")||uri.contains("/loginUserServlet")||uri.contains("/checkCode")||uri.contains("/css/")||uri.contains("/fonts/")||uri.contains("/js/")){
            chain.doFilter(req, resp);
        }
        else {
            HttpSession session = request.getSession();
            Object user = session.getAttribute("user");
            if (user!=null){
                chain.doFilter(request,resp);
            }else {
                request.setAttribute("login_msg","您尚未登入,請先登入!");
                request.getRequestDispatcher("/login.jsp").forward(request,resp);
            }
        }


    }

    public void init(FilterConfig config) throws ServletException {

    }

}
  1. 案例2_敏感詞彙過濾
  • 需求: 1. 對day17_case案例錄入的資料進行敏感詞彙過濾 2. 敏感詞彙參考《敏感詞彙.txt》 3. 如果是敏感詞彙,替換為 ***

  • 分析: 1. 對request物件進行增強。增強獲取引數相關方法 2. 放行。傳遞代理物件

package web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
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;
import java.util.Map;
import java.util.Set;

@WebFilter("/*")
public class SensitiveWordFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        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 {
                //  增強Parameter方法
                //判斷是否有Parameter方法
               if (method.getName().equals("getParameter")){
                   //增強返回值
                   //獲取返回值
                   String value = (String) method.invoke(req, args);
                   if (value!=null){
                   for (String s : list) {
                       if (value.contains(s)){
                            value = value.replaceAll(s, "***");
                       }
                   }}
                   return value;
               }
               if (method.getName().equals("getParameterMap")){
                   Map<String,String[]> value=(Map<String,String[]>)method.invoke(req,args);
                   if (value!=null){
                       for (String s : list) {
                           Set<String> keySet = value.keySet();
                           for (String key : keySet) {
                               String[] strs = value.get(key);
                               for (int i = 0; i < strs.length; i++) {
                                  if (strs[i].contains(s)){
                                      strs[i]=strs[i].replaceAll(s,"***");
                                  }
                               }
                           }
                       }
                       return value;
                   }
               }

               if (method.getName().equals("getParameterValues")){
                   //增強返回值
                   //獲取返回值
                   String[] value = (String[]) method.invoke(req, args);
                   if (value!=null){
                       for (String s : list) {
                           for (String str : value) {
                               if (str.contains(s)){
                                 str=str.replaceAll(s,"***");
                               }
                           }
                       }
                       return value;
                   }

               }
               return method.invoke(req,args);
            }
        });
        chain.doFilter(proxy_req, resp);

    }
      private 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));
        String len;
        while((len=br.readLine())!=null){
            list.add(len);

        }
            br.close();
            System.out.println(list);
        } catch (Exception e){
            e.printStackTrace();
        }

    }

}

Listener:監聽器

  • 概念:web的三大元件之一。

  • 事件的監聽機制:

    • 事件:一件事情
    • 事件源:事件發生的地方
    • 監聽器:一個物件
    • 註冊監聽:將事件、事件源、監聽器綁在一起。當事件源上發生某個事件後,執行監聽器程式碼
  • ServletContextListener:監聽ServletContext物件的建立和銷燬

    1. 方法: * void contextDestroyed(ServletContextEvent sce):ServletContext物件被銷燬之前會呼叫該方法 * void contextInitialized(ServletContextEvent sce):ServletContext物件建立後會呼叫該方法

    2. 步驟: * 定義一個類,實現ServletContextListener介面 * 複寫方法 * 配置 i. web.xml <listener><listener-class>全類名</listener-class> 指定初始化引數<context-param> ii. 註解: @WebListener