·配置 Tomcat5.5 站点

n 本训练实现过滤器程序。

·过滤器研究

n 创建 public class RequestLoggingFilter implements Filter，一个过滤器类，我们用这个过滤器实现用户请求（request）的日志功能，RequestLoggingFilter 类完整代码如下。

package jsplession;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class RequestLoggingFilter implements Filter {

private FilterConfig config = null;

private FileOutputStream fos;

public void init(FilterConfig _config) throws ServletException {

this.config = _config;

try {

/* Timestamp log file */

File f = new File("RequestLoggingFilter_" + new Date().getTime()

+ ".log");

fos = new FileOutputStream(f);

} catch (FileNotFoundException e) {

System.out.println("Error opening log file.");

System.out.println(e.toString());

}

}

public void doFilter(ServletRequest _req, ServletResponse _res,

FilterChain _chain) throws IOException, ServletException {

/* Log HTTP form parameters */

if (_req instanceof HttpServletRequest) {

String log = getParms((HttpServletRequest) _req);

fos.write(log.getBytes());

}

/* Continue with filter chain */

_chain.doFilter(_req, _res);

}

public void destroy() {

config = null;

try {

fos.close();

} catch (IOException e) {

System.out.println("Error closing log file.");

System.out.println(e.toString());

}

}

private String getParms(HttpServletRequest _req) throws ServletException {

String newline = System.getProperty("line.separator");

StringBuffer log = new StringBuffer();

/* Get Http Parms */

log.append("HTTP Request: ");

log.append(new Date());

log.append(newline + newline);

log.append("Remote Address: " + _req.getRemoteAddr() + newline);

log.append("Remote Host: " + _req.getRemoteHost() + newline + newline);

Enumeration e = _req.getParameterNames();

while (e.hasMoreElements()) {

String key = (String) e.nextElement();

String[] values = _req.getParameterValues(key);

log.append(key + " = ");

for (int i = 0; i < values.length; i++) {

log.append(values[i] + " ");

}

log.append(newline);

}

return log.toString();

}

}

1. 定义私有属性 private FilterConfig config = null，表示过滤器的配置

2. 定义私有属性 private FileOutputStream fos，我们用这个文件输出流把日志内容保存到文件里。

3. 创建私有方法 private String getParms(HttpServletRequest _req)，在这个方法中利用 HttpServletRequest _req 参数，获得用户请求(request)的一些信息：客户端地址、客户端主机名和包含的用户数据：

· 客户端地址：_req.getRemoteAddr()

· 客户端主机名：_req.getRemoteHost()

· 请求中包含的各种用户数据：先获得所有变量名 Enumeration e = _req.getParameterNames()，以 e.hasMoreElements()为 while 语句的条件，得到每一个变量的值 String key = (String) e.nextElement();String[] values = _req.getParameterValues(key)

4. 重写 public void init(FilterConfig _config)方法，把参数_config 赋值给属性 config，并创建 fos 对象即 File f = new File("RequestLoggingFilter_" + new Date().getTime() + ".log"); fos = new FileOutputStream(f)，注意异常的处理。

5. 重写 public void doFilter(ServletRequest _req, ServletResponse _res, FilterChain _chain)方法，实现过滤的动作：

· 若_req 是 HttpServletRequest 的实例即 if (_req instanceof HttpServletRequest)，则调用 getParms()方法提取 request 中的信息即 String log = getParms((HttpServletRequest) _req)，并把日志内容保存到文件里即 fos.write(log.getBytes())

· 把控制权交给下一个 filter 即_chain.doFilter(_req, _res)

6. 重写 public void destroy()方法，把 config 设置为空 config=null，并关闭文件输出流 fos 即 fos.close()，注意异常的处理。

n 创建 public class ResponseLoggingFilter implements Filter，一个过滤器类，我们用这个过滤器实现响应（response）的日志功能，把响应包含的网页内容记录下来。ResponseLoggingFilter 类完整代码如下。

package jsplession;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class ResponseLoggingFilter implements Filter {

private FilterConfig config = null;

private FileOutputStream fos;

public void init(FilterConfig _config) throws ServletException {

this.config = _config;

try {

/* Timestamp log file */

File f = new File("ResponseLoggingFilter_" + new Date().getTime()

+ ".log");

fos = new FileOutputStream(f);

} catch (FileNotFoundException e) {

System.out.println("Error opening log file.");

System.out.println(e.toString());

}

}

public void doFilter(ServletRequest _req, ServletResponse _res,

FilterChain _chain) throws IOException, ServletException {

/* Wrap the response object */

final ByteArrayOutputStream os = new ByteArrayOutputStream();

final ServletOutputStream stream = new ServletOutputStream() {

public void write(int b) throws IOException {

os.write(b);

}

public String toString() {

return os.toString();

}

};

final PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));

final HttpServletResponse HttpRes = (HttpServletResponse) _res;

HttpServletResponse res = new HttpServletResponseWrapper(HttpRes) {

public ServletOutputStream getOutputStream() throws IOException {

return stream;

}

public PrintWriter getWriter() throws IOException {

return pw;

}

};

/* Continue Processing */

_chain.doFilter(_req, res);

pw.flush();

/* Log the response content */

StringBuffer log = new StringBuffer();

String newline = System.getProperty("line.separator");

log.append("*** HTTP Response: ").append(new Date()).append("***"+newline+newline);

String output = stream.toString();

log.append(output).append(newline+newline);

fos.write(log.toString().getBytes());

/* Write content to browser */

//_res.setContentLength(output.getBytes().length);

_res.getWriter().print(output);

_res.getWriter().close();

}

public void destroy() {

config = null;

try {

fos.close();

} catch (IOException e) {

System.out.println("Error closing log file.");

System.out.println(e.toString());

}

}

}

1. 定义私有属性 private FilterConfig config = null，表示过滤器的配置

2. 定义私有属性 private FileOutputStream fos，我们用这个文件输出流把日志内容保存到文件里。

3. 重写 public void init(FilterConfig _config)方法，把参数_config 赋值给属性 config，并创建 fos 对象即 File f = new File("ResponsetLoggingFilter_" + new Date().getTime() + ".log"); fos = new FileOutputStream(f)，注意异常的处理。

4. 重写 public void doFilter(ServletRequest _req, ServletResponse _res, FilterChain _chain)方法，实现过滤的动作，这里我们把 response 包含的网页内容提取出来，保存到日志文件中：

· 为了从 response 对象中提取网页内容，我们需要对 HttpServletResponse 进行包装，创建一个 HttpServletResponseWrapper 对象，利用这个对象完成从 response 对象中提取网页内容的功能，这个对象就是利用装饰模式对 response 对象进行了包装。

(1) 首先创建 final ByteArrayOutputStream os = new ByteArrayOutputStream()

(2) 在 ByteArrayOutputStream os 的基础上创建 ServletOutputStream stream，即：

final ServletOutputStream stream = new ServletOutputStream() {

public void write(int b) throws IOException {

os.write(b);

}

public String toString() {

return os.toString();

}

};

(3) 创建 final PrintWriter pw = new PrintWriter(new OutputStreamWriter(os));

(4) 将_res 强制转换为 HttpServletResponse 类型，即 final HttpServletResponse HttpRes = (HttpServletResponse) _res，HttpRes 为下一步提供参数。

(5) 用创建内部匿名类的方式创建 HttpServletResponse res，即

HttpServletResponse res = new HttpServletResponseWrapper(HttpRes) {

public ServletOutputStream getOutputStream() throws IOException {

return stream;

}

public PrintWriter getWriter() throws IOException {

return pw;

}

};

· 把控制权交给下一个过滤器_即 chain.doFilter(_req, res);pw.flush();

· 调用 stream.toString()就可以获得 response 对象中的网页内容，再保存到文件中，即：

StringBuffer log = new StringBuffer();

String output = stream.toString();

log.append(output).append(newline+newline);

fos.write(log.toString().getBytes());

· 最后再把网页把内容写到浏览器，即_res.getWriter().print(output);_res.getWriter().close();

5. 重写 public void destroy()方法，把 config 设置为空 config=null，并关闭文件输出流 fos 即 fos.close()，注意异常的处理。

n 在部署描述符文件（web.xml）中使用 filter 和 filter-mapping 元素，把特定的 URL 映射到这二个过滤器上，/*也就意味着全部的 URL：

<filter>

<filter-name>requestLoggingFilter</filter-name>

<filter-class>jsplession.RequestLoggingFilter</filter-class>

</filter>

<filter>

<filter-name>responseLoggingFilter</filter-name>

<filter-class>jsplession.ResponseLoggingFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>requestLoggingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>responseLoggingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

·署运行

n 部署文件

编译 ResponseLoggingFilter.java 和 RequestLoggingFilter.java，把 ResponseLoggingFilter.class 和 RequestLoggingFilter.class 放到 WEB-INF\classes\jsplession 目录下。

n 启动 Tomcat，启动 Mysql

n 在 IE 浏览器的地址栏中输入<http://localhost:8080/Decorating/census.jsp>

n 再输入合法数据，点击“提交”按钮，得到反馈信息。

n 在 Tomcat 的 bin 目录下，可以找到 RequestLoggingFilter_xxx.log 和 ResponseLoggingFilter_xxx.log 二个过滤器生成的日志文件，查看一下文件内容。