struts2与先前的struts不同之一就是:struts使用servlet类来处理前台消息,而struts2使用filter类来处理前台消息,有很多人喜欢把filter也称为一种特殊的servlet,因为它确实在struts2中所实现的功能几乎和servlet一个样子刻出来的,但其终究还不是完全的servlet,否则也不会叫filter了。filter与servlet最大的不同之处就在于:filter只能进行消息的预处理(可以是前台传来的消息,或者是servlet向前台进行输出的消息),却不能直接向用户生成响应;一个filter可同时处理多个用户请求,而一个servlet只能处理单个请求。filter的生命周期和servlet大体相同:
1.void init():初始化filter;
2.void destroy():销毁filter前,回收某些资源;
3.void doFilter():filter的实现主体;
filter的配置方式也和servlet差不多,但要注意的是,servlet由于只能处理单个请求,所以其url不能是匹配型的,而filter可处理多个请求,其Url既可以是匹配型的,也可以是指定的单个请求。如下所示:
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意看url-pattrn的区别。如果在servlet-mapping的url-pattern配置为/*,则会出现运行错误。
我们来看一个简单登陆案例:在客户端输入用户名和密码时,filter负责获取客户端IP地址和定位消息处理URL,servlet负责验证登陆信息是否正确。
index.jsp关键代码如下(两个输入框和一个提交按钮):
<body>
<form action="login.do" id = "login" method="get">
user name:<input type="text" name="username"><br/>
user password:<input type = "text" name="userpassword"><br/>
<input type = "submit" value = "login">
</form>
</body>
success.jsp代码如下:
success!
error.jsp代码如下:
<body>
<%=request.getAttribute("err") %><br/>
login failed!
</body>
FirstFilter类代码如下(向控制台输出客户端IP地址和消息处理URL):
package com.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class FirstFilter implements Filter{
private FilterConfig config;
public void destroy() {
config = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpServletResponse httpResponse = (HttpServletResponse)response;
long before = System.currentTimeMillis();
System.out.println("开始过滤。。。");
System.out.println("拦截到用户IP地址:"+ httpRequest.getRemoteAddr());
chain.doFilter(request, response);//过滤器不进行消息处理,消息处理继续传递到servlet中进行响应
long after = System.currentTimeMillis();
System.out.println("过滤结束!过滤所花时间为:"+ (after-before) );
System.out.println("请求被定为到:" + httpRequest.getRequestURL());
// if("James".equals(request.getAttribute("username") ) && "admin".equals(request.getAttribute("userpassword")))
// {
// RequestDispatcher dispatcher = request.getRequestDispatcher("/success.jsp");
// dispatcher.forward(request, response);
// }
// else
// {
// RequestDispatcher dispatcher = request.getRequestDispatcher("/error.jsp");
// dispatcher.forward(request, response);
// }
}
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}
LoginServlet类代码如下(对登陆信息进行验证):
package com.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet{
private String userpassword;
private String username;
public void service(HttpServletRequest request,HttpServletResponse response)
{
RequestDispatcher dispatcher;
username = request.getParameter("username");
userpassword = request.getParameter("userpassword");
if("James".equals(username)&& "admin".equals(userpassword))
{
dispatcher = request.getRequestDispatcher("/success.jsp");
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
dispatcher = request.getRequestDispatcher("/error.jsp");
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
web.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
在控制台中输出的结果为:
开始过滤。。。
拦截到用户IP地址:10.0.0.121
过滤结束!过滤所花时间为:625
请求被定为到:http://pc-201101141739:8080/try/ 或 请求被定为到:http://pc-201101141739:8080/try/login.do
另外需要特别注意的一点是:servlet中可以进行的消息处理行为(向前台输出内容除外),在filter中也可以进行处理。为了进行验证,我们可以把上面filter代码中注释部分去掉,则网页一开始就会显示为:
terrible!
login failed!
这就是说,在这里,我们完全可以不用servlet,而只单用一个filter就能进行所有的消息处理。这也是struts2的消息处理机制:struts2的配置文件中没有servlet类的配置,只有一个filter的配置,由此可以看出其用filter处理所有的消息,至于如何处理前台传来的各种消息,我会在下一篇文章中详细阐述。