天天看点

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 加入留言内容

即可看到效果。

继续阅读