标签:
过滤器是一个程序,它先于与之相关的Servlet页面运行在服务器上,但它并不是一个标准的Servlet,它不能处理用户请求,也不能对客户端生成响应。它主要用于对HttpServletRequest
进行预处理,也可以对HttpServletResponse
进行后处理。过滤器可以附加到一个或多个Servlet、JSP页面或者是HTML静态页面上,然后检查进入这些资源的请求信息。它对这些请求进行拦截,从而实现一些特殊的功能,比如可以实现权限访问控制,过滤敏感词汇,设置统一字符集等功能。
<filter-mapping>
的顺序决定在Servlet作为过滤器使用时,它可以对客户的请求进行处理。处理完成之后,它会交给下一个过滤器处理,这样,客户的请求在过滤器链中逐个处理,直到请求发送到目标为止。例如,我们访问用户管理系统的某个页面,服务器在进行处理时需要做两项工作:①判断客户端的会话是否有效然后检查权限;②对提交的数据进行统一编码。这两项工作可以在由两个过滤器组成的过滤器链中进行处理。当过滤器处理成功后,再把提交的数据发送到最终目标。
可以看一下过滤器链在整个Web应用中的位置:
开发Servlet过滤器的步骤为:
1.编写实现Filter接口的Servlet类。
2.在web.xml中配置Filter
开发一个过滤器需要实现Filter接口,Filter接口定义了以下方法:
destory()
由web容器调用,销毁此Filter
init(FilterConfig filterConfig)
由Web容器调用,初始化此Filter
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
具体处理过滤的代码
一个过滤器的代码类似如下,其中最重要的是在doFilter()方法中的实现自己对request和response的过滤:
public class MyFilter implements Filter {
@Override
public void destroy() {
//销毁代码
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain chain) throws IOException, ServletException {
//具体的过滤细节
}
@Override
public void init(FilterConfig arg0) throws ServletException {
//初始化代码
}
}
过滤器的部署细节与Servlet很相似,Servlet是要配置<servlet>
和<servlet-mapping>
,而过滤器是要配置<filter>
和<filter-mapping>
配置如下所示,假设我的Filter放在com.gavin.filter包下:
<filter>
<filter-name>FilterName</filter-name>
<filter-class>com.gavin.filter.FilterName</filter-class>
</filter>
配置mapping的方法有很多种,根据映射到Servlet或者JSP的不同,相应的配置也不相同:
(1)映射到一个或多个Servlet
filter-mapping>
<filter-name>FilterName</filter-name>
<servlet-name>ServletName1</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>FilterName</filter-name>
<servlet-name>ServletName2</servlet-name>
</filter-mapping>
(2)映射到一个或多个JSP:
<filter-mapping>
<filter-name>FilterName</filter-name>
<url-pattern>/path/FileName.jsp</url-pattern>
</filter-mapping>
(3)映射到任意的URL:
<filter-mapping>
<filter-name>FilterName</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在实际应用中,要特别注意过滤器链的执行顺序问题,web服务器根据过滤器在web.xml文件中的注册顺序,决定先调用哪个过滤器,当第一个过滤器的doFilter方法被调用时,web服务器会创建一个代表过滤器链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
在【Servlet(2)之简单应用】中,我们介绍了使用Session防止用户非法登录到某个页面,采用的是在登录页面将用户信息放入Session,在需要防止非法登录的页面取出登录的信息,如果没有登录用户的信息,则为非法登录,然后将其强制跳转到登录页面。
那么就出现了一个问题,如果我们的Web应用有很多个需要防止非法登录的页面怎么办?一个个都这样处理肯定非常麻烦。这时候,过滤器的应用就让这个问题变得非常简单。
首先,我们编写CheckUserFilter,它的doFilter()代码如下:
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)arg0;
HttpServletResponse response = (HttpServletResponse)arg1;
User login_user = (User)request.getSession().getAttribute("login-user");
if(login_user == null){
// 说明用户没有登录,让他跳转到错误页面
request.setAttribute("error", "请登录!");
request.getRequestDispatcher("/LoginServlet").forward(request,response);
}else{
// 让其通过
chain.doFilter(request, response);
}
}
可以看到,在doFilter中,我们去判断Session中是否有登录用户的信息,如果有,让其通过;如果没有,则强制跳转到登录页面。然后我们对这个Filter进行部署,假设我们的主页面MainFrame,添加用户的页面AddUser和更新用户的页面UpdateUser都需要防止非法登录,则可以让其映射到所有的这些Servlet上,部署如下:
<filter>
<filter-name>CheckUserFilter</filter-name>
<filter-class>com.gavin.filter.CheckUserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CheckUserFilter</filter-name>
<servlet-name>MainFrame</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>CheckUserFilter</filter-name>
<servlet-name>AddUser</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>CheckUserFilter</filter-name>
<servlet-name>UpdateUser</servlet-name>
</filter-mapping>
实验可得,在没有登录之前去访问MainFrame、AddUser或者UpdateUser,都会提示错误信息,然后跳转到登录页面。
其实过滤器还有更多的知识与细节,比如request、forward、include和error四种过滤器的具体使用方法等。这些知识在这里先不展开,后续用到再补充。
标签:
原文地址:http://blog.csdn.net/gavin_john/article/details/51387976