🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 过滤器 ## 为什么要使用过滤器 把请求中需要全局处理的逻辑放在过滤器中执行,控制层专心做与自己本身相关的事情(获取参数、处理业务逻辑、传递数据、页面跳转)。 在实际的开发中,我们一般将诸如页面编码设置、登陆用户 Session 判断等放在过滤器中执行。 ![](https://box.kancloud.cn/e69696f764f5e3b0ea0427da0531f3d5_651x273.png) ## 如何使用过滤器 过滤器是一个实现了 javax.servlet.Filter 的类,在 Web 服务器启动的时候会被初始化。 - 定义过滤器类 ~~~ package cn.filters; 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; /** * Servlet Filter implementation class EncodingFilter */ public class EncodingFilter implements Filter { private String encoding = "UTF-8"; /** * Default constructor. */ public EncodingFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain) */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub // place your code here HttpServletRequest req = (HttpServletRequest) request; req.setCharacterEncoding(encoding); // pass the request along the filter chain chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { String en = fConfig.getInitParameter("Encoding"); if (null != en && !en.equals("")) { encoding = en; } } } ~~~ - 认识 web.xml web.xml 放置在 WEB-INF 目录下,是 Servlet 容器中一个非常重要的配置文件。 在 web.xml 中主要定义的几个元素包括:Filter、Servlet(Servlet现在一般使用注解的方式,将请求的地址定义在类注解中),其中,Filter 建议定义在 web.xml 做更加精细的控制。 welcome-file-list 节点是默认欢迎页面的定义 **在 web.xml 中注册过滤器** web.xml 实例代码 ~~~ <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>demo3</display-name> <welcome-file-list> <welcome-file>Login2Servlet</welcome-file> <welcome-file>LoginServlet</welcome-file> </welcome-file-list> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>cn.filters.EncodingFilter</filter-class> <init-param> <param-name>Encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter> <filter-name>SessionFilter</filter-name> <filter-class>cn.filters.SessionFilter</filter-class> <init-param> <param-name>UnCheckUrls</param-name> <param-value>/LoginServlet#/LogoutServlet#/LoginCheckServlet</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>SessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> ~~~ > 其中 `filter-mapping` 决定了过滤器执行的顺序 ## 定义复杂的过滤器 1. 映射过滤应用程序中所有资源 ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>/*</url-pattern> //访问当前主机,当前应用程序根下的所有文件包括多级子目录下的所有文件,注意这里*前有“/” </filter-mapping> ~~~ 2. 过滤指定的类型文件资源 ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>*.html</url-pattern> //访问当前主机,当前应用程序根目录下的所有html文件,注意:*.html前没有“/”,否则错误 </filter-mapping> ~~~ > 其中*.html要过滤jsp那么就改*.html为*.jsp,但是注意没有“/”斜杠。如果要同时过滤多种类型资源: **方法1 url-pattern 分开写** ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>*.jsp</url-pattern>//访问当前主机,当前应用程序根目录以所有及子目录下的所有jsp文件 </filter-mapping> ~~~ **方法2 将url-pattern合并** ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>*.html;*.jsp</url-pattern> </filter-mapping>//*.html;*.jsp两类型之间用分号;间隔 ~~~ 3. 过滤指定的目录下的所有文件 ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>/folder_name/*</url-pattern>//访问当前主机,当前应用程序根目录下的folder_name子目录(可是多级子目录)下所有文件 </filter-mapping> ~~~ 4. 过滤指定的servlet ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <servlet-name>loggerservlet</servlet-name> </filter-mapping> <servlet> <servlet-name>loggerservlet</servlet-name> <servlet-class>myfilter.LoggerServlet</servlet-class> </servlet> ~~~ 5. 过滤指定文件(即单一文件) ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>/simplefilter.html</url-pattern> </filter-mapping> ~~~ 6. 过滤指定目录下的指定类型的所有文件 > 这种情况下在web.xml中无法一次性配置完成,需要结合filter的实现类 > 首先在web.xml中配置过滤指定目录下的所有文件 ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>/dir_name/*</url-pattern> </filter-mapping> ~~~ 然后在filter的实现类中的doFilter方法中获取请求的uri或者url,判断uri或者url中是否包含指定文件类型的字符串,决定是否过滤。 ~~~ //获得用户请求的uri String uri = request.getRequestURI(); if(uri.contains(".jsp")||uri.contains(".html")) System.out.println("开始过滤"+url); ~~~ 7. 过滤指定目录下指定类型的单一文件 ~~~ <filter> <filter-name>loggerfilter</filter-name> <filter-class>myfilter.LoggerFilter</filter-class> </filter> <filter-mapping> <filter-name>loggerfilter</filter-name> <url-pattern>/dir_name/index.jsp</url-pattern> </filter-mapping> ~~~ > 以上都要注意是否有斜杠“/”