看了网上一篇译文《Servlet 2.3 过滤器编程》原文 《Filter code with Servlet 2.3 model 》出自http://www.javawold.com/。里面讲了四个例子,有三个意思不大,没有仔细看。
一、web.xml文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<!-- CLICKSTREAM LOGGER -->
<filter>
<filter-name>clickstreamFilter</filter-name>
<filter-class>com.java3z.examples.ClickstreamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>clickstreamFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>clickstreamFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<listener>
<listener-class>com.java3z.examples.ClickstreamLogger</listener-class>
</listener>
<!-- END CLICKSTREAM LOGGER -->
</web-app>
这注册了ClickstreamFilter并设置其处理*.jsp和*.html来的请求。这也将ClickstreamLogger注册为一个监听器以在应用事件发生时接受他们。
二、既是ServletContextListener又是 HttpSessionListener监听器ClickstreamLogger类
package com.java3z.examples;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ClickstreamLogger implements ServletContextListener, HttpSessionListener
{
Map clickstreams = new HashMap();
public ClickstreamLogger()
{
// System.out.println("ClickstreamLogger constructed");
}
public void contextInitialized(ServletContextEvent sce)
{
// System.out.println("ServletContext Initialised");
sce.getServletContext().setAttribute("clickstreams", clickstreams);
}
public void contextDestroyed(ServletContextEvent sce)
{
sce.getServletContext().setAttribute("clickstreams", null);
// System.out.println("ServletContext Destroyed");
}
public void sessionCreated(HttpSessionEvent hse)
{
// System.out.println("Session Created");
HttpSession session = hse.getSession();
Clickstream clickstream = new Clickstream();
session.setAttribute("clickstream", clickstream);
clickstreams.put(session.getId(), clickstream);
}
public void sessionDestroyed(HttpSessionEvent hse)
{
// System.out.println("Session Destroyed");
HttpSession session = hse.getSession();
Clickstream stream = (Clickstream)session.getAttribute("clickstream");
clickstreams.remove(session.getId());
System.out.println("Final session clickstream:\n" + stream);
}
}
ClickstreamLogger类在servlet环境创建时设置全局属性getServletContext.setAttribute("clickstreams", clickstreams),一个
Map,在用户访问网站时设置会话属性session.setAttribute("clickstream", clickstream),并将可记录会话数据的对象clickstream
放入Map,以便在JSP页面中输出网站访问者的信息。
三、过滤器ClickstreamFilter类
package com.java3z.examples;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class ClickstreamFilter implements Filter {
protected FilterConfig filterConfig;
private final static String FILTER_APPLIED = "_clickstream_filter_applied";
public void init(FilterConfig config) throws ServletException {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 确保该过滤器在每次请求中只被使用一次
if (request.getAttribute(FILTER_APPLIED) == null) {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
HttpSession session = ((HttpServletRequest)request).getSession();
Clickstream stream = (Clickstream)session.getAttribute("clickstream");
stream.addRequest(((HttpServletRequest)request));
}
// 传递请求
chain.doFilter(request, response);
}
public void destroy() { }
}
doFilter ()方法取得用户的session,从中获取Clickstream,并将当前请求数据加到Clickstream中。其中使用了一个特殊的 FILTER_APPLIED标记属性来标注此过滤器是否已经被当前请求使用(可能会在请求调度中发生)并且忽略所有其他的过滤器行为。
四、保存请求数据的Clickstream类
package com.java3z.examples;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Clickstream implements Serializable
{
List clickstream = new ArrayList();
String hostname = null;
HttpSession session = null;
String initialReferrer = null;
Date start = new Date();
Date lastRequest = new Date();
boolean bot = false;//是否是机器人访问
public Clickstream()
{
}
public void addRequest(HttpServletRequest request)
{
lastRequest = new Date();
if (hostname == null) {
hostname = request.getRemoteHost();
session = request.getSession();
}
// if this is the first request in the click stream
if (clickstream.size() == 0)
{
// setup initial referrer
if (request.getHeader("REFERER") != null)
{
initialReferrer = request.getHeader("REFERER");
}
else
{
initialReferrer = "";
}
// decide whether this is a bot
bot = BotChecker.isBot(request, this);
}
clickstream.add(request.getServerName() +
(request.getServerPort() != 80 ? ":" + request.getServerPort() : "") +
request.getRequestURI() +
(request.getQueryString() != null ? "?" + request.getQueryString() : ""));
// System.out.println(this.toString());
}
public String getHostname()
{
return hostname;
}
public boolean isBot()
{
return bot;
}
public void setBot(boolean value)
{
this.bot = value;
}
public HttpSession getSession()
{
return session;
}
public String getInitialReferrer()
{
return initialReferrer;
}
public Date getStart()
{
return start;
}
public Date getLastRequest()
{
return lastRequest;
}
public List getStream()
{
return clickstream;
}
public String toString()
{
StringBuffer output = new StringBuffer();
output.append("Clickstream for: " + hostname + "\n");
output.append("Session ID: " + (session != null ? session.getId() + "" : "") + "\n");
output.append("Initial Referrer: " + initialReferrer + "\n");
output.append("Stream started: " + start + "\n");
output.append("Last request: " + lastRequest + "\n");
long streamLength = lastRequest.getTime() - start.getTime();
output.append("Stream length:" +
(streamLength > 3600000 ?
" " + (streamLength / 3600000) + " hours" : "") +
(streamLength > 60000 ?
" " + ((streamLength / 60000) % 60) + " minutes" : "") +
(streamLength > 1000 ?
" " + ((streamLength / 1000) % 60) + " seconds" : "") +
"\n");
Iterator clickstreamIt = clickstream.iterator();
int count = 0;
while (clickstreamIt.hasNext())
{
count++;
output.append(count + ": " + clickstreamIt.next() + "\n");
}
return output.toString();
}
}
五、是机器人吗?
BotChecker类用来确定客户端是否是一个机器人。
package com.java3z.examples;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class BotChecker
{
public static String[] botHosts = {"inktomi.com", "inktomisearch.com", "googlebot.com", "linuxtoday.com.au"};
public static boolean isBot(HttpServletRequest request, Clickstream stream)
{
String requestURI = request.getRequestURI();
// if it requested robots.txt, it's a bot
if (requestURI.indexOf("robots.txt") >= 0)
{
return true;
}
// it requested a RSS feed from our backend, it's a bot
if (requestURI.indexOf("/backend/") >= 0)
{
return true;
}
for (int i = 0; i < botHosts.length; i++)
{
if (request.getRemoteHost().indexOf(botHosts[i]) >= 0)
{
return true;
}
}
return false;
}
}
六、测试:请下载测试这个WEB应用的所有文件。