Filter過濾器與Listener監聽器的使用(全站中文亂碼處理)

目錄

 

一、Filter過濾器的使用

【1】Filter技術概述

【2】Filter訪問機制

【3】Filter的生命週期

【4】使用過濾器處理中文亂碼問題

二、Listener監聽器的使用

【1】監聽器技術概述

【2】監聽器的種類


一、Filter過濾器的使用

【1】Filter技術概述

Filter技術,即過濾器技術,是Servlet三大核心技術之一,主要用於攔截請求進行過濾操作,是實現例如權限控制、全站亂碼解決、壓縮響應等功能的基礎,是web開發中最實用的技術之一。

【2】Filter訪問機制

過濾器可以配置多個,多個過濾器之前採用責任鏈模式,依次進行攔截。只有所有過濾器都通過,纔可以訪問到最終的資源

如果是在web.xml中進行配置,通過<filter>和<filter-mapping>標籤實現配置。<filter-mapping>用來設置此外過濾器的虛擬路徑,只有符合過濾的虛擬路徑,纔會被過濾器攔截。不符合將不會被攔截,此外攔截的順序是通過標籤<filter-mapping>上下順序進行過濾。

如果是通過WebFilter()註解方式進行配置,可以使用filterName屬性來指定filter的名稱,可以使用value屬性或者urlPatterns屬性來指定Filter過濾的虛擬路徑。只有符合過濾的虛擬路徑,纔會被過濾器攔截。不符合將不會被攔截,此外攔截的規則是通過屬性filterName字母順序進行過濾。

【3】Filter的生命週期

在tomcat服務器啓動後加載當前web應用時,filter會創建一個對象駐留在內存當中,在創建對象之後,立刻調用init方法完成初始化的操作。每次過濾器攔截請求或響應,都會導致它身上的doFilter方法執行,在doFilter方法中可以選擇是否放行,如果放行在放行代碼前後可以添加額外操作。當tomcat服務器關閉,在服務器關閉之前,filter對象銷燬,對象銷燬之前會自動調用destroy方法完成善後的操作。

補充:

【1】關於doFilter方法,每次過濾器攔截請求和響應之後,都會執行,請求過來時,會執行chain.doFilter(req, resp);語句前面的內容,響應回來之後,會執行chain.doFilter(req, resp);語句後面的內容。這點有點像請求轉發執行的過程。

【2】關於責任鏈,在一個web應用中可以配置多個過濾器,只有請求響應都通過這些過濾器,纔可以到達對應的資源身上,這些過濾器組成的鏈稱爲過濾器鏈。這些過濾器鏈稱之爲過濾器的責任鏈模式。

【4】使用過濾器處理中文亂碼問題

使用服務器(tomcat7)及其以下版本,默認使用的是iso8859-1字符集,因爲iso8859-1編碼沒有中文,所以會產生亂碼。

如果頁面使用的是POST請求提交方式,我們可以使用request.setCharacterEncoding("utf-8");設置編碼字符集爲utf-8。

如果頁面使用的是GET請求提交方式,我們可以使用new String(request.getParameter("username").getBytes("iso8859-1"),"utf-8");方式處理亂碼。

如果我們使用的處理POST處理方式則不能處理GET請求方式的亂碼,但如果我們使用GET請求方式,卻可以處理POST請求方式。所以使用GET請求方式進行處理。但如果使用GET請求方式,則不容易獲取,需要處理的參數。所以,我們可以對getParameters()之類的方法進行增強,通過裝飾者模式進行增強方法。

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

class MyHttpServletRequest extends HttpServletRequestWrapper {

    private String encode;
    public MyHttpServletRequest(HttpServletRequest request, String encode) {
        super(request);
        this.encode = encode;
    }
    //重寫的方法
    /**
     * 返回一個經過亂碼處理後的map對象
     * @return
     */
    @Override
    public Map<String, String[]> getParameterMap() {

        //獲取原有的map值,依次作出亂碼處理,處理後將值放入到新map中,並返回
        Map<String, String[]> map = super.getParameterMap();
        //創建新的map,用於存放處理好的map參數
        Map<String, String[]> rmap = new HashMap<String, String[]>();

        try {
            //遍歷map
            for (Map.Entry<String, String[]> entry: map.entrySet()) {

                String key = entry.getKey();
                String[] values = entry.getValue();
                String[] rvalues = new String[values.length];

                for (int i = 0; i < values.length; i++) {
                    rvalues[i] = new String(values[i].getBytes("iso8859-1"),encode);
                }
                //將亂碼處理後的數組放入到新map中
                rmap.put(key,rvalues);
            }

            return  rmap;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public String[] getParameterValues(String name) {

        Map<String, String[]> map = getParameterMap();
        return map.get(name);

    }

    @Override
    public String getParameter(String name) {
        String[] values = getParameterValues(name);
        //如果數組爲null,則返回null,否則將數組中的第一個元素作爲方法返回值使用

        return values==null?null:values[0];
    }


}

書寫一個自定義類,繼承HttpServletRequestWrapper 實現類,增強getParameterMap、getParameterValues、getParameter方法。

之所以繼承HttpServletRequestWrapper 類,是因爲HttpServletRequestWrapper 幫我們實現了ServletRequest與HttpServletRequest接口的方法。HttpServletRequest繼承ServletRequest接口,HttpServletRequestWrapper 實現HttpServletRequest接口。

在Filter類上配置註解爲@WebFilter(filterName = "EncodingFilter",value="/*")

在過濾器doFilter中書寫以下內容便可以對中文進行過濾。

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //請求亂碼處理
        HttpServletRequest request = new MyHttpServletRequest((HttpServletRequest) req);
        //響應亂碼處理
        resp.setContentType("text/html;charset="+encode);
        chain.doFilter(request, resp);
    }

二、Listener監聽器的使用

【1】監聽器技術概述

Listener是Servlet三大技術之一。Servlet三大技術包含Filter、Listener、Servlet。

如果希望自己的網站收集一些必要的數據,可以通過Listener監聽器去監聽獲取。在某一個事件觸發監聽器之後,監聽器會執行對應的操作。

【2】監聽器的種類

1、監聽三大作用域創建和銷燬的監聽器

ServletContextListener 監聽ServletContext域的創建銷燬
HttpSessionListener 監聽Session域的創建銷燬
ServletRequestListener 監聽request域的創建銷燬

2、監聽三大作用域中屬性變化的監聽器(創建、更新、銷燬)

ServletContextAttributeListener 監聽ServletContext域中屬性的變化
HttpSessionAttributeListener 監聽Session域中屬性的變化
ServletRequestAttributeListener 監聽request域中屬性的變化

 

實現以上三個接口,可以獲得到三個域對象,從而獲取用戶的信息,參數,譬如響應頭,請求頭,url地址等等。

3、監聽JavaBean在Session域中狀態變化的監聽器 

HttpSessionBindingListener 監聽javabean在session域中添加和銷燬事件
HttpSessionActivationListener 讓javabean自己感知到自己隨着session被鈍化和活化。

 

Javabean實現HttpSessionBindingListener和HttpSessionActivationListener接口,會重寫這兩個接口中的方法,HttpSessionBindingListener用於感知javabean在session域的變化。

HttpSessionActivationListener讓javabean自己感知到自己隨着session被鈍化和活化。

鈍化是指當服務器正常關閉時,還存活着的session 會隨着服務器的關閉被以文件(“SESSIONS.ser”)的形式存儲在tomcat 的work 目錄下。
活化是指當服務器再次正常開啓時,服務器會找到之前的“SESSIONS.ser” 文件,從中恢復之前保存起來的Session 對象。此時SESSIONS.ser這個文件會被消除。

想要隨着Session 被鈍化、活化的對象它的類必須實現Serializable 接口。關於序列化的問題,可參考https://blog.csdn.net/c17315377559/article/details/100044843

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章