Servlet中過濾器技術

來源:互聯網
上載者:User
Servlet中過濾器技術

Servlet中過濾器技術 基本概念 過濾器入門案例 API詳解 指定攔截 對請求進行攔截 攔截指定的類型 案例 在Jsp頁面中增加富文字編輯器

基本概念

3W1H原則:why(為什麼會有這個技術)、what(該技術的概念)、where(應用情境)、how(該技術怎麼用)。 為什麼要使用過濾器以及應用情境怎麼樣。

在項目的開發中,經常會寫重複的代碼,如在每一個Servlet中我們都會在代碼的開始處設定utf-8編碼,再如判斷使用者是否登入,在刪除、修改、添加情境中都會用到判斷邏輯,只有在登入之後才能操作,等等。很多情況下我們都會抽取重複的代碼,封裝為一個方法,並且需要手動的調用這些重複的方法。那麼就需要過濾器在請求到達Servlet之前首先進行過濾(所謂過濾就是公用代碼的執行),並且Servlet技術執行結束之後在回到過濾器,完成之後再經過Jsp層,起到過濾和開關的工作。 過濾器是什麼。

Filter就是過濾器,過濾器也是在tomcat中運行,並且在tomcat下只能運行Servlet程式,所以過濾器技術實際上也是Servlet技術,是Servlet技術中最激動人心的技術。 增加過濾器之後的執行流程

首先使用者訪問伺服器,接著過濾器對Servlet進行攔截,過濾器將Servlet請求處理完之後再允許存取,接著進入Servlet中,當然也能進入Jsp中(因為Jsp技術實際上也是Servlet技術),Servlet處理完成之後,再回到過濾器,最後過濾器將結果發送給瀏覽器做響應,過濾器形象的比喻就是回家的門! 過濾器入門案例 首先建立一個Servlet

//FilterServlet.javapackage com.jpzhutech.filter;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class FilterServlet extends HttpServlet {    /**     * The doGet method of the servlet. <br>     *     * This method is called when a form has its tag value method equals to get.     *      * @param request the request send by the client to the server     * @param response the response send by the server to the client     * @throws ServletException if an error occurred     * @throws IOException if an error occurred     */    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html");        System.out.println("4.處理使用者請求開始");    }    /**     * The doPost method of the servlet. <br>     *     * This method is called when a form has its tag value method equals to post.     *      * @param request the request send by the client to the server     * @param response the response send by the server to the client     * @throws ServletException if an error occurred     * @throws IOException if an error occurred     */    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html");        doGet(request, response);    }}
建立過濾器類,實現Filter介面
//FilterDemo1.javapackage com.jpzhutech.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class FilterDemo1 implements Filter {    // 建立過濾器執行個體,在伺服器啟動時執行    public FilterDemo1() {        System.out.println("1.建立過濾器執行個體");    }    //執行初始化方法,在伺服器啟動時執行    public void init(FilterConfig filterConfig) throws ServletException {        System.out.println("2.執行過濾器初始化方法");    }    //過濾器業務處理方法,在請求到達Servlet之前,先進入該方法處理公用的商務邏輯操作    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain) throws IOException, ServletException {        System.out.println("3.執行過濾器業務處理方法");        //允許存取,去到Servlet        chain.doFilter(request,response);        //Servlet處理完成,又回到過濾器        System.out.println("5.Servlet處理完成,又回到過濾器");    }    public void destroy() {        System.out.println("6.銷毀過濾器執行個體");    }}
在web.xml中配置Filter
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">  <display-name>filter</display-name>  <filter>    <filter-name>FilterDemo1</filter-name>    <filter-class>com.jpzhutech.filter.FilterDemo1</filter-class>  </filter>  <filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>  <servlet>    <description>This is the description of my J2EE component</description>    <display-name>This is the display name of my J2EE component</display-name>    <servlet-name>FilterDemo1</servlet-name>    <servlet-class>com.jpzhutech.filter.FilterDemo1</servlet-class>  </servlet>  <servlet>    <description>This is the description of my J2EE component</description>    <display-name>This is the display name of my J2EE component</display-name>    <servlet-name>FilterServlet</servlet-name>    <servlet-class>com.jpzhutech.filter.FilterServlet</servlet-class>  </servlet>  <servlet-mapping>    <servlet-name>FilterDemo1</servlet-name>    <url-pattern>/FilterDemo1</url-pattern>  </servlet-mapping>  <servlet-mapping>    <servlet-name>FilterServlet</servlet-name>    <url-pattern>/FilterServlet</url-pattern>  </servlet-mapping>  <welcome-file-list>    <welcome-file>index.html</welcome-file>    <welcome-file>index.htm</welcome-file>    <welcome-file>index.jsp</welcome-file>    <welcome-file>default.html</welcome-file>    <welcome-file>default.htm</welcome-file>    <welcome-file>default.jsp</welcome-file>  </welcome-file-list></web-app>

在瀏覽器訪問 localhost:8080/filte/FilterServlet 在控制台中會發現過濾器類中方法的調用順序

當有多個過濾器時,按照在web.xml檔案中的配置順序,依次進入不同的過濾器,之後看到允許存取代碼就進入到要執行的Servlet中,執行完Servlet之後回到過濾器的順序與進入的順序剛好相反

圖解上述過程

API詳解 涉及到的介面,其中的方法參見Servlet協助文檔
interface Filter 核心介面 interface FilterConfig interface FilterChain

請查閱Servlet文檔查看這三個介面中對應的方法。 指定攔截 對請求進行攔截

看web.xml設定檔中的一些具體內容:

  <filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>

其中url-pattern中/*代表攔截所有的資源(包括Servlet、Jsp、JS、Html、css、圖片等都是資源)請求,那麼我現在想做的是我能不能攔截指定的資源呢。比如說我現在只攔截Jsp資源,不攔截Servlet資源。怎麼做到呢。

 <filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>/index.jsp</url-pattern> </filter-mapping>

上面的url-pattern=index.jsp代表的是只攔截index.jsp資源。如果我我想攔截多個資源該怎麼做呢。

<filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>/index.jsp</url-pattern>    <url-pattern>/list.jsp</url-pattern> </filter-mapping>

同樣我可以寫成Regex的情況:

<filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>*.jsp</url-pattern> </filter-mapping>

如果我們只攔截Servlet呢。

<filter-mapping>    <filter-name>FilterDemo1</filter-name>    <url-pattern>/index</url-pattern> </filter-mapping>
攔截指定的類型
<filter-mapping>    <filter-name>FilterDemo1</filter-name>     <dispatcher>REQUEST/ERROR/FORWARD/INCLUDE</dispatcher> </filter-mapping>

上面的配置執行個體表名只攔截請求/錯誤/轉寄/只攔截包含頁面。 案例

案例一:編碼統一處理,要求處理請求資料中的中文問題,請求分為GET/POST提交。因為每一個Servlet都要執行該步驟,所以我們將這個處理放到過濾器中執行,在Servlet中不再執行。

//EncodingFilter.javapackage com.jpzhutech.login;import java.io.IOException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class EncodingFilter implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest req, ServletResponse res,            FilterChain chain) throws IOException, ServletException {        final HttpServletRequest request = (HttpServletRequest) req;        HttpServletResponse response = (HttpServletResponse) res;        request.setCharacterEncoding("utf-8");        response.setContentType("text/html;charset=utf-8");        /**出現get中文亂碼是因為在request.getParameter方法內部沒有對提交方式判斷並處理         * String name = request.getParameter("userName");         *          * 解決辦法:對指定的介面的某一個方法進行功能擴充,可以使用代碼,對request對象(也就是目標對象),         * 建立代理對象         */        HttpServletRequest proxy =  (HttpServletRequest) Proxy.newProxyInstance(                request.getClass().getClassLoader(),         // 指定當前使用的類載入器                new Class[]{HttpServletRequest.class},         // 對目標對象實現的介面類型                new InvocationHandler() {        // 事件處理器                    @Override                    public Object invoke(Object proxy, Method method, Object[] args)  //method代表的是方法,後面的args是指前面method的值                            throws Throwable {                        // 定義方法傳回值                        Object returnValue = null;                        // 擷取方法名                        String methodName = method.getName();                        // 判斷:對getParameter方法進行GET提交中文處理                        if ("getParameter".equals(methodName)) {                            // 擷取請求資料值 <input type="text" name="userName">                            String value = request.getParameter(args[0].toString());    // 也就是得到userName的值                            // 擷取提交方式                            String methodSubmit = request.getMethod(); // 直接調用目標對象的方法                            // 判斷如果是GET提交,需要對資料進行處理  (POST提交已經處理過了)                            if ("GET".equals(methodSubmit)) {                                if (value != null && !"".equals(value.trim())){                                    // 處理GET中文                                    value = new String(value.getBytes("ISO8859-1"),"UTF-8");                                }                            }                             return value;   //對get提交處理之後,返回處理後的值                        }                        else {                            // 執行request對象的其他方法,只對getParamter方法進行處理                            returnValue = method.invoke(request, args);                        }                        return returnValue;                    }                });        chain.doFilter(proxy, response); //過濾器處理完成之後一定要允許存取,否則不會取執行Servlet代碼    }    @Override    public void destroy() {    }}
//LoginServlet.javapackage com.jpzhutech.login;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginServlet extends HttpServlet {    /**     * The doGet method of the servlet. <br>     *     * This method is called when a form has its tag value method equals to get.     *      * @param request the request send by the client to the server     * @param response the response send by the server to the client     * @throws ServletException if an error occurred     * @throws IOException if an error occurred     */    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");  //post方式提交時只需要加這一行代碼便能做到中文不亂碼        String name = request.getParameter("userName");        System.out.println("使用者名稱"+name);    }    /**     * The doPost method of the servlet. <br>     *     * This method is called when a form has its tag value method equals to post.     *      * @param request the request send by the client to the server     * @param response the response send by the server to the client     * @throws ServletException if an error occurred     * @throws IOException if an error occurred     */    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}
<--login.jsp--><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>My JSP 'index.jsp' starting page</title><!-- 新 Bootstrap 核心 CSS 檔案 --><link rel="stylesheet"    href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"><!-- 可選的Bootstrap主題檔案(一般不用引入) --><link rel="stylesheet"    href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css"><!-- jQuery檔案。務必在bootstrap.min.js 之前引入 --><script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script><!-- 最新的 Bootstrap 核心 JavaScript 檔案 --><script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script></head><body>    <form action="${pageContext.request.contextPath}/LoginServlet"        method="post">        使用者名稱:<input type="text" name="userName"><br /> <input            type="submit" value="post提交">    </form>    <hr />    <form action="${pageContext.request.contextPath}/LoginServlet"        method="get">        使用者名稱:<input type="text" name="userName"><br /> <input            type="submit" value="get提交">    </form></body></

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.