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>
<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>
- <formaction="login.do"id = "login"method="get">
- user name:<inputtype="text"name="username"><br/>
- user password:<inputtype = "text"name="userpassword"><br/>
- <inputtype = "submit"value = "login">
- </form>
- </body>
<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>
<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;
- publicclass FirstFilter implements Filter{
-
- private FilterConfig config;
- publicvoid destroy() {
- config = null;
- }
-
- publicvoid 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);
- // }
- }
-
- publicvoid init(FilterConfig config) throws ServletException {
- this.config = config;
- }
- }
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;
- publicclass LoginServlet extends HttpServlet{
- private String userpassword;
- private String username;
- publicvoid 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();
- }
- }
- }
- }
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配置文件如下:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <web-appversion="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>
<?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处理所有的消息,至于如何处理前台传来的各种消息,我会在下一篇文章中详细阐述。