天天看點

Day08JavaWeb【Filter與Listener】Filter

學習目标

開發一個web項目,沒有人一個一個地給Sevlet的請求與響應設計編碼,而是通過過濾器解決全局亂碼

1.能夠說出過濾器的作用

2.能夠編寫過濾器

3.能夠說出過濾器生命周期相關方法

4.能夠根據過濾路徑判斷指定的過濾器是否起作用

5.能夠說出什麼是過濾器鍊

6.能夠編寫過濾器解決全局亂碼

filter-概述

  • (1)Filter是什麼?

    Java Web開發有三大元件:Servlet Filter Listener

  • (2)Filter有什麼作用?

    過濾器實際上就是對web資源進行攔截,做一些處理後再交給下一個過濾器或servlet處理

  • (3)有什麼特點

    通常都是用來攔截request進行處理的

    也可以對傳回的response進行攔截處理

Day08JavaWeb【Filter與Listener】Filter

filter-過濾器的建立***

  • (1)Idea 建立 Filter
  • (2)類比 Servlet

@WebServlet

extends HttpServlet

doGet/doPost方法

@WebFilter

implements Filter

doFilter方法

  • (3)過濾的正确了解

    如果過濾位址是s1,那麼隻有位址是s1的請求才能被過濾,你通路a.jpg

    ,s2等等,過濾器都不過濾,不會執行doFilter方法。

\src\com.wzx.pack01_filter\Demo1Servlet.java

@WebServlet("/s1")
public class Demo1Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet方法執行了啦");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}      

src\com.wzx.pack01_filter\Demo1Filter.java

//我要過濾請求資源路徑是s1,如果你通路的是 s1,我就過濾
@WebFilter("/s1")
public class Demo1Filter implements Filter {
    public void destroy() {
    }

    /*
      1:這個方法是你通路我要過濾的資源時,自動執行
      2: FilterChain被稱為過濾器鍊
      3:  chain.doFilter(req, resp);放行
         如果調用:請求放行
         如果不調用,請求不放行
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("過濾器doFilter方法執行了");
        chain.doFilter(req, resp);

        System.out.println("過濾器響應了");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

filter-過濾器的執行流程

  • (1)一個同學進校園,先會遇到保安,如果該同學出校園,也會碰到保安
  • (2)過濾器的執行流程

    1>tomcat引擎将http請求轉成request對象,http響應轉response對象

    2>位址符合條件,則将request,resposne傳給doFilter方法

    3>再傳給chain.doFilter(request,response)方法

    4>再傳給doGet或者doPost方法,當servlet完成三件事之後

    5>doFilter再執行剩餘代碼之後,reponse再傳回浏覽器

  • (3)設定編碼的代碼位置

    doFilter之前設定請求編碼,之前設定響應編碼

  • Day08JavaWeb【Filter與Listener】Filter

filter-過濾器的執行順序***

Day08JavaWeb【Filter與Listener】Filter
  • (1)如果有兩個Filter都過濾請求,那麼執行順序是如何的?

    先Filter1,再Filter2,最後Servlet,響應傳回時相反

  • (2)什麼設定決定Filter器的執行順序?

    1:注解配置

    當有多個過濾器時,是按照過濾器類的首字母的先後順序執行

    2:web.xml配置

    當有多個過濾器時,是按照web.xml中​​

    ​<filter-mapping></filter-mapping>​

    ​配置的先後先後順序執行的

src\com.wzx.pack02_filter\AFilter.java

@WebFilter("/s2")
public class AFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("第1個過濾器收到請求");
        chain.doFilter(req, resp);
        System.out.println("第1個過濾器收到響應");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

src\com.wzx.pack02_filter\BFilter.java

@WebFilter("/s2")
public class BFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("第2個過濾器收到請求");
        chain.doFilter(req, resp);
        System.out.println("第2個過濾器收到響應");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

src\com.wzx.pack02_filter\Demo2Servlet.java

@WebServlet("/s2")
public class Demo2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("servlet執行了");
    }
}      

注釋@WebFilter,改成xml配置

<!--配置Servlet-->
    <servlet>
        <servlet-name>Demo3Servlet</servlet-name>
        <servlet-class>com.wzx.pack03_filter.Demo3Servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo3Servlet</servlet-name>
        <url-pattern>/s3</url-pattern>
    </servlet-mapping>
    <!--配置TwoFilter-->
    <filter>
        <filter-name>TwoFilter</filter-name>
        <filter-class>com.wzx.pack03_filter.TwoFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TwoFilter</filter-name>
        <url-pattern>/s3</url-pattern>
    </filter-mapping>
    <!--配置OneFilter-->
    <filter>
         <filter-name>ZneFilter</filter-name>
         <filter-class>com.wzx.pack03_filter.ZneFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ZneFilter</filter-name>
        <url-pattern>/s3</url-pattern>
    </filter-mapping>      

filter-過濾器的生命周期(了解)

  • (1)過濾器有3個方法

    init方法:伺服器啟動時就建立該filter對象

    doFilter方法:每當一個請求的路徑是滿足過濾器的配置路徑,那麼就會執行一次過濾器的doFilter方法

    destory方法:伺服器關閉時filter銷毀

src\com.wzx.pack04_life_cycle\Demo3Filter.java

@WebFilter("/*")
public class Demo3Filter implements Filter {
    /*
        當你關閉伺服器時執行,一般釋放資源
     */
    public void destroy() {
        System.out.println("destroy執行啦888888888888888888888888888888888888");
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        chain.doFilter(req, resp);
    }

    //當你把項目部署到伺服器上的時候,或者啟動伺服器,該方法就執行
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init方法執行了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    }

}      

filter-過濾器的url-pattern配置

  • (1)Filter的url-pattern配置有3種,類比Servlet
1:完全路徑比對
   @WebFilter("/s1")
   @WebFilter("/abc/s1")
2:目錄比對
   @WebFilter("/*")
   @WebFilter("/abc/*")
3:擴充名比對
   @WebFilter("*.do")
   @WebFilter("*.jsp")      

src\com.wzx.pack04_life_cycle\Demo4Filter.java

@WebFilter("/abc/xxx/*")
public class Demo4Filter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("doFilter方法執行了");
       chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

filter-過濾器的攔截方式設定

  • (1)過濾器可以區分不同的通路資源的方式,有不同的攔截方式。
  • (2)dispatcher:通路的方式

    REQUEST:預設值,代表直接通路某個資源時執行filter

    FORWARD:轉發時才執行filter

  • (3)如何設定

    預設情況下,過濾器隻能攔截直接通路的資源,不能攔截轉發通路的資源

    如果想讓過濾器不管是直接通路,還是轉發通路,都能攔截,則需要設定 @WebFilter屬性

@WebFilter(value = "/index.jsp",dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD})      
Day08JavaWeb【Filter與Listener】Filter

src\pack05_filter\DispaterServlet.java

@WebServlet("/dispater")
public class DispaterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }
}      

src\pack05_filter\AccessFilter.java

@WebFilter(value = "/index.jsp",dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD})
public class AccessFilter implements Filter {
    public void destroy() {
    }

    /*
    1:FilterChain内部了解成一個集合,這個集合中維持一個過濾器鍊條
    2:這個過濾器鍊中的過濾器必須按順序依次執行
    3:過濾器鍊中必須全部通過,才能通過,隻要有一個不通過,則無法通路對應的資源
     */
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("過濾器執行了");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

filter-過濾器鍊

  • (1)什麼是過濾器鍊

    1:FilterChain内部了解成一個集合,這個集合中維持一個過濾器鍊條

  • (2)有什麼特點?

    》1 這個過濾器鍊中的過濾器必須按順序依次執行

    》2 過濾器鍊中必須全部通過,才能通過,隻要有一個不通過,則無法通路對應的資源

  • Day08JavaWeb【Filter與Listener】Filter

filter-全局亂碼解決

  • (1)在擷取參數之前設定請求編碼
  • (2)在響應浏覽器之前設定響應編碼

    web\index.jsp

<form action="${pageContext.request.contextPath}/get_form" method="post">
        使用者名:<input type="text" name="username"/>
               <input type="submit" value="送出"/>
    </form>      

src\com.wzx.pack05_filter\GetFormServlet.java

@WebServlet("/get_form")
public class GetFormServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        request.setCharacterEncoding("UTF-8");
        //1:擷取表單資料
        String username = request.getParameter("username");
        System.out.println("username:"+username);
        //2:響應
//        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("收到資料啦!");
    }
}      

src\com.wzx.pack05_filter\CharSetFilter.java

  • 此處是關鍵,隻要符合條件的請求會被過濾器攔截,多個Servlet的請求,被攔截下來之後先設定好編碼,再交給Servlet
@WebFilter("/*")
public class CharSetFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1:解決請求參數亂碼
        HttpServletRequest request = (HttpServletRequest)req;
        String method = request.getMethod();

        if(method.equals("POST")) {
            req.setCharacterEncoding("UTF-8");
        }
        resp.setContentType("text/html;charset=UTF-8");
        chain.doFilter(req, resp);

    }

    public void init(FilterConfig config) throws ServletException {

    }

}      

filter-全局亂碼分析 (了解)