天天看點

javaee學習之路(六)Servlet過濾器

javaee學習之路(六)Servlet過濾器

例1、初步認識過濾器。

第一步、BaseFilter.java

package cn.itcast.filter;
import *;
public class BaseFilter implements Filter{
    public BaseFilter(){//先執行個體化,後初始化
        System.out.println("BaseFilter方法");
    }
    /*
     * 初始化方法  servlet容器調用該方法   ==Servlet init方法
     *    *能被調用一次
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法");
    }
    /**
     * 處理客戶請求的方法
     *     *  servlet容器調用該方法  =  servlet service()方法
     *     *  能被調用多次
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws xception {
        System.out.println("doFilter方法");
        HttpServletRequest res=(HttpServletRequest)request;
        System.out.println("res.getServletPath()"+res.getServletPath());
        //放行,控制後面的資源是否執行
        chain.doFilter(request, response);
    }
    /**
     * 3.釋放資源的方法
     *    *   servlet容器調用該方法==servlet中的destroy方法
     */
    public void destroy() {
        System.out.println("destroy方法");
    }
}
           

第二步、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 注冊filter -->
<filter>
   <!-- 注冊的過濾器的名稱 -->
   <filter-name>BaseFilter</filter-name>
   <!-- filter的完整路徑 -->
   <filter-class>cn.itcast.filter.BaseFilter</filter-class>
</filter>
<!-- 配置過濾器映射 -->
<filter-mapping>
   <!-- 上面注冊的filter的名稱 -->
   <filter-name>BaseFilter</filter-name>
   <!-- 攔截所有的請求 -->
   <url-pattern>/*</url-pattern>
</filter-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
           

第三步、啟動tomcat伺服器,在IE中鍵入http://localhost:8080/day17Filter/觀察結果

……

2012-10-23 19:10:14 org.apache.catalina.core.StandardEngine start

資訊: Starting Servlet Engine: Apache Tomcat/6.0.20

BaseFilter方法

init方法

……

資訊: Server startup in 5301 ms

doFilter方法

res.getServletPath()/index.jsp

例2、過濾器的詳細應用。

第一步、BaseFilter.java

package cn.itcast.filter;
import *;
public class BaseFilter implements Filter{
    public BaseFilter(){//先執行個體化,後初始化
        System.out.println("BaseFilter方法");
    }
    /*
     * 初始化方法  servlet容器調用該方法   ==Servlet init方法
     *    *能被調用一次
     *    *FilterConfig類似于servletConfig
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init方法");
        System.out.println("filterConfig:"+filterConfig);
/********************************************************************************/
        System.out.println("擷取過濾器的名稱:"+filterConfig.getFilterName());//web.xml中配置的
/********************************************************************************/
        /*
         *  <init-param>
                  <param-name>test1</param-name>
                  <param-value>a1</param-value>
            </init-param> 
           <init-param>
                  <param-name>test2</param-name>
                  <param-value>a2</param-value>
           </init-param>
         */
        String initparam1=filterConfig.getInitParameter("test1");
        System.out.println("initparam1"+initparam1);
/********************************************************************************/
        java.util.Enumeration<String> em=filterConfig.getInitParameterNames();
        while(em.hasMoreElements()){
            String paramName=em.nextElement();
            String paramValue=filterConfig.getInitParameter(paramName);
            System.out.println(paramName+":"+paramValue);
        }
        /*
         *  <context-param>
                <param-name>testContext</param-name>
                <param-value>xxxxxxxxxx</param-value>
            </context-param>
         */
        //擷取上下文對象,相當有用
/********************************************************************************/
        ServletContext sc=filterConfig.getServletContext();
        String str=sc.getInitParameter("testContext");
        System.out.println("str"+str);
    }
    /**
     * 處理客戶請求的方法
     *     *  servlet容器調用該方法  =  servlet service()方法
     *     *  能被調用多次
     *     request:用戶端的請求資訊
     *     response:對用戶端的響應資訊
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws Exception {
        System.out.println("doFilter方法");
        HttpServletRequest res=(HttpServletRequest)request;//注意要轉型
        HttpServletResponse req=(HttpServletResponse)response;
        System.out.println("res.getContextPath():"+res.getContextPath());
        System.out.println("res.getRequestURL():"+res.getRequestURL());
        System.out.println("res.getRequestURI():"+res.getRequestURI());
        System.out.println("res.getServletPath()"+res.getServletPath());
        //放行
        chain.doFilter(request, response);//也可以是res,req 
    }
    /**
     * 3.釋放資源的方法
     *    *   servlet容器調用該方法==servlet中的destroy方法
     */
    public void destroy() {
        System.out.println("destroy方法");

    }

}
           

第二步、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app ……
<context-param>
    <param-name>testContext</param-name>
    <param-value>xxxxxxxxxx</param-value>
</context-param>
<!-- 注冊filter -->
<filter>
   <!-- 注冊的過濾器的名稱 -->
   <filter-name>BaseFilter</filter-name>
   <!-- filter的完整路徑 -->
   <filter-class>cn.itcast.filter.BaseFilter</filter-class>
   <init-param>
      <param-name>test1</param-name>
      <param-value>a1</param-value>
   </init-param> 
   <init-param>
      <param-name>test2</param-name>
      <param-value>a2</param-value>
   </init-param>
</filter>

<!-- 配置過濾器映射 -->
<filter-mapping>
   <!-- 上面注冊的filter的名稱 -->
   <filter-name>BaseFilter</filter-name>
   <!-- 攔截所有的請求 -->
   <url-pattern>/*</url-pattern>
</filter-mapping>
           

……

第三步、啟動伺服器,在IE中鍵入:http://localhost:8080/day17Filter/并觀察結果

……

資訊: Starting Servlet Engine: Apache Tomcat/6.0.20

BaseFilter方法

init方法

filterConfig:ApplicationFilterConfig[name=BaseFilter, filterClass=cn.itcast.filter.BaseFilter]

擷取過濾器的名稱:BaseFilter

initparam1a1

test1:a1

test2:a2

strxxxxxxxxxx

……

資訊: Server startup in 3873 ms

doFilter方法

res.getContextPath():/day17Filter

res.getRequestURL():http://localhost:8080/day17Filter/

res.getRequestURI():/day17Filter/

res.getServletPath()/index.jsp

例3:字元編碼的過濾器:通過配置參數encoding緻命使用何種字元編碼,以處理html Form請求參數的中文問題

第一步、

javaee學習之路(六)Servlet過濾器

第二步、login.jsp

<%@ page language=”java” import=”java.util.*” pageEncoding=”UTF-8”%>

……

<div id="container">
     <div id="login">
         <div id="form">
             <form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
                <div id="input">
                  <div> 使用者:<input type="text" name="username"/><br/></div>
                  <div> 密碼:<input type="password" name="password"/><br/></div>
                </div>
                <div id="btn">
                 <input type="submit" value="登入"/>
           
……
           

第三步、LoginServlet.java

package cn.itcast.web;
import *;
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //request.setCharacterEncoding("UTF-8");
//沒有上面一行,送出表單時中文會出現亂碼問題,用過濾器來處理
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        String username=request.getParameter("username");
        System.out.println("username"+username);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
           

第四步、

package cn.itcast.filter;
import *;
public class CharacterEncodingFilter implements Filter {
    String encoding;
    public void init(FilterConfig filterConfig) throws ServletException {
        /*
         * <init-param>
               <param-name>encoding</param-name>
               <param-value>UTF-8</param-value>
         </init-param>
         */
        String encoding = filterConfig.getInitParameter("encoding");
        this.encoding=encoding;
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)request;
        if(req.getCharacterEncoding()==null){
            if(this.encoding!=null){
                //設定字元編碼
                request.setCharacterEncoding(this.encoding);
            }
        }
        //放行
        chain.doFilter(request, response);
    }
    public void destroy() {
    }
}
           

第五步、

<filter-mapping>
     <filter-name>CharacterEncodingFilter</filter-name>
     <!-- 使用servlet的名稱  也就是Servlet中servlet-name标簽的值 -->
     <servlet-name>LoginServlet</servlet-name>
  </filter-mapping>
           

映射Filter(串聯一)

1、 通天一個Filter設定多個映射

2、 在同一個web.Xml檔案中可以為同一個Filter設定多個映射,若一個Filter鍊中多次出現了同一個Filter程式,這個Filter程式的攔截處理過程将被執行多次

javaee學習之路(六)Servlet過濾器
<filter>
     <filter-name>CharacterEncodingFilter</filter-name>
     <filter-class>cn.itcast.filter.CharacterEncodingFilter</filter-class>
     <init-param>
           <param-name>encoding</param-name>
           <param-value>UTF-8</param-value>
     </init-param>
  </filter>
 ① <filter-mapping>
     <filter-name>CharacterEncodingFilter</filter-name>
     <url-pattern>/a/b/b.jsp</url-pattern>
  </filter-mapping>
 ② <filter-mapping>
     <filter-name>CharacterEncodingFilter</filter-name>
     <url-pattern>/a/a.jsp</url-pattern>
  </filter-mapping>
  ③<filter-mapping>
     <filter-name>CharacterEncodingFilter</filter-name>
     <url-pattern>/login.jsp</url-pattern>
  </filter-mapping>
           

如果filter-mapping的内容都要執行的話,過濾器的執行順序按照filter_mapping在web.xml檔案中的順序執行。

上面的執行順序為:①②③

例5、項目應用2:是浏覽器不緩存頁面的過濾器:

* 有三個HTTP響應頭字段都可以禁止浏覽器緩存目前頁面,他們在Servlet中的執行個體代碼:

//設定該網頁的到期時間,一旦過期則必須到伺服器重新調用

Response.setDateHeader(“Expires”,-1);

//Cache-Control指定請求和響應遵循的緩存機制 no-cache隻是請求或響應消息不能緩存

Response.setHeader(“Cache-Control”,”no-cache”);

//是用于設定禁止浏覽器從本地機的緩存中調閱頁面内容,設定後一旦離開網頁就無法從Cache中再調出

Response.setHeader(“Pragma”,”no-cache”);

  • 并不是所有的浏覽器都能完全支援上面的三個響應頭,是以最好是同時使用上面的三個響應頭

    問題示範:

    javaee學習之路(六)Servlet過濾器
    第一步、pic.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>pic.html</title>
  </head>  
  <body>
    <img src="./1.jpg"/>
    <br/>
    <a href="./test.jsp">test.jsp</a>
  </body>
</html>
           

第二步、test.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
    <a href="./pic.html">pic.html</a>
  </body>
</html>
           

将工程釋出到tomcat中,鍵入http://localhost:8080/day18FilterNoCache/nocache/pic.html ,可以看到頁面有1.jpg

再将pic.html中改為2.jpg,并重新釋出,然後在浏覽器中按超連結(注意不要重新整理),再點選超連結,可以看到pic.html中顯示的内容沒有變化,原因:圖檔緩存了

解決辦法:

第一步、pic.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>pic.html</title>
  </head>

  <body>
    <img src="./2.jpg"/>
    <br/>
    <a href="./test.jsp">test.jsp</a>
  </body>
</html>
           

第二步、test.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
    <a href="./pic.html">pic.html</a>
  </body>
</html>
           

第三步、過濾器

package cn.itcast.filter;
import *;
public class NoCacheFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res=(HttpServletResponse)response;
        res.setDateHeader("Expires",-);
        res.setHeader("Cache-Control","no-cache");
        res.setHeader("Pragma","no-cache");
        chain.doFilter(request, response);
    }
    public void destroy() {
        // TODO Auto-generated method stub
    }
}
           

第四步、web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app……
  <filter>
     <filter-name>NoCacheFilter</filter-name>
     <filter-class>cn.itcast.filter.NoCacheFilter</filter-class>
  </filter>
  <filter-mapping>
     <filter-name>NoCacheFilter</filter-name>
     <url-pattern>/*</url-pattern>
     <dispatcher>REQUEST</dispatcher>
     <dispatcher>FORWARD</dispatcher>
  </filter-mapping>
           

Filter串聯二:

* 若有多個 Filter 程式對某個 Servlet 程式的通路過程進行攔截,當針對該 Servlet 的通路請求到達時,web 容器将把這多個 Filter 程式組合成一個 Filter 鍊(過濾器鍊)。Filter 鍊中各個 Filter 的攔截順序與它們在應用程式的 web.xml 中映射的順序(即filter-mapping的順序)一緻

Servlet過濾器對請求的過濾:

A、 Servlet容器建立一個過濾器執行個體

B、 Servlet容器調用init方法,讀取過濾器的初始化參數

C、 Servlet容器調用doFilter方法,根據初始化參數的值,判斷該請求是否合法

D、 如果該請求不合法則阻塞該請求

E、 如果該請求合法則調用chain.doFliter方法将該請求向後續傳遞

例6、檢測使用者是否登入。

第一種、利用session來做

javaee學習之路(六)Servlet過濾器

第一步、login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
……
             <form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
                <div id="input">
                  <div> 使用者:<input type="text" name="username"/><br/></div>
                  <div> 密碼:<input type="password" name="password"/><br/></div>
                </div>
                <div id="btn">
                 <input type="submit" value="登入"/>
                 <input type="button" value="注冊" onclick=""/>
         ……
           

第二步、success.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
……
  <body> 轉發成功!!! <br>
<a href="${pageContext.request.contextPath}/success1.jsp">success1.jsp</a><br/>
<a href="${pageContext.request.contextPath}/success2.jsp">success2.jsp</a><br/>
<a href="${pageContext.request.contextPath}/success3.jsp">success3.jsp</a><br/>
<a href="${pageContext.request.contextPath}/success4.jsp">success4.jsp</a><br/>
……
           

第三步、LoginServlet.java

package cn.itcast.web;
import *;
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        HttpSession session=request.getSession();
        //擷取使用者名
        String username=request.getParameter("username");
        session.setAttribute("username", username);
        //轉發到success.jsp
        request.getRequestDispatcher("/success.jsp").forward(request,response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
           

第四步、success1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'success1.jsp' starting page</title> 
       <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
   <%   
       String username = (String)session.getAttribute("username");
       if(username==null){//表示使用者沒有登入
           String contextPath=request.getContextPath();
           //重新定向到login.jsp登陸頁面
           response.sendRedirect(contextPath+"/login.jsp");
       }
   %>
  success1.jsp
    <a href="${pageContext.request.contextPath}/success.jsp">success.jsp</a>
  </body>
</html>
           

第五步、success2.jsp、success3jsp、success4.jsp

第六步、觀察結果:在IE中鍵入:http://localhost:8080/day18CheckLogin/login.jsp 輸入使用者名登陸 在點選超連結 success1.jsp會看到success1.jsp中的頁面内容success1.jsp success.jsp 然後關閉浏覽器,在打開一個浏覽器,直接鍵入:

http://localhost:8080/day18CheckLogin/success1.jsp 則頁面會轉向到login.jsp

第二種方法:過濾器

javaee學習之路(六)Servlet過濾器

第一步、配置web.xml

……

<!-- 儲存的關鍵字 -->
<context-param>
   <param-name>checkSessionKey</param-name>
   <param-value>username</param-value>
</context-param>
<!-- 重定向的頁面 -->
<context-param>
   <param-name>redirectURL</param-name>
   <param-value>/login.jsp</param-value>
</context-param>
<!-- 不做檢查的清單 -->
<context-param>
   <param-name>notCheckURLList</param-name>
   <param-value>/login.jsp,/servlet/LoginServlet</param-value>
</context-param>
<!-- 配置檢查使用者登入的過濾器 -->
    <filter>
      <filter-name>CheckLoginFilter</filter-name>
      <filter-class>cn.itcast.filter.CheckLoginFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>CheckLoginFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
           
……
           

第二步、login.jsp

……

<div id="form">
             <form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
                <div id="input">
                  <div> 使用者:<input type="text" name="username"/><br/></div>
                  <div> 密碼:<input type="password" name="password"/><br/></div>
                </div>
                <div id="btn">
                 <input type="submit" value="登入"/>
           
……
           

第三步、success.jsp

第四步、success1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
  success1.jsp
    <a href="${pageContext.request.contextPath}/success.jsp">success.jsp</a>
  </body>
</html>
           

第五步、LoginServlet.java

package cn.itcast.web;
import *;
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws Exception {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        HttpSession session=request.getSession();
        //擷取使用者名
        String username=request.getParameter("username");
        /*<!-- 儲存的關鍵字 -->
            <context-param>
               <param-name>checkSessionKey</param-name>
               <param-value>username</param-value>
            </context-param>
         * 
         */
        ServletContext sc=this.getServletContext();
        String checkSessionKey = sc.getInitParameter("checkSessionKey");
        if(checkSessionKey!=null){
            //儲存使用者名到Session中
            session.setAttribute(checkSessionKey, username);
        }
        session.setAttribute("username", username);
        //轉發到success.jsp
        request.getRequestDispatcher("/success.jsp").forward(request,response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
           

第六步、

package cn.itcast.filter;
import *;
public class CheckLoginFilter implements Filter {
    private String checkSessionKey;
    private String redirectURL;
    private List notCheckURLList;
    public void init(FilterConfig filterConfig) throws ServletException {
        //讀取web.xml檔案中的初始化參數
        /*
         * <!-- 儲存的關鍵字 -->
                <context-param>
                   <param-name>checkSessionKey</param-name>
                   <param-value>username</param-value>
                </context-param>
         */
        ServletContext sc=filterConfig.getServletContext();
        checkSessionKey=sc.getInitParameter("checkSessionKey");
        this.checkSessionKey=checkSessionKey;
        /*
         * <!-- 重定向的頁面 -->
                <context-param>
                   <param-name>redirectURL</param-name>
                   <param-value>/login.jsp</param-value>
                </context-param>
         */
        redirectURL = sc.getInitParameter("redirectURL");
        this.redirectURL=redirectURL;
        /*
         * <!-- 不做檢查的清單 -->
                <context-param>
                   <param-name>notCheckURLList</param-name>
                   <param-value>/login.jsp,/servlet/LoginServlet</param-value>
                </context-param>
         */
        String[] notCheckURLListstr=sc.getInitParameter("notCheckURLList").split(",");
        notCheckURLList=Arrays.asList(notCheckURLListstr);
        this.notCheckURLList=notCheckURLList;
    }
    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws Exception {
        HttpServletRequest req=(HttpServletRequest)request;
        HttpServletResponse res=(HttpServletResponse)response;
        //擷取servlet的路徑
        String servletPath=req.getServletPath();
        System.out.println(servletPath);
        //擷取session
        HttpSession session=req.getSession();
        //1.如果通路的路徑中包含notCheckURLList中的路徑,放行
        if(this.notCheckURLList!=null&&this.notCheckURLList.contains(servletPath)){
            chain.doFilter(request, response);
        }else{//2.如果通路路徑中不包含notCheckURLList中的路徑
                    //2.1從session中回去使用者名
            String username=(String)session.getAttribute(this.checkSessionKey);
                             //2.1.1如果使用者名不為空,放行
                if(username!=null){
                    chain.doFilter(request, response);
                }else{
                             //2.1.2如果使用者名為空,重定向到redirectURL指向的登入頁面
                    String contextPath=req.getContextPath();
                    res.sendRedirect(contextPath+this.redirectURL);
                }
        }
    }
    public void destroy() {
    }
}
           

第七步、觀察結果:在IE中鍵入:http://localhost:8080/day18CheckLogin/login.jsp 輸入使用者名登陸 在點選超連結 success1.jsp會看到success1.jsp中的頁面内容success1.jsp success.jsp 然後關閉浏覽器,在打開一個浏覽器,直接鍵入:

http://localhost:8080/day18CheckLogin/success1.jsp 則頁面會轉向到login.jsp

javaee學習之路(六)Servlet過濾器

破壞情況(新開一個浏覽器)

javaee學習之路(六)Servlet過濾器

裝飾模式

案例:

javaee學習之路(六)Servlet過濾器

1、IMessageBoard.java

package cn.itcast.test;
public interface IMessageBoard {
    public String filter();
}
           
  1. MessageBoard.java
package cn.itcast.test;
public class MessageBoard implements IMessageBoard {
    @Override
    public String filter() {
        return "你喜歡戰争嗎?";
    }
}
           

3.Client.java

package cn.itcast.client;
import cn.itcast.test.IMessageBoard;
import cn.itcast.test.MessageBoard;
public class Client {
    public static void main(String[] args) {
        Client c=new Client();
        IMessageBoard messageBoard = new MessageBoard();
        c.test(messageBoard);
    }
    public void test(IMessageBoard messageBoard) {
        System.out.println(messageBoard);
        String content = messageBoard.filter();
        System.out.println("content"+content);
    }
}
           

運作結果:[email protected]

content你喜歡戰争嗎?

?要求:在不改變MessageBoard類和Client類中的test方法的代碼的情況下輸出你喜歡和平嗎,如何解決?

方法一、可以使用繼承來實作功能的拓展,如果這些需要拓展的功能的種類很繁多,那麼勢必生成很多子類,增加系統的複雜性。

javaee學習之路(六)Servlet過濾器

第一步、建立一個類MessageBoardExtends.java

package cn.itcast.test;
public class MessageBoardExtends extends MessageBoard{
    @Override
    public String filter() {
        String content=super.filter();
        System.out.println("MessageBoardExtends"+content);
        return content.replaceAll("戰争", "和平");
    }
}
           

第二步、更新Client.java

package cn.itcast.client;
import *;
public class Client {
    public static void main(String[] args) {
        Client c=new Client();
        IMessageBoard messageBoard = new MessageBoardExtends();
        c.test(messageBoard);
    }
    public void test(IMessageBoard messageBoard) {
        System.out.println("messageBoard"+messageBoard);
        String content = messageBoard.filter();
        System.out.println("content"+content);
    }
}
           

第三步、運作結果為:

messageBoardcn.itcast.test.MessageBoardExtends@dc8569
MessageBoardExtends你喜歡戰争嗎?
content你喜歡和平嗎?
           

方法二、使用Decorator的理由是:這些功能需要由使用者動态決定加入的方式和時機,Decorator提供了”即插即用”的方法,在運作期間決定何時增加何種功能

javaee學習之路(六)Servlet過濾器

第一步、MessageBoardDecorator.java (具體裝飾角色,需要一個具體建構角色的類的對象)

package cn.itcast.test;
public class MessageBoardDecorator implements IMessageBoard{
    private IMessageBoard messageBoard;
    /**
     * 
     * @param messageBoard是接口實作類的兌現個,在這個程式中 new MessageBoard
     */
    public MessageBoardDecorator(IMessageBoard messageBoard){
        System.out.println("包裝類的對象    "+messageBoard);
        this.messageBoard=messageBoard;
    }
    @Override
    public String filter() {
        String content = messageBoard.filter();
        return content.replaceAll("戰争", "和平");
    }
}
           

第二步、Client.java

package cn.itcast.client;
import *;
public class Client {
    public static void main(String[] args) {
        Client c=new Client();
        //不可變的類
        MessageBoard m=new MessageBoard();
        IMessageBoard messageBoard = new MessageBoardDecorator(m);
        c.test(messageBoard);
    }
    public void test(IMessageBoard messageBoard) {
        System.out.println("messageBoard  "+messageBoard);
        String content = messageBoard.filter();
        System.out.println("用戶端content"+content);
    }
}
           

第三步、觀察結果

包裝類的對象 [email protected]

messageBoard [email protected]

用戶端content你喜歡和平嗎?

Decorator定義:

動态給一個對象添加一些額外的職責,就像在牆上刷油漆。使用Decorator模式相比用生成子類方式達到功能的擴充顯得更為靈活。

1、抽象建構角色(Component):定義一個抽象接口,以規範準備接受附加責任的對象。

    *具體建構角色,具體裝飾角色要實作這個接口—Person(抽象類)

2、具體建構角色(Concrete Component):這是被裝飾着,定義一個将要被裝飾增加功能的類。

    *具體建構角色 實作抽象建構角色這個接口 —西施

3、具體裝飾角色(Concrete Decorator):負責給構件添加增加的功能。

    *具體裝飾角色 要實作 抽象建構角色這個接口 —東施

    *增加一個構造方法,參數為抽象建構角色類型,接收不能改變類的對象(西施)

    *實作filter這個接口

     *擷取具體建構角色中的内容 —-西施

    *增加新的要求 —-打扮西施

例7、為論壇過濾掉不雅文字。

javaee學習之路(六)Servlet過濾器

第一步、content.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
    留言闆:${content}
    <form action="${pageContext.request.contextPath}/servlet/ContentServlet" method="post">
      <input type="text" name="content">
      <input type="submit" value="留言">  
    </form>
  </body>
</html>
           

第二步、過濾器IlleagleFilter.java

package cn.itcast.filter;
import *;
public class IlleagleFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {   }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        MyHttpServletRequestWrapper httpServletRequestWrapper=
                    new MyHttpServletRequestWrapper((HttpServletRequest)request);
        chain.doFilter(httpServletRequestWrapper, response);
    }
    public void destroy() { }
}
           

第三步、web.xml

<filter>
   <filter-name>IlleagleFilter</filter-name>
   <filter-class>cn.itcast.filter.IlleagleFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>IlleagleFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
           

第四步、ContentServlet.java

package cn.itcast.web;
import *;
public class ContentServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        String content=request.getParameter("content");
        request.setAttribute("content", content);
        request.getRequestDispatcher("/content.jsp").forward(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
           

第五步、filter.properties

a1=bad1
a2=bad2
a3=bad3
           

第六步、MyHttpServletRequestWrapper.java

package cn.itcast.filter;
import *;
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{
    private static List list=null;
    public MyHttpServletRequestWrapper(HttpServletRequest request){
        super(request);
    }
    static{
        InputStream ins=
MyHttpServletRequestWrapper.class.getResourceAsStream("filter.properties");
        Properties prop=new Properties();
        try{
            prop.load(ins);
            /*
             * a1=bad1
             * a2=bad2
             * a3=bad3
             */
            Collection c=prop.values();
            list=new ArrayList(c);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 重寫該方法,在ContentServlet中調用的就是getParameter方法
     */
    @Override
    public String getParameter(String name) {
        //擷取的值
        String str=super.getRequest().getParameter(name);
        //包含               更改
        if(list!=null){
            for(int i=;i<list.size();i++){
                if(str.contains((String)list.get(i))){
                str=str.replaceAll((String)list.get(i), "*****************");

                }
            }
        }
    return str;
    }
}
           

第七步、在IE中鍵入http://localhost:8080/day18IlleagleFilter/content.jsp 加入留言内容

即可看到效果。

繼續閱讀