@yangjy
2015-01-08T16:51:19.000000Z
字数 4299
阅读 1240
过滤器
java
Servlet
Servlet过滤器是服务器与客户端请求与响应的中间层组件,在实际项目开发中Servlet过滤器主要用于对浏览器的请求进行过滤处理,将过滤后的请求转给下一资源。其实,Servlet过滤器与Servlet十分相似,只是多了一个具有拦截浏览器请求的功能。过滤器可以改变请求的内容来满足客户的需求。
开发一个过滤器必须实现Java定义好的javax.servlet.Filter接口:
这一接口含有三个过滤器必须执行的方法:
- doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。同样也是上层过滤器调用的方法。引入的FilterChain对象提供了后续过滤器所要调用的信息。如果该过滤器是过滤器链中的最后一个过滤器,则将请求交给被请求资源。也可以直接给客户端返回响应信息。
- init(FilterConfig):由Web容器来调用完成过滤器的初始化工作。它保证了在第一次doFilter()调用前由容器调用。能获取在 web.xml 文件中指定的初始化参数。
- destroy():由Web容器来调用来释放资源,doFilter()中的所有活动都被该实例终止后,调用该方法。
在编写Web程序时,经常出现乱码现象,本实例使用Servlet过滤器解决乱码问题。
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
this.request = (HttpServletRequest) request;
this.response = (HttpServletResponse) response;
charset = filterConfig.getInitParameter("charset");
System.out.println("ConfigFilter " + charset);
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
chain.doFilter(request, response);//请求转发
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;//从Web务器获取过滤器配置对象
}
过滤器开发完成后还需要在web.xml中进行配置。
代码演示:web.xml 中加入Filter配置
<filter>
<filter-name>ConfigFilter</filter-name>
<filter-class>com.filter.ConfigFilter</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ConfigFilter</filter-name>
<url-pattern>/FilterServlet</url-pattern>
</filter-mapping>
<filter>节点描述该Filter对应的类是哪一个。写明具体路径
<filter-mapping>中的<filter-name>必须和<filter>节点中的<filter-name>值相同,<init-param> 是Filter的参数。获取该参数的方式为:
public void init(FilterConfig filterConfig) throws ServletException {
charset=filterConfig.getInitParameter("charset"); }
- 防止通过其它URL地址直接访问本站资源。当URL地址不是本站地址时,在网页中显示错误信息。
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String imurl = request.getRemoteAddr();
System.out.println("request.getServerName() " + request.getServerName());
System.out.println("imurl :" + imurl);
if(imurl == null || !imurl.contains(request.getServerName())){
request.getRequestDispatcher("../error.jsp").forward(request, response);
}else{
chain.doFilter(request, response);
}
}
public void init(FilterConfig chain) throws ServletException {
}
在实际的项目开发过程中,经常需要在项目运行时记录并在控制台输出运行时的日志信息,便于查看运行状况。
private Log log = LogFactory.getLog(this.getClass());
private String filterName;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
long startTime = System.currentTimeMillis(); //运行前的时间
String requestURI = request.getRequestURI(); //获取访问的URI
//所有的地址栏信息
requestURI = request.getQueryString() == null ? requestURI:(requestURI+ "?" +request.getQueryString());
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
log.info(request.getRemoteAddr() + " 访问了 " + requestURI + ",总用时 " + (endTime-startTime) + " 毫秒。");
log.hashCode();
}
public void init(FilterConfig chain) throws ServletException {
filterName = chain.getFilterName();//获取Filter的name,启动Filter
log.info("****** 启动 Filter:" + filterName);
}
Filter日志最大的优点在于可拆卸性,当不需要记录日志信息功能时,只需要将Filter配置注释掉即可。
Servlet过滤器可以对用户提交的数据或服务器返回的数据进行更改。任何到达服务器的请求都会首先经过过滤器的处理。本实例应用过滤器的这个特点编写一个用于访问量统计的过滤器。
private static int num = 0;//定义全局变量
public synchronized void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
this.num++;
request.setAttribute("num", String.valueOf(num));
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
- 异常捕获
- 对用户的身份进行验证
- 对用户发送的数据进行过滤和替换
- 监控网站流量
- 防止页面缓存
- 对请求和相应加密处理
- 精确匹配,就是填写jsp或Servlet等需要过滤的请求的具体地址,例如:/Filter/TestFilter
- 扩展匹配,由“*”号和扩展名组成,例如*.jsp
- 路径前缀匹配,包含一个目录和一个/* 例如:/Servlet/*指的是对Servlet目录下的所有资源进行过滤
- 全部匹配,使用/*,指的是对所有资源都过滤
在Filter执行的整个过程中客户端和目标资源是不知道过滤器的存在的。Filter提供的是一种声明式的服务,即在不用在原程序上做任何修改,只需要编写Filter,原程序想用Filter,只需要在XML文件中声明一下即可。他具有可插拔的能力,用的时候配上web.XML,不用的时候只需要修改web.xml,对整个系统没有影响,这种声明式的服务非常方便,也非常强大。
其次,使用Filter进行控制业务也非常方便,比如验证用户是否登录,是否有操作权限,判断Session,字符集等,放到Filter里,可以省去大量重复的代码和繁琐的控制。