【SpringMVC笔记10】SpringMVC处理静态资源

发布于:2022-07-17 ⋅ 阅读:(145) ⋅ 点赞:(0)

这篇文章,主要介绍SpringMVC处理静态资源的几种方式。

目录

一、SpringMVC静态资源

1.1、SpringMVC处理静态资源

(1)问题引入

(2)为什么不拦截JSP文件???

1.2、几种静态资源处理方式

(1)开启默认Servlet

(2)mvc:resources

(3)不拦截【/】斜杠请求


一、SpringMVC静态资源

1.1、静态资源404问题

(1)问题引入

SpringMVC框架中,前端控制器DispatcherServlet是拦截【/】请求,这个【/】就是会拦截所有的前端请求,但是对于jsp资源例外。为什么这么说呢???为什么SpringMVC不会拦截JSP文件呢???

下面通过一个案例来看下,SpringMVC对于静态资源html和jsp文件的访问效果。

  • 创建一个工程,引入SpringMVC相关依赖,然后在【webapp】目录下面,新建两个静态资源文件:【demo.html】和【demo.jsp】。

  • 启动工程,依次访问两个资源文件,例如:http://localhost:8080/springmvc/demo.jsp、http ://localhost:8080/springmvc/demo.html。

从上面的案例可以看出,SpringMVC框架中前端控制器DispatcherServlet会拦截所有的请求,但是不会拦截JSP资源文件,至于为什么呢???

(2)为什么不拦截JSP文件???

为了验证SpringMVC框架会不会处理JSP文件,那我们可以通过源码来看下,在DispatcherServlet类里面,给【doDispatch()】方法打一个断点,然后分别访问两个静态资源文件,看两次请求是否都会被断点拦截到。

  • 首先访问html文件。

从断点可以看到,SpringMVC框架会拦截html静态资源。

  • 接着访问jsp资源。

访问JSP之后,可以发现不会经过源代码中的断点,这就可以证明,SpringMVC框架中【/】拦截的请求不包含JSP资源。

具体原因是为什么呢????

要解释这个问题,首先需要知道【/】表示的什么意思???

  • SpringMVC框架中【/】表示的是,如果当前请求没有找到处理的Servlet的话,那么这个时候就会将当前请求交给【/】斜杠对应的Servlet进行处理。
  • 但是,对于JSP来说,它本质上也是Servlet,在之前学习JSP与Servlet的时候,可以发现,Tomcat里面会有两个默认的Servlet。
  • 一个Servlet是DefaultServlet,它是用于处理那些找不到对应Servlet的请求的。
  • 另一个是JspServlet,这个是专门用于处理JSP资源文件的Servlet。
  • 从这里也可以看出来,SpringMVC框架本质上是通过DispatcherServlet替换了Tomcat里面对应的【DefaultServlet】,所以对于JSP文件来说,还是使用的Tomcat里面的JspServlet进行处理。

下面看下Tomcat里面web.xml文件中的两个Servlet。

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
	    <!-- The mapping for the default servlet -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
	
    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

    <!-- The mappings for the JSP servlet -->
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

从web.xml配置文件里面来看,JspServlet是处理【jsp】或者【jspx】为后缀的请求,而DefaultServlet是拦截的【/】,也就是处理那些找不到对应处理Servlet的请求。

这里我再解释一下,什么叫做DefaultServlet处理的是那些找不到对应处理Servlet的请求。

举个栗子:

  • 假设现在有一个AServlet,它处理的【/aServlet】的请求。
  • 有一个BServlet,它处理的【/bServlet】的请求。
  • 现在,我们打开浏览器依次访问两个请求。
  • 访问【/aServlet】,此时这个请求将会被【AServlet】进行处理;
  • 访问【/bServlet】的时候,此时这个请求将会被【/bServlet】进行处理;
  • 但是,现在如果我们访问【/cServlet】,由于我们没有编写专门用于处理【/cServlet】请求的【Servlet】,所以这个时候,Tomcat会将【/cServlet】交给【DefaultServlet】进行处理。

1.2、几种静态资源处理方式

由于SpringMVC的前端控制器DispatcherServlet只会根据请求去寻找对应的Handler,如果找不到就会抛出404,那要如何处理这种静态资源的情况呢???这里说的静态资源包括:html、js、css、img等等。

(1)开启默认Servlet

这种处理方式是在【springmvc】的配置文件里面,添加如下配置:

<!-- 开启默认servlet -->
<mvc:default-servlet-handler/>

当我们添加了这个配置之后,我们再次访问前面的demo.html文件,此时可以正常访问。

 <mvc:default-servlet-handler/>解决静态资源访问问题的原理:

当我们添加<mvc:default-servlet-handler/>这个配置之后,SpringMVC会定义一个DefaultServletHttpRequestHandler类,接着SpringMVC通过DefaultServletHttpRequestHandler类将当前请求转发到Tomcat容器里面的DefaultServlet,这个时候就相当于是Tomcat处理静态资源了,完美解决静态资源访问问题。

单纯的使用<mvc:default-servlet-handler/>配置,这个时候虽然可以解决静态资源的访问问题,但是同时,也出现了新的问题:就是SpringMVC中的所有请求都将被转发到Tomcat的DefaultServlet进行处理。

下面看下,如果我们项目里面有一个控制器Controller,有个demo方法,如下所示:

@RestController
@RequestMapping("/api")
public class IndexController {

    @RequestMapping("/demo")
    public String demo() {
        return "IndexController Api Demo.";
    }

}

通过访问上面的请求,可以发现出现404了。

如何解决404问题???

在【springmvc】的配置文件里面,添加【<mvc:annotation-driven/>】注解配置,如下所示:

<!-- 注解驱动 -->
<mvc:annotation-driven/>

也就是说,通过这种方式处理静态资源,需要同时配置两个内容,分别如下所示:

<!-- 开启默认servlet -->
<mvc:default-servlet-handler/>
<!-- 注解驱动 -->
<mvc:annotation-driven/>

再次访问静态资源和非静态资源,如下所示:

 以上,就是通过开启默认Servlet以及注解驱动,解决SpringMVC框架的静态资源问题。

(2)mvc:resources

这种方式,是通过添加【<mvc:resources>】配置来解决静态资源处理问题,【<mvc:resources>】标签的属性如下:

【<mvc:resources>】标签属性:

  • location:静态资源所在路径。
  • mapping:这是拦截的请求路径,可以采用通配符。

举个栗子:

  • 项目里面有三个静态资源目录,分别是:【pages】、【css】、【js】。
  • 现在需要访问三个目录中的静态资源,此时,就可以通过【<mvc:resources>】标签进行配置。
<!-- 第二种方式: 处理静态资源 -->
<mvc:resources location="/pages/" mapping="/pages/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>

具体工程目录结构如下所示:

启动工程,打开浏览器,依次访问三个目录下的静态资源文件。

 注意:如果出现404情况,可以看下打包之后的target目录下面,是否有静态资源的目录,没有的话重新打包一下。

但是,上面配置了三个静态资源目录,有点麻烦了,实际开发里面,都是将静态资源统一放到一个目录下面,然后只配置一个【<mvc:resources>】标签即可。实际开发中,都是将静态资源目录放在【static】目录下面。

【<mvc:resources>】标签是如何解决静态资源的问题呢???

SpringMVC框架中,如果是通过【<mvc:resources>】标签来解决的静态资源问题,那么SpringMVC框架会创建自己的静态资源处理对象,然后自己根据请求,去【<mvc:resources>】指定的目录下面进行查找资源,然后响应给客户端。

通过【<mvc:resources>】标签这种方式,可以完全不用关心Tomcat容器的DefaultServlet,也就是说和容器没有关系。

这种处理静态资源的方式,同样会存在非静态资源访问404的情况,也是需要通过【<mvc:annotation-driven>】。

(3)不拦截【/】斜杠请求

第三种处理静态资源的方式,既然SpringMVC框架出现静态资源访问问题,是因为拦截的【/】斜杠请求,那我们可以不拦截【/】,而是拦截我们自己指定的请求,例如:SpringMVC通过前端控制器DispatcherServlet只处理拦截【*.do】结尾的请求,这样当我们访问静态资源的时候,依然可以通过Tomcat的DefaultServlet进行处理,从而解决了静态资源问题。

<!-- 配置 DispatcherServlet 前端控制器 -->
<servlet>
    <!-- servlet 名称 -->
    <servlet-name>springMVC</servlet-name>
    <!-- servlet处理类 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 设置 SpringMVC 配置文件 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- 设置启动时候加载 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet映射路径 -->
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <!-- 拦截【*.do】请求 -->
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

以上,介绍了三种SpringMVC静态资源的处理方式,其实还有其他的几种处理方式,但是不太常用,所以这里不介绍了。

综上,这篇文章结束了,主要介绍SpringMVC处理静态资源的几种方式。

【源代码地址:https://gitee.com/zhuyoubin/ssm_code/tree/master/spring-mvc/springmvc-demo08

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到