菜鸟教程 传送门
过滤器Filter::JavaWeb三大组件之一,它与Servlet很相似,过滤器是用来拦截请求的,而不是处理请求的
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
过滤器Filter生命周期
package com.Gary.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.annotation.WebFilter; @WebFilter("/*") public class GaryFilter implements Filter { public GaryFilter() { System.out.println("过滤器-构造方法"); } public void destroy() { System.out.println("过滤器-destroy()"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); System.out.println("过滤器-doFilter()"); } public void init(FilterConfig fConfig) throws ServletException { System.out.println("过滤器-init()"); } }
init(FilterConfig):在服务器启动时会创建Filter实例,并且每个类型的Filter只创建一个实例,从此不再创建!在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;
doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户每次访问“目标资源(<url->pattern>index.jsp</url-pattern>)”时执行,如果需要“放行”,那么需要调用FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不调用FilterChain的doFilter()方法,那么目标资源将无法执行;
destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。
@WebFilter("/*")表示过滤全部的请求
@WebFilter("/login.jsp")表示过滤登录的请求
每发起一个请求过滤器都会调用一次doFilter()【通常都是对请求进行过滤,对请求过滤放到chain.doFilter(request, response)上边】
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("过滤器-请求前"); chain.doFilter(request, response); System.out.println("过滤器-请求后"); }
当过滤登录请求时可先指定路径@WebFilter("/login.jsp*")后,修改doFilter()方法,用户访问login.jsp时页面重定向到index.jsp
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); //当访问login.jsp时页面请求重定向 ((HttpServletResponse)response).sendRedirect("index.jsp"); }
通过Web.xml中配置
<!-- 注册 告诉web有哪些filter并告诉其路径 --> <filter> <filter-name>xxx</filter-name> <filter-class>com.Gary.filter.GaryFilter</filter-class> </filter> <!-- filter映射 --> <filter-mapping> <filter-name>xxx</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<filter>指定一个过滤器。 <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。 <filter-class>元素用于指定过滤器的完整的限定类名。 <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。 <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径 <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字 <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式) <servlet-name>指定过滤器所拦截的Servlet名称。 <dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。 <dispatcher>子元素可以设置的值及其意义 REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。 INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。 FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。 ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
过滤器的应用场景:
执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;
【静态】当编码通过静态设置时可直接放到过滤器doFilter()中
// HttpServletRequest ServletRequest // HttpServletRequest ServletResponse public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //对编码进行过滤 类型为ServletResponse request.setCharacterEncoding("utf-8"); chain.doFilter(request, response); }
【动态】当编码通过动态设置时需放到Web.xml中
<!-- 注册 告诉web有哪些filter并告诉其路径 --> <filter> <filter-name>xxx</filter-name> <filter-class>com.Gary.filter.EncodeFilter</filter-class> <init-param> <param-name>Encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!-- filter映射 --> <filter-mapping> <filter-name>xxx</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
过滤器中init()初始化编码类型
private String encoding; public void init(FilterConfig fConfig) throws ServletException { encoding = fConfig.getInitParameter("Encoding"); }