为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器
粗线的理解,启动项目后进行了两次请求,访问两次过滤器。访问资源时只进行一次请求,所以访问一次过滤器。
于是为了更加清楚地看清在启动项目后进行了哪两次请求,我特意将request信息进行展示。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("request"+servletRequest);
System.out.println("filterDemo1被执行了");
//放行
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filterDemo1回来");
System.out.println("response"+servletResponse);
}
运行结果如下图所示,可以说符合假设,在启动服务器时对index.jsp资源请求了两次,并得到了两次响应。因为可以看到@后面的hash值是不一样的。
如果是在启动服务器后,通过浏览器访问,只会出现一次请求与一次响应。通过结果来看,你会看到一个请求一个响应,但是这个请求对象与响应对象和服务器最后一次请求与响应是一个对象。并且,之后再对index.jsp资源进行访问的时候,都是同一个对象。如下图所示。
于是我在想,是不是存在一种可能,就是服务器会将所有资源都会去请求一遍,类似于检测是否各个模块出现未检测出来的运行时异常呢?于是我添加了2个jsp文件,如果假设成立,那么我们会看到四组请求与响应。期待结果。如下图所示,结果表明,即使在有多个jsp资源的情况下,也不会预先地去访问其他jsp,这种假设是错误的。当然,还发现,其实浏览器用的是一个request和response对象对资源进行访问的。因此结论暂定为:服务器在启动时会对index.jsp产生两次请求及响应。
延伸但又相关
如果我们设置注解参数
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
这样就说明如果浏览器直接请求和转发的方式都可以触发filter。如果我们在index.jsp中放入转发的代码,服务器第一次启动后,发现两次请求转发的request和response相同。这个结果和我们上文提到的对于没有转发代码,只是单纯访问index.jsp的结果是不一样的。所以有转发的index.jsp服务器可能存在“在第一次进行请求index.jsp页面的时候转发后将request和response对象记录了下来”的情况。所以第二次再请求的时候一样的现象。
另外的问题是,转发和直接访问触发过滤器的方式会触发几次过滤器,实验结果是一次。(在服务器启动后访问)如下图所示。
filter链的访问次数情况
与转发、浏览器访问组合方式的情况一样,request和response只创建一次。并且请求两次,但由于是链的缘故,所以它会按照递归方式进行请求与响应,如下图。
希望有其它想法的博主进行留言!