天天看點

JavaWeb(四)Filter與Listener學習

Filter

1.web中的過濾器:

當通路伺服器的資源時,過濾器可以将請求攔截下來,完成一些特殊的功能。

2.過濾器的作用:

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

3.簡單使用:

建立類,實作接口Filter

@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() {
		
	}
}
           

4.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>
           

5.過濾器執行流程

(1)執行過濾器

(2)執行放行後的資源

(3)回來執行過濾器放行代碼下邊的代碼

6.過濾器生命周期方法

(1)init:在伺服器啟動後,會建立Filter對象,然後調用init方法。隻執行一次。用于加載資源

(2)doFilter:每一次請求被攔截資源時,會執行。執行多次

(3)destroy:在伺服器關閉後,Filter對象被銷毀。如果伺服器是正常關閉,則會執行destroy方法。隻執行一次。用于釋放資源

7.過濾器配置詳解:

攔截路徑配置

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

攔截方式配置:資源被通路的方式

(1)注解配置:
    設定dispatcherTypes屬性:
        REQUEST:預設值。浏覽器直接請求資源
        FORWARD:轉發通路資源
        INCLUDE:包含通路資源
        ERROR:錯誤跳轉資源
        ASYNC:異步通路資源
(2)web.xml配置:
	設定<dispatcher></dispatcher>标簽即可
           

8.過濾器鍊(配置多個過濾器)

執行順序:如果有兩個過濾器:過濾器1和過濾器2

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

過濾器先後順序問題:

1. 注解配置:按照類名的字元串比較規則比較,值小的先執行
	* 如: AFilter 和 BFilter,AFilter就先執行了。
2. web.xml配置: <filter-mapping>誰定義在上邊,誰先執行
           

9.敏感詞彙過濾:(案例)

* 增強對象的功能:
			* 設計模式:一些通用的解決固定問題的方式
			1. 裝飾模式
			2. 代理模式
				* 概念:
					1. 真實對象:被代理的對象
					2. 代理對象:
					3. 代理模式:代理對象代理真實對象,達到增強真實對象功能的目的
			 	* 實作方式:
				 	1. 靜态代理:有一個類檔案描述代理模式
				 	2. 動态代理:在記憶體中形成代理類
						* 實作步驟:
							1. 代理對象和真實對象實作相同的接口
							2. 代理對象 = Proxy.newProxyInstance();
							3. 使用代理對象調用方法。
							4. 增強方法

						* 增強方式:
							1. 增強參數清單
							2. 增強傳回值類型
							3. 增強方法體執行邏輯
           
//敏感詞彙過濾器
@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;
                }
                //判斷方法名是否是 getParameterMap
                //判斷方法名是否是 getParameterValue
                return method.invoke(req,args);
            }
        });

        //2.放行
        chain.doFilter(proxy_req, resp);
    }
    private List<String> list = new ArrayList<String>();//敏感詞彙集合
    public void init(FilterConfig config) throws ServletException {

        try{
            //1.擷取檔案真實路徑
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感詞彙.txt");
            //2.讀取檔案
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            //3.将檔案的每一行資料添加到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() {
    }
}
           

Listener:監聽器

1.監聽機制:

* 事件	:一件事情
* 事件源 :事件發生的地方
* 監聽器 :一個對象
* 注冊監聽:将事件、事件源、監聽器綁定在一起。 當事件源上發生某個事件後,執行監聽器代碼
           

2.ServletContextListener:

監聽ServletContext對象的建立和銷毀

* 方法:
	* void contextDestroyed(ServletContextEvent sce) :ServletContext對象被銷毀之前會調用該方法
	* void contextInitialized(ServletContextEvent sce) :ServletContext對象建立後會調用該方法
    
* 步驟:
		1. 定義一個類,實作ServletContextListener接口
		2. 複寫方法
		3. 配置
			1. web.xml
			<listener>
 			 <listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
            </listener>

			* 指定初始化參數<context-param>
           2.注解方式:
                @WebListener
           

3.監聽器的入門:

在伺服器開啟時建立對象,關閉時被破壞:

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;

@WebListener
public class ContextLoaderListener implements ServletContextListener {
    /**
     * 監聽ServletContext對象建立的。ServletContext對象伺服器啟動後自動建立。
     *
     * 在伺服器啟動後自動調用
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加載資源檔案
        //1.擷取ServletContext對象
        ServletContext servletContext = servletContextEvent.getServletContext();
        //2.加載資源檔案
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        //3.擷取真實路徑
        String realPath = servletContext.getRealPath(contextConfigLocation);
        //4.加載進記憶體
        try{
            FileInputStream fis = new FileInputStream(realPath);
            System.out.println(fis);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("ServletContext對象被建立了。。。");
    }
    /**
     * 在伺服器關閉後,ServletContext對象被銷毀。當伺服器正常關閉後該方法被調用
     * @param servletContextEvent
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext對象被銷毀了。。。");
    }
}

           

繼續閱讀