设置编码过滤器、用户在线验证(session检测)过滤器、记录访问时间过滤器,在web.xml的<web-app>标签里面,设置多个<filter>,添加的代码如下。
<filter>
<filter-name>encodeFilter</filter-name>
<filter-class>com.demo.filter.EncodeFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodeFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- "/*"即对所有的请求进行过滤 -->
</filter-mapping>
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.demo.filter.LoginFilter</filter-class>
<init-param>
<param-name>gotoUrl</param-name>
<param-value>/login.jsp</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>countTimeFilter</filter-name>
<filter-class>com.demo.filter.CountTimeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>countTimeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
可以看到设置了三个过滤器:编码过滤器、用户在线验证(session检测)过滤器、记录访问时间过滤器。过滤器(Filter)的执行顺序为:encodeFilter--loginFilter--countTimeFilter,对于一个MVC系统,整个过程顺序应该是这样的:‘V’--‘Filter’--‘C’--‘M’--‘Filter’--‘V’,见过有一张图片很形象描述出整个过程顺序的,有兴趣的可以找找。在每个过滤器(Filter的子类)的doFilter()方法,都会带有“chain.doFilter(request,response);”这样一行代码,意味:本过滤器主要方法执行完了下一个过滤器来的猛烈些吧,注意,此时过滤器没关掉,过滤器是每当用户访问时,是最先被调用的(在”过程顺序“的开头),也是最后才关闭的(在”过程顺序“的结尾)。下面分别对每个过滤器做介绍。
(1)编码过滤器的路径为:com.demo.filter.EncodeFilter,详细介绍见上一篇文章,这里附上其部分的代码:
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
if (!ignore) {
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(encode);
}
}
wordFiltering(request,response);
chain.doFilter(request,response);
}
(2)用户在线验证(session检测)过滤器的路径为com.demo.filter.LoginFilter。该过滤器要注意其在web.xml的映射设置,若设置为<url-pattern>/*</url-pattern>,则页面从服务器传到浏览器时将只有文字,页面的图片、样式等等元素都被过滤了,结果大吃一斤有木有,当时我就大吃两斤了,后来参考网上的资料,改成<url-pattern>*.jsp</url-pattern>就解决了问题,“/*”的用法还是讲技巧的。当用户访问页面时,每个操作都会检测用户的session是否存在,若用户没有正常登陆则不会执行用户的操作并转到登陆页面,当然,改过滤器对某些页面设置了放行,放行的页面参见类的成员变量permitUrlList。另外,过滤器也设置了访问ip过滤、特殊用户过滤,访问ip过滤参见类的成员变量permitUrlList,特殊用户过滤参见类的成员变量userBlockList。该类的代码如下。
package com.demo.filter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* 限制IP访问
* 限制用户访问
* 限制离线操作
*/
public class LoginFilter implements Filter{
private boolean ignore = false;
private String gotoUrl = null;
private List<String> ipBlockList = new ArrayList<String>();
private List<String> userBlockList = new ArrayList<String>();
private List<String> permitUrlList = new ArrayList<String>();
public void init(FilterConfig filterConfig) throws ServletException {
String ignore = filterConfig.getInitParameter("ignore");
String gotoUrl = filterConfig.getInitParameter("gotoUrl");
if ("1".equals(ignore) || "true".equals(ignore)) {
this.ignore = true;
}
this.gotoUrl = gotoUrl;
this.ipBlockList.add("222.2");
//this.ipBlockList.add("127.0");
this.userBlockList.add("test1");
this.userBlockList.add("test2");
this.permitUrlList.add("group.jsp");
this.permitUrlList.add("login.jsp");
this.permitUrlList.add("register.jsp");
}
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse)response;
if(!ignore){
if(checkIP(request,response)){ //限制IP访问
String username = (String)req.getSession().getAttribute("username");
if(username!=null){ //限制离线操作
for(String userBlock : userBlockList){ //限制用户访问
if(username.equals(userBlock)){
PrintWriter out = response.getWriter();
out.println("<h3>Sorry for your Permission...</h3>");
out.flush();
return;
}
}
chain.doFilter(request, response);
}else{
String uri = req.getRequestURI();
System.out.print(uri);
for(String permitUrl : permitUrlList){
if(uri.indexOf(permitUrl)>0){
chain.doFilter(request, response);
return;
}
}
resp.sendRedirect(req.getContextPath() + gotoUrl);
}
}
}
}
private boolean checkIP(ServletRequest request, ServletResponse response) throws IOException, ServletException {
String addr = request.getRemoteAddr();
for(String a:ipBlockList){
if(addr.indexOf(a)==0){
PrintWriter out = response.getWriter();
out.println("<h3>Sorry for your IPaddress...</h3>");
out.flush();
return false;
}
}
return true;
}
public void destroy() {
ignore = false;
gotoUrl = null;
}
}
(3)访问时间记录过滤器的路径为com.demo.filter.CountTimeFilter,实现的方法比较简单,代码如下所示。
package com.demo.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.LogFactory;
import sun.security.krb5.Config;
/*
*记录用户的访问时间
*/
public class CountTimeFilter implements Filter{
private long startTime;
private long endTime;
private FilterConfig filterConfig = null;
public void init(FilterConfig config) throws ServletException {
this.filterConfig = config;
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
String username = (String)req.getSession().getAttribute("username");
String uri = req.getRequestURI();
startTime = System.currentTimeMillis();
chain.doFilter(request, response);
endTime = System.currentTimeMillis();
long countTime = endTime-startTime;
filterConfig.getServletContext().log("CountTimeFilter:'"+username+"' visited '"+uri+"' in "+ countTime +"ms");
}
}
如有其它的意见欢迎补充~