springMVC处理静态资源分析

说明:本文是参考其他博客觉得挺好的,便参考过来供大家分享。 yq.aliyun.com/articles/38… 如果想看原文的可以访问上述连接。

springMVC处理静态资源的两个配置标签主要是:

<mvc:resources location="/WEB-INF/views/css/**" mapping="/css/**"/>
<mvc:default-servlet-handler/>
复制代码
1、对于<mvc:resources>标签的分析
复制代码

注意对于在配置文件里配置的标签都会有一个对应的BeanDefinitionParser的实现类来解析,所以对于“mvc:resources”标签的实现类是ResourceBeanDefinitionParser来解析,这个实现类里注册了一个SimpleUrlHandlerMapping,它拥有它是拥有一个Map urlMap的,它把mvc:resources标签中的mapping属性作为key,把ResourceHttpRequestHandler作为handler。即/css/**类似的url请求,会由这个SimpleUrlHandlerMapping匹配到ResourceHttpRequestHandler上。

再看下,到底调用ResourceHttpRequestHandler的哪个方法来处理请求呢?

ResourceHttpRequestHandler实现了HttpRequestHandler,所以就会调用ResourceHttpRequestHandler的void handleRequest(HttpServletRequest request, HttpServletResponse response)方法 其实很容易就明白了,ResourceHttpRequestHandler会根据mvc:resources标签中的location属性作为目录,去寻找对应的资源,然后返回资源的内容。这里就不再详细说明了,可以自行查看ResourceHttpRequestHandler的所实现的handleRequest方法。

2、对于<mvc:default-servlet-handler/>
复制代码

同理,mvc:default-servlet-handler标签对应的BeanDefinitionParser的实现类是DefaultServletHandlerBeanDefinitionParser。

这里注册了SimpleUrlHandlerMapping,它的Map urlMap中存放了一个 key为/* ,对应的handler为DefaultServletHttpRequestHandler。即请求路径匹配 / * 的时候,这个SimpleUrlHandlerMapping会交给DefaultServletHttpRequestHandler来处理。这种情况一般是其他HandlerMapping无法匹配处理,最后才无奈交给DefaultServletHttpRequestHandler。

来看下DefaultServletHttpRequestHandler是怎么处理的:

它同样实现了HttpRequestHandler接口,拥有void handleRequest(HttpServletRequest request, HttpServletResponse response)方法,如下:

@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
    if (rd == null) {
        throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
                this.defaultServletName +"'");
    }
    rd.forward(request, response);
}
复制代码

我们可以看到,这里其实就是转发给了web容器自身的servlet。这个servlet名称可以在mvc:default-servlet-handler标签中进行配置,如果没有配置,采用默认的配置,如下:

/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish */
private static final String COMMON_DEFAULT_SERVLET_NAME = "default";

/** Default Servlet name used by Google App Engine */
private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default";

/** Default Servlet name used by Resin */
private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file";

/** Default Servlet name used by WebLogic */
private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet";

/** Default Servlet name used by WebSphere */
private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet";
复制代码

即tomcat、Jetty等,在容器启动的时候,自身就默认注册了一个name叫default的servlet。DefaultServletHttpRequestHandler就是转发给这些servlet。

其实这个时候,请求先经过tomcat的servlet的url-pattern的匹配,进入到了SpringMVC,然后经过SpringMVC的HandlerMapping的一系列匹配,没有对应的handler匹配,导致又再次转发给tomcat等默认的servlet上了,绕了很大的弯,所以要尽量避免这样的操作。

3、对于当dispatcherServlet的url-pattern配置为"/"与"/*"的区别分析

结合tomcat的url-pattern来综合案例 这里举一个案例进行分析,在tomcat发布的根目录中,有一个a.html和a.jsp文件,以及一个SpringMVC项目

其中SpringMVC项目配置了mvc:default-servlet-handler标签,接下来以SpringMVC的DispatcherServlet的两种配置进行说明,分别是

/ 和 /* 两种方式 结果分别是:

DispatcherServlet配置为 / 的时候,a.html和a.jsp都可以正常访问到,如下

访问a.html 访问a.jsp

DispatcherServlet配置为 /* 的时候,a.html可以正常访问到,a.jsp就不行了,如下

访问a.html 访问a.jsp源码输出

分析如下:

我们知道 /* 的优先级大于 .jsp的优先级,.jsp的优先级大于 / (可以由我的上一篇文章了解到tomcat的url-pattern的源码分析),在这个前提下

访问a.html时:

当DispatcherServlet配置为 / 的时候,tomcat仍会选择SpringMVC的DispatcherServlet来处理a.html-》它也处理不了,交给默认配置的mvc:default-servlet-handler来处理-》转发到tomcat默认的servlet的,即DefaultServlet来处理-》DefaultServlet去寻找有没有该文件,找到了,返回文件内容 当DispatcherServlet配置为 /* 的时候,tomcat仍然是选择SpringMVC的DispatcherServlet来处理a.html,同上面是一样的过程 访问a.jsp时:

当DispatcherServlet配置为 / 的时候,tomcat会优先选择自己已经默认注册的JspServlet来处理-》JspServlet翻译文件内容,返回 当DispatcherServlet配置为 /* 的时候,tomcat会选择SpringMVC的DispatcherServlet来处理a.jsp-》发现SpringMVC找不到匹配的handler,交给配置的mvc:default-servlet-handler来处理-》转发到tomcat默认的servlet的,即DefaultServlet来处理-》DefaultServlet仅仅将a.jsp的源码内容进行返回

转载于:https://juejin.im/post/5be51473f265da611f07320e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值