Spring启动- filter

核能气质少年 提交于 2020-03-25 16:40:45

3 月,跳不动了?>>>

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>
	<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名称。
<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

在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:

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!