了解Servlet过滤器的概念
了解Servlet过滤器的工作过程
掌握创建Servlet过滤器的方法
掌握发布Servlet过滤器的方法
1、Servlet过滤器的概念
Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。
Servlet过滤器本身并不生成请求和响应对象,他只提供过滤作用。
Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容;
在Servlet被调用之后检查Response对象,修改responseHeader和Response内容。Servlet过滤器负责过滤的Web组件可以是Servlet、JSP或HTML文件
2、Servlet过滤器的过滤过程
3、Filter接口
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:
init()、doFilter()、destory()
每一个过滤器都要在web容器部署描述符中,就是web.xml中进行部署
- init(FilterConfig):这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数
- doFilter(ServletRequest,ServletResponse,FilterChain):这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器
- destroy():Servlet容器在销毁过滤器实例前调用该方法,在这个方法中可以释放Servlet过滤器占用的资源。
过滤器的链式请求处理过程FilterChain示意图:
过滤器如果出现错误,整个服务就将失败
4、一个具体的Filter:
import java.io.IOException; 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; import javax.servlet.http.HttpSession; public class LoginFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest r = (HttpServletRequest)request; HttpSession session = r.getSession(); String requestURI = r.getRequestURI(); if(requestURI.endsWith("login.jsp") || requestURI.endsWith("MyLoginServlet")) { chain.doFilter(request, response); return; } if(null == session.getAttribute("user")) { ((HttpServletResponse)response).sendRedirect("filter/login.jsp"); return; } else { chain.doFilter(request, response); } } public void init(FilterConfig filterConfig) throws ServletException { System.out.println("filter init invoke!"); } }
部署描述符中的配置:
<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.cdtax.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
一个使用filter过滤器的实例:一个输入页面comment.jsp,有username和comment两个输入域,提交后由一个servlet处理转向一个显示页面,一个过滤器对输入的内容进行过滤,username中含有123则替换为abc,comment中有wokao替换为****
comment.jsp
page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'comment.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="CommentServlet" method="post"> username:<input type="text" name="username"/><br/> commnet:<textarea name="comment" rows="7" cols="7"></textarea><br/> <input type="submit" value="submit"/> </form> </body> </html>
CommentServlet:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CommentServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getRequestDispatcher("commentResult.jsp").forward(req, resp); } }
显示页面:commentResult.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'commentResult.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> username:<%= request.getAttribute("username") %><br/> comment:<%= request.getAttribute("comment") %> </body> </html>
过滤器:CommentFilter
import java.io.IOException; 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; public class CommentFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse resp = (HttpServletResponse)response; String username = req.getParameter("username"); String comment = req.getParameter("comment"); username = username.replace("123", "abc"); comment = comment.replace("wokao", "****"); req.setAttribute("username", username); req.setAttribute("comment", comment); chain.doFilter(request, response); } public void init(FilterConfig filterConfig) throws ServletException { } }
web.xml中的部署
<filter> <filter-name>CommentFilter</filter-name> <filter-class>com.cdtax.filter.CommentFilter</filter-class> </filter> <filter-mapping> <filter-name>CommentFilter</filter-name> <url-pattern>/CommentServlet</url-pattern> </filter-mapping>
5、串联Servlet过滤器的工作流程
客户并不知道过滤器的存在,过滤器完全是服务器端的行为
过滤器链的实例
info.jsp
<body> <form action="InfoServlet" method="post"> username:<input type="text" name="username"/><br/> <input type="submit" value="submit"/>" </form> </body>
InfoServlet:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class InfoServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println(req.getParameter("username")); req.getRequestDispatcher("infoResult.jsp").forward(req, resp); } }
infoResult.jsp:
<body> <%= request.getParameter("username") %> </body>
过滤器MyFilter1和MyFilter2
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class MyFilter1 implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("Filter1 before chain.doFilter"); chain.doFilter(request, response); System.out.println("Filter1 after chain.doFilter"); } public void init(FilterConfig filterConfig) throws ServletException { } } import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class MyFilter2 implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("Filter2 before chain.doFilter"); chain.doFilter(request, response); System.out.println("Filter2 after chain.doFilter"); } public void init(FilterConfig filterConfig) throws ServletException { } }
web.xml配置:
<filter> <filter-name>MyFilter1</filter-name> <filter-class>com.cdtax.filter.MyFilter1</filter-class> </filter> <filter> <filter-name>MyFilter2</filter-name> <filter-class>com.cdtax.filter.MyFilter2</filter-class> </filter> <filter-mapping> <filter-name>MyFilter1</filter-name> <url-pattern>/InfoServlet</url-pattern> </filter-mapping> <filter-mapping> <filter-name>MyFilter2</filter-name> <url-pattern>/InfoServlet</url-pattern> </filter-mapping>
Filter的执行顺序是跟配置中的<filter-mapping>相关联的,哪个<filter-mapping>在前,就先执行哪个Filter,如将上面的配置改为
<filter-name>MyFilter2</filter-name> <url-pattern>/InfoServlet</url-pattern> </filter-mapping> <filter-mapping> <filter-name>MyFilter1</filter-name> <url-pattern>/InfoServlet</url-pattern> </filter-mapping>
其他不动,执行结果为:
Filter2 before chain.doFilter
Filter1 before chain.doFilter
wwww
Filter1 after chain.doFilter
Filter2 after chain.doFilter
执行的结果:
Filter1 before chain.doFilter
Filter2 before chain.doFilter
wwww
Filter2 after chain.doFilter
Filter1 after chain.doFilter
6、关于FilterConfig
在web.xml中filter可以带参数:
<filter> <filter-name>CommentFilter</filter-name> <filter-class>com.cdtax.filter.CommentFilter</filter-class> <init-param> <param-name>hello</param-name> <param-value>world</param-value> </init-param> <init-param> <param-name>zhang</param-name> <param-value>li</param-value> </init-param> </filter>
在Filter中通过FilterConfig获得参数的方法:
public void init(FilterConfig filterConfig) throws ServletException { String value1 = filterConfig.getInitParameter("hello"); String value2 = filterConfig.getInitParameter("zhang"); System.out.println(value1 + value2); }
通过FilterConfig可以获得ServletContext对象,也就是application,语法:
ServletContext sc = filterConfig.getServletContext();
相当于使用request:
ServletContext sc = request.getSession().getServletContext();