【SpringMVC问题】springmvc添加mvc:default-servlet-handler后,静态资源可以访问,controller不能访问

3 篇文章 0 订阅

文章目录

问题

springmvc添加<mvc:default-servlet-handler/>或者<mvc:resources mapping="/img/**" location="/img/"/>后,静态资源可以访问,Controller不能访问,删掉<mvc:default-servlet-handler/>后才能访问controller
具体配置文件

 <context:component-scan base-package="com.cw">
        <!-- 只加载使用@Controller标注的bean -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--
        核心控制器拦截的是所有请求,需要对静态资源请求进行放行,通过配置放行资源实现
    -->
    <!--放行指定类型静态资源配置方式-->
    <!--<mvc:resources mapping="/img/**" location="/img/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>-->

    <!--SpringMVC提供的通用资源放行方式,可以放行所有普通资源-->
    <mvc:default-servlet-handler/>

如果想要解决访问静态资源问题,通常会使用默认handler:

<mvc:default-servlet-handler/>

该标签的xsd文档说明如下:

/*配置一个handler通过转发到servlet容器的默认servlet来处理静态资源*/
Configures a handler for serving static resources by forwarding to the Servlet container's default Servlet. 

/*使用该handler允许DispatcherServlet 的url-patter 为'/',同时仍然使用servlet让其去处理静态资源*/
Use of this handler allows using a "/" mapping with the DispatcherServlet while still utilizing the Servlet container to serve static resources. 

/*该handler将会转发所有的请求到默认serlvet*/
This handler will forward all requests to the default Servlet. 

/*所以,在所有的URL HandlerMappings中,该handler对应的mapping应该留置最后!*/
Therefore it is important that it remains last in the order of all other URL HandlerMappings. 

/*你可以使用两种方式去保证你的handlermapping 的order属性值小于DefaultServletHttpRequestHandler  对应的handlermapping的order属性值:使用<mvc:annotation-driven/>标签或者手动配置HandlerMapping实例并设置其order属性值*/
That will be the case if you use the "annotation-driven" element 
or alternatively if you are setting up your customized HandlerMapping instance 

be sure to set its "order" property to a value lower 

than that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.

在这里插入图片描述

default-servlet-handler将在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler

DefaultServletHttpRequestHandler的javadoc如下:

/**
 * An {@link HttpRequestHandler} for serving static files using the Servlet container's "default" Servlet.
 *
 * <p>This handler is intended to be used with a "/*" mapping when the
 * {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
 * is mapped to "/", thus  overriding the Servlet container's default handling of static resources.
 * The mapping to this handler should generally be ordered as the last in the chain so that it will
 * only execute when no other more specific mappings (i.e., to controllers) can be matched.
 *
 * <p>Requests are handled by forwarding through the {@link RequestDispatcher} obtained via the
 * name specified through the {@link #setDefaultServletName "defaultServletName" property}.
 * In most cases, the {@code defaultServletName} does not need to be set explicitly, as the
 * handler checks at initialization time for the presence of the default Servlet of well-known
 * containers such as Tomcat, Jetty, Resin, WebLogic and WebSphere. However, when running in a
 * container where the default Servlet's name is not known, or where it has been customized
 * via server configuration, the  {@code defaultServletName} will need to be set explicitly.
 *
 * @author Jeremy Grelle
 * @author Juergen Hoeller
 * @since 3.0.4
 */

翻译如下

/*使用servlet容器的默认servlet处理静态资源*/
An {@link HttpRequestHandler} for serving static files using the Servlet container's "default" Servlet.

/*当DispatcherServlet url-pattern为"/"时,该handler将会使用"/*"去匹配请求路径;因此,重置了servlet容器对静态资源的默认处理*/
This handler is intended to be used with a "/*" mapping 
when the {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet} is mapped to "/", 
thus overriding the Servlet container's default handling of static resources.

/*匹配该handler的mapping 应该是最后到达,当没有其他mapping可以处理请求时才会执行该handler匹配的mapping。*/
The mapping to this handler should generally be ordered as the last in the chain 
so that it will only execute when no other more specific mappings (i.e., to controllers) can be matched. 

即,当DispatcherServlet url-pattern为"/“时,该handler将会使用”/*"去匹配请求路径。

参考servlet的url-pattern规则可知/*可以拦截一切请求。因为/将servlet定义为默认serlvet,在没有精确匹配servlet出现前,/*将拥有最高的优先级

这是很严重的,/*可以拦截路径和资源型的请求,并转发到默认的serlvet

也就是说,静态资源此时可以由默认default servlet进行处理,但是default servlet不能处理你的业务请求(mapping)

所以,需要保证该handler对应的handler mapping在执行顺序中为最后

解决办法

在配置文件中添加以下配置项

<mvc:annotation-driven />

annotation-driven 配置的作用如下:

  1. 主要是注册了 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter bean,存储了请求url到Controller方法的映射关系
  2. 注册了异常处理器

RequestMappingHandlerMapping:HandlerMapping的实现类,它处理的是@RequestMapping注解,并将其注册到映射表中,即url对应的Controller的方法
RequestMappingHandlerAdapter:HandlerAdapter的实现类,它是处理请求的适配器,就是确定调用哪个Controller的 哪个方法

Spring MVC 中如果配置了 <mvc:annotation-driven> ,则所有的 Controller 就会被解析,所以相应的请求就会被 Controller 处理,因此这个配置至关重要。当请求没有匹配到处理类(其中包括没有配置 <mvc:annotation-driven> 或者 访问的是静态资源文件)时,就会去找 <mvc:default-servlet-handler> (处理静态资源文件)配置的 DefaultServletHttpRequestHandler 默认处理器处理了

<mvc:annotation-driven />:使用默认的servlet来响应静态文件,建议放在开始;
<mvc:default-servlet-handler/>:放在注解处理映射器的后面,可以直接放在文件最后面

这样就不会出现<mvc:default-servlet-handler/>导致controller失效

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈小哥cw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值