Spring启动filter

编程

Filter对用户请求进行预处理,接着将请求HttpServletRequest交给Servlet进行处理并生成响应(可以修改HttpServletRequest头和数据),最后Filter再对服务器响应HttpServletResponse进行后处理(也可以修改HttpServletResponse头和数据)。

package javax.servlet;

import java.io.IOException;

public interface Filter {

default public void init(FilterConfig filterConfig) throws ServletException {}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;

default public void destroy() {}

}

doFilter函数可以过滤请求或者响应,当其过滤完请求后将调用FilterChain的doFilter函数让FilterChain中的下一个Filter来过滤请求。最先过滤请求的Filter将最后过滤响应。

生命周期

Filter的生命周期和Servlet一样,Filter的创建和销毁也是由WEB服务器负责。不过与Servlet区别的是:

  1. 在应用启动的时候就进行装载Filter类(与Servlet的load-on-startup >=0配置效果相同)。
  2. 容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。
  3. 当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。
  4. 当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。注意:init方法与destroy方法只会直接一次。

配置

<filter>

<filter-name>testFilter</filter-name>

<filter-class>com.noob.filter.testFilter</filter-class>

<!--配置FilterTest过滤器的初始化参数-->

<init-param>

<param-name>name</param-name>

<param-value>test124</param-value>

</init-param>

<init-param>

<param-name>like</param-name>

<param-value>java</param-value>

</init-param>

</filter>

<!--映射过滤器-->

<filter-mapping>

<filter-name>testFilter</filter-name>

<url-pattern>/index.jsp</url-pattern>

<dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

</filter-mapping>

可以使用FilterConfig接口对象来访问初始化参数如果过滤器不需要指定初始化参数,那么<init-param>元素可以不配置

<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
<servlet-name>指定过滤器所拦截的Servlet名称。 servlet-name对应Servlet的相关配置, 只针对于该Servlet有效
<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher> 子元素用来指定 Filter 对资源的多种调用方式进行拦截。

REQUEST:当用户直接访问页面时,Web容器将会调用过滤器
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,该过滤器将被调用
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,该过滤器将被调用
ERROR:如果目标资源是通过声明式异常处理机制调用时,该过滤器将被调用

执行源码分析

/org/apache/tomcat/embed/tomcat-embed-core/9.0.19/tomcat-embed-core-9.0.19-sources.jar

FilterChain

在org.apache.catalina.core.ApplicationDispatcher.dispatch(ServletRequest request, ServletResponse response) ->.doDispatch -> .invoke方法中:
首先: 创建FilterChain

具体过程如下:

初始化ApplicationFilterChain:

获取dispatcher:

两次遍历从StandardContext中获取到的FilterMap数组,注入匹配的Filter。
都需要matchDispatcher,而 matchFiltersURL | matchFiltersServlet 印证了 “一个Filter拦截的资源可通过:Servlet 名称和资源访问的请求路径  来指定

其次: 执行filterChain

这里含Tomcat的异步 处理逻辑。 最终也会执行到servlet.service

ApplicationFilterChain.doFilter ->.internalDoFilter(ServletRequest request, ServletResponse response):

首先执行filter.doFilter:

接着执行servlet.service:

 

 

以上是 Spring启动filter 的全部内容, 来源链接: utcz.com/z/514711.html

回到顶部