例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 加入留言内容
即可看到效果。