相信上面的这张图片友友们并不陌生吧,特别是在通过 SpringMVC 进行重定向或者请求转发的时候。
比如我们的项目中有一张图片(静态资源):
然后我们通过正确的重定向访问该资源:
@RequestMapping("/img")
public String getImg(){
return "redirect:/111.png";
}
但我们激动的启动服务器客户端发送请求,就看到了如下惨不忍睹的画面:
那么问题就来了:
带着上面的3个问题我们一起来进行分析。⬇️
首先,所谓静态资源指的是如 HTML、CSS、JS、图片等资源。这些静态资源如果想要加载到服务器,我们就需要通过一个默认的 Servlet 叫做 DefaultServlet
来将静态资源加载到服务器(tomcat)中,这样重定向的静态资源才会被找到。
我们可以打开 tomcat 安装目录下的 conf/web.xml
文件,在里面找到 DefaultServlet
:
那么我们继续在文件中往下找到 DefaultServlet
的映射信息:
可以看到其映射的 URL 为 /
,看到这里那么问题也就即将得到解决了。
我们再来看看我们配置的前端控制器 DispatcherServlet
:
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
仔细观察的你一定发现了,那就是 DefaultServlet
和 DispatcherServlet
的
都是 /
这就涉及到一个优先级问题了。到底是以谁的 /
为准呢?
答案是【就近原则】,项目中配置的
优先级高于 tomcat 实际配置文件中方的
。
那么也就意味着 DispatcherServlet
配置的 /
会覆盖掉 DefaultServlet
中的 /
。因而导致 DefaultServlet
失效,故无法加载静态资源。这时如果我们直接手动转发或者重定向到静态资源时页面就会出现 404。
其原因是访问静态资源会被当作一个请求而被 DispatcherServlet
拦截,但是找不到映射该请求对应的处理器方法,所以报错。
可是,请求静态资源本就不需要创建处理请求的方法,所以我们需要在 SpringMVC 的配置文件中添加如下配置。⬇️
解决方案:
<mvc:default-servlet-hander/>
<mvc:annotation-driven/>
配置了
标签后将会在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler
,它会对进入 DispatcherServlet
的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 Web 应用服务器默认的 DefaultServlet
处理,如果不是静态资源的请求,才由 DispatcherServlet
处理。
好了,本次问题的简单分析就到这里,希望对你有所帮助。