例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请求参数的中文问题
第一步、
第二步、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程序的拦截处理过程将被执行多次
<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”);
-
并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头
问题演示:
第一步、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来做
第一步、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
第二种方法:过滤器
第一步、配置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
破坏情况(新开一个浏览器)
装饰模式
案例:
1、IMessageBoard.java
package cn.itcast.test;
public interface IMessageBoard {
public String filter();
}
- 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方法的代码的情况下输出你喜欢和平吗,如何解决?
方法一、可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性。
第一步、新建一个类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提供了”即插即用”的方法,在运行期间决定何时增加何种功能
第一步、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、为论坛过滤掉不雅文字。
第一步、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 加入留言内容
即可看到效果。