【JavaWeb】Web 中访问资源路径问题汇总

Web中 / 斜杠的不同意义

  • 浏览器内代表所有资源:/**
  • 服务器内代表所有资源:/

在Web中,/ 是绝对路径

  • / 如果被浏览器解析,得到的地址是:http://ip:port/ (指写在静态html代码中,无法被服务器解析,只能被浏览器解析)
1
<a href="/">斜杠</a>
  • / 如果被服务器解析,得到的地址是:http://ip:port/工程路径/
1
2
3
4
5
6
7
8
// 映射
<url-pattern>/servlet1<url-pattern>

// 获取绝对路径
servletContext.getRealPath("/");

// 请求转发
request.getRequestDispacther("/");
  • 特殊情况:response.sendRedirect("/");会将斜杠发送给浏览器解析,得到http://ip:port/ ,因此需要再加上工程名response.sendRedirect("/projectName/xxx");

/WEB-INF/目录下的资源文件,客户端无法直接访问(即不能在浏览器中输入url直接跳转),而只能在servlet程序中跳转

在IDEA中,"/“代表的项目文件路径为”target/项目名-1.0-SNAPSHOT/"

在Web应用的前端程序(.jsp)中:

  • 不以 / 开始的相对路径找资源时以当前资源的路径为基准,容易出现问题(不推荐使用)
  • 以 / 开始的相对路径找资源时以http://ip:port/为基准,不包含当前项目名称路径,因此需要在资源前加上${pageContext.request.contextPath}/以使程序能找到"target/项目名-1.0-SNAPSHOT/"下的资源文件(项目名-1.0-SNAPSHOT为Maven工程打包后生成的工程根目录)。例如若想在.jsp文件中引入css文件的路径,需要写 href="${pageContext.request.contextPath}/css/style.css"

image-20210604105603326

Spring MVC资源路径映射

在Spring MVC的web.xml中配置路径时,常用 /

1
2
3
4
5
6
<!-- / 匹配所有的请求;(不包括.jsp)-->
<!-- /* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

注意点

  • / 不会匹配 .jsp
  • /* 匹配所有的请求,包括 .jsp

*.jsp 由Tomcat负责处理,不需要SpringMVC拦截处理。因此常用 /

原因分析

所有JavaWeb项目里的web.xml都继承自Tomcat的父web.xml,其内配置了一个默认的DefaultServlet

1
2
3
4
5
6
7
8
9
10
11
12
<servlet>
<servlet-name>defaultServlet</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>defaultServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

DefaultServlet是Tomcat用于处理静态资源(除了jsp和servlet之外都是静态资源)的处理器,当DefaultServlet判断得知url中访问的是静态资源文件时,就会直接去服务器目录下找该资源是否存在。其配置了url-pattern:/

而Spring MVC中我们同样配置了url-pattern:/,因此会覆盖Tomcat中的DefaultServlet,使得静态资源不能被Tomcat里的DefaultServlet所处理,只能被我们配置的DispatcherServlet拦截处理。静态资源被DispatcherServlet拦截时会判断哪个方法的@RequestMapping是这个静态资源,显然并不能找到,因此无法正常显示。

*.jsp 处理问题:Tomcat里的web.xml中配置了对jsp文件的处理,该处理器将处理jsp文件:

1
2
3
4
5
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>

若我们在SpringMVC配置中只添加url-pattern:/而没有添加url-pattern:*.jsp,则将只覆盖父web.xml里的url-pattern:/(处理静态资源),并没有覆盖url-pattern:*.jsp。因此这种情况下,遇到jsp文件,则由Tomcat里的默认处理器处理;遇到普通请求,由DispatcherServlet处理;遇到静态资源,因覆盖了Tomcat,则无法处理。

若配置url-pattern:/*,则所有请求资源都将被拦截处理。

因此,若想在使用Spring MVC的DispatcherServlet的同时仍能处理静态资源,则需要添加:

1
<mvc:default-servlet-handler/>

其能将Spring MVC无法处理的请求交给Tomcat默认的Servlet处理,让Spring MVC不处理静态资源。