ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Filter ## 概念 Filter 的基本功能是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊的功能。 在 Servlet API 中定义了三个接口类来开供开发人员编写 Filter 程序:Filter, FilterChain, FilterConfig Filter 程序是一个实现了 Filter 接口的 Java 类,与 Servlet 程序相似,它由 Servlet 容器进行调用和执行 Filter 程序需要在 web.xml 文件中进行注册和设置它所能拦截的资源:Filter 程序可以拦截 Jsp, Servlet, 静态图片文件和静态 html 文件 *** ### 创建一个HelloWorldFilter 创建一个test.jsp 创建一个继承Filter的类 ~~~ package com.neusoft.web.fiter; 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 HelloWorldFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub System.out.println("destroy"); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("doFilter"); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub System.out.println("init"); } } ~~~ web.xml配置Filter ~~~ <filter> <filter-name>helloworldFilter</filter-name> <filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class> </filter> <filter-mapping> <filter-name>helloworldFilter</filter-name> <url-pattern>/20180125/test.jsp</url-pattern> </filter-mapping> ~~~ 运行jsp,发现init()被调用后(创建Filter对象后立即被调用,且只被调用一次),doFilter()被调用,所以init()与Servlet的init()基本功能一样,都是初始化用的,而doFilter()与Servlet当中的service()功能基本一样,而FilterConfig与ServletConfig基本一样,封装着配置信息;destory()释放当前Filter所占用的资源的方法,在Filter被销毁之前调用,且只能调用一次 而上述例子当中,发现页面中的内容并没有出现,是因为Filter将请求拦截下来了,想要对拦截进行放行,需要调用FilterChain的doFilter方法 ~~~ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("doFilter"); chain.doFilter(request, response); } ~~~ ### Filter链 ~~~ <filter> <filter-name>helloworldFilter</filter-name> <filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class> </filter> <filter-mapping> <filter-name>helloworldFilter</filter-name> <url-pattern>/20180125/test.jsp</url-pattern> </filter-mapping> <filter> <filter-name>secondFilter</filter-name> <filter-class>com.neusoft.web.fiter.SecondFilter</filter-class> </filter> <filter-mapping> <filter-name>secondFilter</filter-name> <url-pattern>/20180125/test.jsp</url-pattern> </filter-mapping> ~~~ 多个Filter在一起形成一个Filter链,而拦截的顺序与filter-mapping的前后有关 思考:多个Filter代码的顺序 ~~~ package com.neusoft.web.fiter; 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 HelloWorldFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub System.out.println("destroy"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("1.doFilter"); chain.doFilter(request, response); System.out.println("2.doFilter"); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub System.out.println("init"); } } ~~~ ~~~ package com.neusoft.web.fiter; 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 SecondFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub System.out.println("destroy2"); } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub System.out.println("3.doFilter2"); arg2.doFilter(arg0, arg1); System.out.println("4.doFilter2"); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub System.out.println("init2"); } } ~~~ ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>Test Page</h1> <% System.out.println("5.test"); %> </body> </html> ~~~ *** 课堂练习--1 ![](https://box.kancloud.cn/7ce6f7a537f33c3b95041d24b4101e95_962x656.png) *** #### dispatcher < dispatcher >指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST. 可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。在filter-mapping中配置。 **REQUEST**:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。 INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。 **FORWARD**:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。 ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。 *** ### 典型应用1--字符编码的过滤器 在每个页面上都写request.setCharacterEncoding()很麻烦,写个过滤器 one.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="two.jsp" method="post"> username:<input type="text" name="username"> <input type="submit" value="Submit"> </form> </body> </html> ~~~ two.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> Hello:${ param.username } </body> </html> ~~~ web.xml ~~~ <context-param> <param-name>encode</param-name> <param-value>UTF-8</param-value> </context-param> ~~~ EncodingFilter ~~~ package com.neusoft.web.fiter; 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.annotation.WebFilter; /** * Servlet Filter implementation class EncodingFilter */ @WebFilter("/*") public class EncodingFilter implements Filter { public void destroy() { // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String encode = fConfig.getServletContext().getInitParameter("encode"); request.setCharacterEncoding(encode); chain.doFilter(request, response); } private FilterConfig fConfig; public void init(FilterConfig fConfig) throws ServletException { this.fConfig = fConfig; } } ~~~ *** ### 典型应用2--检测用户是否登录的过滤器 list.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>List Page</h1> <a href="a.jsp">AAA</a> <br><br> <a href="b.jsp">BBB</a> <br><br> <a href="c.jsp">CCC</a> <br><br> <a href="d.jsp">DDD</a> <br><br> <a href="e.jsp">EEE</a> <br><br> </body> </html> ~~~ a.jsp,b.jsp,c.jsp,d.jsp,e.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>BBB Page</h1> <a href="list.jsp">Return...</a> </body> </html> ~~~ doLogin.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <% // 1.获取用户的登录信息 String username = request.getParameter("username"); // 2.若登录信息完整,则把登录信息放到HttpSession里 if(username != null && !username.trim().equals("")){ session.setAttribute(application.getInitParameter("userSessionKey"), username); // 3.重定向到list.jsp response.sendRedirect("list.jsp"); }else{ response.sendRedirect("login.jsp"); } %> </body> </html> ~~~ login.jsp ~~~ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="doLogin.jsp" method="post"> userName:<input type="text" name="username"> <input type="submit" value="Submit"> </form> </body> </html> ~~~ web.xml ~~~ <!-- 不要拦截的资源 --> <context-param> <param-name>noCheckPage</param-name> <param-value>/login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp</param-value> </context-param> <!-- 拦截后重定向到的页面 --> <context-param> <param-name>redirectPage</param-name> <param-value>/login/login.jsp</param-value> </context-param> <!-- 用户信息放入到session中的键名 --> <context-param> <param-name>userSessionKey</param-name> <param-value>USERSESSIONKEY</param-value> </context-param> ~~~ CheckLoginFilter ~~~ package com.neusoft.web.fiter; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet Filter implementation class CheckLoginFilter */ @WebFilter("/login/*") public class CheckLoginFilter extends HttpFilter { private String sessionKey; private String redirectUrl; private String noCheckPage; @Override public void init() { ServletContext servletContext = getFilterConfig().getServletContext(); sessionKey = servletContext.getInitParameter("userSessionKey"); redirectUrl = servletContext.getInitParameter("redirectPage"); // /login/a.jsp,/login/doLogin.jsp,/login/list.jsp,/login/login.jsp noCheckPage = servletContext.getInitParameter("noCheckPage"); } @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { // 1.获取请求的serlvetPath String servletPath = request.getServletPath(); // 2.检查获取到的是否为不需要检查中的一个,若是,则放行,return List<String> urls = Arrays.asList(noCheckPage.split(",")); if(urls.contains(servletPath)) { filterChain.doFilter(request, response); return; } // 3.检查是否有登录者,即检查sessionKey是否存在,若不存在,则重定向redirectUrl Object user = request.getSession().getAttribute(sessionKey); if(user == null) { response.sendRedirect(request.getContextPath()+redirectUrl); return; } // 4.若存在,放行,允许访问 filterChain.doFilter(request, response); } } ~~~ HttpFilter ~~~ package com.neusoft.web.fiter; 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 HttpFilter implements Filter{ @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; doFilter(request,response,filterChain); } public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(request, response); } private FilterConfig filterConfig; public FilterConfig getFilterConfig() { return filterConfig; } @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; init(); } public void init(){ } } ~~~ *** ### Filter小结 (1)简介 Filter是JavaWEB的一个重要组件,可以对发送到Servlet的请求进行拦截,并对响应也进行拦截 Filter是实现了Filter接口的Java类 Filter需要在web.xml文件中进行配置和映射(注解) (2)在web.xml中如何配置 ~~~ <filter> <filter-name>helloworldFilter</filter-name> <filter-class>com.neusoft.web.fiter.HelloWorldFilter</filter-class> </filter> <filter-mapping> <filter-name>helloworldFilter</filter-name> <url-pattern>/20180125/test.jsp</url-pattern> </filter-mapping> ~~~ 配置与Servlet的配置很相似,url-pattern映射的路径是可以拦截的资源,也就是通过哪些url能够访问到该Filter ***