Spring MVC 中檢視的實現原理,在Spring MVC 中實現重定向和轉發,以及訪問靜態資源

Rainbow-Sea發表於2024-07-14

1. Spring MVC 中檢視的實現原理,在Spring MVC 中實現重定向和轉發,以及訪問靜態資源

@

目錄
  • 1. Spring MVC 中檢視的實現原理,在Spring MVC 中實現重定向和轉發,以及訪問靜態資源
    • 1.1 Spring MVC檢視支援可配置
    • 1.2 Spring MVC支援的常見檢視
    • 1.3 實現檢視機制的核心介面
    • 1.4 實現檢視機制的原理描述
    • 1.5 邏輯檢視名到物理檢視名的轉換
  • 2. Thymeleaf檢視
  • 3. JSP檢視(瞭解)
  • 4. 轉發與重定向
    • 4.1 轉發和重定向區別
  • 5. 在 Spring MVC 中 “重定向” 以及 “轉發”
    • 5.1 在 Spring MVC 中使用 forward 實現轉發
    • 5.2 在 Spring MVC 中使用 redirect 實現重定向
  • 6. mvc:view-controller 和 mvc:annotation-driven/ 的配合使用
  • 7. Spring MVC 中訪問靜態資源
    • 7.1 第一種方案:開啟預設的 Servlet處理
    • 7.2 第二種方案:使用 mvc:resources 標籤配置靜態資源
  • 8. 總結:
  • 9. 最後:


1.1 Spring MVC檢視支援可配置

在Spring MVC中,檢視 View 是支援定製的,例如我們之前在 springmvc.xml 檔案中進行了如下的配置:

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!--元件掃描-->
    <context:component-scan base-package="com.rainbowsea.springmvc.controller"></context:component-scan>

<!--    檢視解析器-->
    <!--    檢視解析器-->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
        <!--作用於檢視渲染的過程中,可以設定檢視渲染後輸出時採用的編碼字符集-->
        <property name="characterEncoding" value="UTF-8"/>
        <!--如果配置多個檢視解析器,它來決定優先使用哪個檢視解析器,它的值越小優先順序越高-->
        <property name="order" value="1"/>
        <!--當 ThymeleafViewResolver 渲染模板時,會使用該模板引擎來解析、編譯和渲染模板-->
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
                <!--用於指定 Thymeleaf 模板引擎使用的模板解析器。模板解析器負責根據模板位置、模板資源名稱、檔案編碼等資訊,載入模板並對其進行解析-->
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                        <!--設定模板檔案的位置(字首)-->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!--設定模板檔案字尾(字尾),Thymeleaf副檔名不一定是html,也可以是其他,例如txt,大部分都是html-->
                        <property name="suffix" value=".html"/>
                        <!--設定模板型別,例如:HTML,TEXT,JAVASCRIPT,CSS等-->
                        <property name="templateMode" value="HTML"/>
                        <!--用於模板檔案在讀取和解析過程中採用的編碼字符集-->
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

以上的配置表明當前 Spring MVC 框架使用的檢視 View 是 Thymelea 的。

如果你需要換成其他的檢視 View,修改以上的配置即可。這樣就可以非常輕鬆的完成檢視 View 的擴充套件。

這種設計是完成符合 OCP 開閉原則 的。檢視 View 和框架是解耦合的,耦合度低擴充套件能力強。

檢視 View 可以透過配置檔案進行靈活切換。

1.2 Spring MVC支援的常見檢視

Spring MVC支援的常見檢視包括:

  1. InternalResourceView:內部資源檢視(Spring MVC框架內建的,專門為JSP模板語法準備的)
  2. RedirectView:重定向檢視(Spring MVC框架內建的,用來完成重定向效果)
  3. ThymeleafView:Thymeleaf檢視(第三方的,為Thymeleaf模板語法準備的)
  4. FreeMarkerView:FreeMarker檢視(第三方的,為FreeMarker模板語法準備的)
  5. VelocityView:Velocity檢視(第三方的,為Velocity模板語法準備的)
  6. PDFView:PDF檢視(第三方的,專門用來生成pdf檔案檢視)
  7. ExcelView:Excel檢視(第三方的,專門用來生成excel檔案檢視)
  8. ......

1.3 實現檢視機制的核心介面

實現檢視的核心類與介面包括:

DispatcherServlet類(前端控制器):

  1. 職責:在整個Spring MVC執行流程中,負責中央排程。
  2. 核心方法:doDispatch

在這裡插入圖片描述


ViewResolver 介面(檢視解析器)

  1. 職責:負責將 邏輯檢視名 轉換為 物理檢視名 ,最終建立 View 介面的實現類,即檢視實現類物件。

  2. 核心方法:resolveViewName

在這裡插入圖片描述

View 介面(檢視):

  1. 職責:負責將模型資料 Model 渲染為檢視格式(HTML程式碼),並最終將生成的檢視(HTML程式碼)輸出到客戶端。(它負責將模板語言轉換成 HTML程式碼)
  2. 核心方法:render

在這裡插入圖片描述

ViewResolverRegistry (檢視解析器註冊器):

負責在 web 容器(Tomcat)啟動的時候,完成檢視解析器的註冊。

如果有多個檢視解析器,會將檢視解析器物件按照 order 的配置放入 List 集合。

總結:

實現檢視的核心類和介面包括:ViewResolverRegistry,DispatcherServlet,ViewResolver,View

如果你想定製自己的檢視元件:

  • 編寫類實現 ViewResolver 介面,實現 resolveViewName方法,在該方法中完成 邏輯檢視名 轉換為物理檢視名 ,並返回 View 物件。
  • 編寫類實現 View 介面,實現 render 方法,在該方法中將模板語言轉換成 HTML程式碼,並將HTML程式碼響應到瀏覽器。

如果 Spring MVC 框架中使用 Thymeleaf 作為檢視技術。那麼相關的類包括:

  • ThymeleafView
  • ThymeleafViewResolver

1.4 實現檢視機制的原理描述

假設我們Spring MVC 中使用了 Thymeleaf 作為檢視:

  1. 第一步:瀏覽器傳送請求給 web 伺服器
  2. 第二步:Spring MVC中的 DispatcherServlet 接收到請求
  3. 第三步:DispatcherServlet 根據請求路徑分發到對應的 Controller
  4. 第四步:DispatcherServlet 呼叫 Controller 的方法
  5. 第五步:Controller 的方法處理業務並返回一個 邏輯檢視名 給 DispatcherServlet
  6. 第六步:DispatcherServlet 呼叫 ThymeleafViewResovler 的 resolveViewName方法,將邏輯檢視名 轉換為 物理檢視名 ,並建立 ThymeleafView 物件返回給 DispatcherServlet
  7. 第七步:DispatcherServlet 再呼叫 ThymeleafView 的 render 方法,render 方法將模板語言轉換為 HTML程式碼,響應給瀏覽器,完成最終的渲染。

假設我們 Spring MVC 中使用了JSP作為檢視:

  1. 第一步:瀏覽器傳送請求給 web 伺服器
  2. 第二步:Spring MVC 中的DispatcherServlet 接收到請求
  3. 第三步:DispatcherServlet 根據請求路徑分發到對應的 Controller
  4. 第四步:DispatcherServlet 呼叫 Controller 的方法
  5. 第五步:Controller 的方法處理業務並返回一個 邏輯檢視名 給 DispatcherServlet
  6. 第六步:DispatcherServlet 呼叫 InternalResourceViewResovlerresolverViewName 方法,將邏輯檢視 轉換為 物理檢視名 ,並建立 InternalResourceView 物件返回給 DispathcerServlet
  7. 第七步:DispatcherServlet 再呼叫 InternalResourceView 的 render 方法,render 方法將模板語言轉換為 HTML 程式碼,響應給瀏覽器,完成最終的渲染。

1.5 邏輯檢視名到物理檢視名的轉換

邏輯檢視名最終轉換的物理檢視名是什麼,取決再 springmvc.xml 檔案中檢視解析器的配置: 假如檢視解析器配置的是 ThymeleafViewResolver,如下:

<bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
    <property name="characterEncoding" value="UTF-8"/>
    <property name="order" value="1"/>
    <property name="templateEngine">
        <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
            <property name="templateResolver">
                <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                    <property name="prefix" value="/WEB-INF/templates/"/>
                    <property name="suffix" value=".html"/>
                    <property name="templateMode" value="HTML"/>
                    <property name="characterEncoding" value="UTF-8"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

以下程式返回邏輯檢視名:index

在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  // 交給 Spring IOC 容器管理起來
public class IndexController {

    @RequestMapping("/")
    public String index() {
        return "index";


    }
}

最終邏輯檢視名 "index" 轉換為物理檢視名: /WEB-INF/templates/index.html

在這裡插入圖片描述


假如檢視解析器配置的是 InternalResourceViewResolver,如下:

在這裡插入圖片描述

<!--    jsp檢視解析器-->
    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

以下程式返回邏輯檢視名:index

package com.rainbowsea.springmvc.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  // 交給 Spring IOC 容器管理起來
public class IndexController {

    @RequestMapping("/")
    public String index() {
        return "index";


    }
}

最終邏輯檢視名 "index" 轉換為物理檢視名:/ WEB-INF/templates/index.jsp

在這裡插入圖片描述

2. Thymeleaf檢視

我們在學習前面內容的時候,採用的都是 Thymeleaf檢視。我們再來測試一下,看看底層建立的檢視物件是不是ThymeleafView
springmvc.xml 配置內容如下:

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--元件掃描-->
    <context:component-scan base-package="com.powernode.springmvc.controller"/>

    <!--檢視解析器-->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
        <property name="characterEncoding" value="UTF-8"/>
        <property name="order" value="1"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                        <property name="prefix" value="/WEB-INF/thymeleaf/"/>
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

Controller程式碼如下:

在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  // 交給 Spring IOC 容器管理起來
public class IndexController {

    @RequestMapping("/")
    public String index() {
        return "index";


    }
}

檢視頁面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>index page</title>
</head>
<body>
<h1>index page</h1>
</body>
</html>

新增斷點:在 DispatcherServlet 的 doDispatch( )方法的下圖位置新增斷點。

在這裡插入圖片描述

啟動Tomcat,在瀏覽器位址列上傳送請求:http://localhost:8080/springmvc/index

在這裡插入圖片描述

程式走到以上位置,這行程式碼是呼叫對應的Controller,並且Controller最終會返回 ModelAndView物件:mv 按照我們之前所講,返回 mv 之後,接下來就是檢視處理與渲染,接著往下走,走到下圖這一行:

在這裡插入圖片描述

這個方法的作用是處理分發結果,就是在這個方法當中進行了檢視的處理與渲染,進入該方法:

在這裡插入圖片描述

進去之後走到上圖位置:這個方法就是用來渲染頁面的方法,再進入該方法:

在這裡插入圖片描述

走到上圖位置就可以看到底層建立的是 ThymeleafView 物件。

3. JSP檢視(瞭解)

我們再來跟一下原始碼,看看 JSP 檢視底層建立的是不是 InternalResourceView物件。
我們前面說過 InternalResourceView是SpringMVC框架內建的,翻譯為內部資源檢視,SpringMVC把JSP看做是內部資源。可見JSP在之前的技術棧中有很高的地位。
不過,當下流行的開發中JSP使用較少,這裡不再詳細講解。只是測試一下。

springmvc.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--元件掃描-->
    <context:component-scan base-package="com.powernode.springmvc.controller"/>

    <!--檢視解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

Controller程式碼如下:

package com.powernode.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
    @RequestMapping("/index")
    public String toIndex(){
        return "index";
    }
}

檢視頁面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>index jsp</title>
  </head>
  <body>
    <h1>index jsp!</h1>
  </body>
</html>

啟動web容器,新增斷點跟蹤:

在這裡插入圖片描述

透過測試得知:對於JSP 檢視來說,底層建立的檢視物件是 InternalResourceView。

4. 轉發與重定向

4.1 轉發和重定向區別

  1. 轉發是一次請求,因此瀏覽器位址列上的地址不會發生變化。
  2. 重定向是兩次請求,因此瀏覽器位址列上的地址會發生變化。
  3. 轉發的程式碼實現:request.getRequestDispatcher("/index").forward(request, response);
  4. 重定向的程式碼實現:response.sendRedirect("/webapproot/index");
  5. 轉發是伺服器內部資源跳轉,由伺服器來控制。不可實現跨域訪問。
  6. 重定向可以完成內部資源的跳轉,也可以完成跨域跳轉。
  7. 轉發的方式可以訪問 WEB-INF 目錄下受保護的資源。
  8. 重定向相當於瀏覽器重新傳送了一次請求,在瀏覽器直接傳送的請求是無法訪問 WEB-INF目錄下受保護的資源的。
  9. 轉發原理:
  1. 假設傳送了 /a 請求,執行了 AServlet
  2. 在 AServlet 中透過 request.getRequestDispatcher("/b").forward(request,response); 轉發到 BServlet
  3. 從AServlet 跳轉到 BServlet 是伺服器內部來控制的。對於瀏覽器而言,瀏覽器只傳送了一個 /a 請求。
  1. 重定向原理:
  1. 假設傳送了 /a 請求,執行了 AServlet
  2. 在 AServlet 中透過 response.sendRedirect("/webapproot/b")
  3. 此時伺服器會將請求路徑 /webapproot/b 響應給瀏覽器
  4. 瀏覽器會自發的再次傳送 webapproot/b 請求來訪問 BServlet
  5. 因此對於重定向來說,傳送了兩次請求,一次是 /webapproot/a ,另一次是 webapproot/b

更多關於 Java Web 轉發和重定向的內容,大家可以移步至:✏️✏️✏️ JavaWeb 中 “轉發”與 “重定向”的區別_java 重定向與轉發-CSDN部落格

以上所描述的是使用原生Servlet API來完成轉發和重定向。在Spring MVC中是如何轉發和重定向的呢?

5. 在 Spring MVC 中 “重定向” 以及 “轉發”

5.1 在 Spring MVC 中使用 forward 實現轉發

在Spring MVC中預設就是轉發的方式,我們之前所寫的程式,都是轉發的方式。

在 Spring MVC 中是怎麼透過程式碼完成轉發的?
@RequestMapping("/a")
public String toA() {
    // 返回的是一個邏輯檢視名稱
    return "a";  // 轉發 ThymeleafView
}

注意,當 return "a"; 的時候,返回一個邏輯檢視名稱,這種方式跳轉到檢視,預設採用的就是 forward 方式跳轉過去的

只不過都是轉發到 Thymeleaf 的模板檔案xxx.html上。
那麼,在Spring MVC中如何轉發到另一個Controller上呢?可以使用Spring MVC的forward
使用格式如下:

return "forward:/b";轉發到 /b ,這是一次請求,底層建立的檢視物件是:internalResourceView物件
注意: "forward:/b" 這個已經不是邏輯檢視名稱了,是以轉發的方式跳轉,是一個資源路徑。

在這裡插入圖片描述

package com.rainbowsea.springmvc.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller // 交給 Spring IOC 容器進行管理
public class ForwardController {

    @RequestMapping("/a")
    public String toA() {
        // 返回的是一個邏輯檢視名稱
        //return "a";

        // 採用SpringMVC的轉發方式跳轉到 /b
        // 轉發的時候,格式有特殊要求,return "forward:下一個資源的路徑"
        // 這種方式就不是邏輯檢視名稱了
        return "forward:/b"; // 建立InternalResourceView物件

        // 這個使用較多,重定向,url 中會顯示資源路徑
        // return "redirect:/b";
    }


    @RequestMapping("/b")
    public String toB() {
        // 返回的是一個邏輯檢視名稱
        return "b";
    }
}

檢視頁面:

A 檢視頁面編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>page a </title>
</head>
<body>
<h1>Page A !!!</h1>

</body>
</html>

B 檢視頁面編寫:

在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>page b</title>
</head>
<body>
<h1>Page B !!!</h1>
</body>
</html>

啟動伺服器,瀏覽器位址列上輸入:http://localhost:8080/springmvc/a

在這裡插入圖片描述

透過測試,可以順利的完成轉發,轉發是一次請求,可以看到位址列上的地址沒有發生改變。

我們來跟蹤一下原始碼,看看以上程式執行過程中,建立了幾個檢視物件,分別是什麼?

在這裡插入圖片描述

透過原始碼的跟蹤得知:整個請求處理過程中,一共建立了兩個檢視物件 ?

  • InternalResourceView

  • ThymeleafView

這說明轉發底層建立的檢視物件是:InternalResourceView

思考: 既然會建立 InternalResourceView,應該會對應一個檢視解析器(InternalResourceViewResolver) ? 但是,我們在 springmvc.xml 檔案中只配置了 ThymeleafViewResolver ,並沒有配置 InternalResourceViewResolver ,這是為什麼?

這是因為 forward: 後面的不是 邏輯檢視名 ,而是一個 請求路徑 ,因此,轉發是不需要檢視解析器的。

另外,轉發使用的是 InternalResourceView ,也說明了轉發是內部資源的跳轉,(Internal 是內部的意思,Resource 是資源的意思。)

5.2 在 Spring MVC 中使用 redirect 實現重定向

redirect 是專門完成重定向效果的。和 forward 語法類似,只需要將之前的 return "forward:/b" 修改為 return "redirect:/b" 即可。

在這裡插入圖片描述

啟動伺服器,瀏覽器位址列上輸入:http://localhost:8080/springmvc/a

在這裡插入圖片描述

可見,重定向是兩次請求,位址列上的地址發生了改變。

可以看一下原始碼,在重定向的時候,Spring MVC建立哪個檢視物件?

在這裡插入圖片描述

透過斷點除錯可以看出,當重定向的時候,SpringMVC會建立一個重定向檢視物件:RedirectView。這個檢視物件也是SpringMVC框架內建的。
另外可以看出重定向之後的第二次請求建立的檢視物件就是ThymeleafView了。

注意:從springmvc應用重定向到springmvc2應用(跨域),語法是:

@RequestMapping("/a")
public String a(){
    return "redirect:http://localhost:8080/springmvc2/b";
}

可以自行測試一下!!!

總結:

轉發: return "forward:/b" 底層建立的是InternalResourceView物件
重定向: return "redirect:/b" 底層建立的是 RedirectView物件

6. mvc:view-controller 和 mvc:annotation-driven/ 的配合使用

<mcx:view-controller> 配置用於將某個請求對映到特定的檢視上,即指定某一個 URL 請求到一個檢視資源的對映,使得這個檢視資源可以被訪問。它相當於是一個獨立的處理程式,不需要編寫任何 Controller ,只需要指定 URL 和對應的檢視名稱就可以了。注意僅僅只是對應的 Controller 不需要寫,其中對應的 html,jsp 或者是其他的檢視是一定需要編寫的。

一般情況下,<mvc:view-controller> 配置可以替代一些沒有業務邏輯的 Controller,例如:首頁,錯誤頁面等。當使用者訪問配置的 URL時,框架將直接匹配到對應的檢視,而無需再經過其他控制器的處理。

<mvc:view-controller > 配置的格式如下:

<mvc:view-controller path="/如何訪問該頁面" view-name="對應的邏輯檢視名稱" />

其中:

  • path:被對映的 URL 路徑。

  • view-name:對應的邏輯檢視名稱。

例如,配置首頁的對映:

在這裡插入圖片描述

<mvc:view-controller path="/" view-name="index" />

上述配置將會匹配上訪問應用程式的根路徑,如:http://localhost:8080/springmvc。當使用者在瀏覽器中訪問該根路徑時,就會直接渲染名為 index 的檢視。

重點:

在SpringMVC中,如果在springmvc.xml檔案中配置了 <mvc:view-controller >,就需要同時在springmvc.xml檔案中新增如下配置:< mvc:annotation-driven />

<mvc:annotation-driven/>

該配置的作用是:啟用Spring MVC的註解。
如果沒有以上的配置,Controller 就無法訪問到。訪問之前的Controller會發生 404 問題。

7. Spring MVC 中訪問靜態資源

一個專案可能會包含大量的靜態資源,比如:css,js,images等。

由於我們 DispatcherServelt 的 url-pattern 的配置是 “/” 。

在這裡插入圖片描述

之前我們說過,這個“/” 代表的是除了jsp 請求之外的所有請求,也就是說訪問應用中的靜態資源,也會走 DispatcherServlet ,這會導致 404 錯誤,無法訪問靜態資源,如何解決,兩種方案:

7.1 第一種方案:開啟預設的 Servlet處理

第一種解決方案,開啟預設的 Servlet處理
    在Tomcat伺服器中提供了一個預設的Servlet,叫做: org.apache.catalina.servlets.DefaultServlet
    在CATALINA_HOME/conf/web.xml檔案中,有這個預設的 Servlet的相關配置
    不過,這個預設的Servlet預設情況下是不開啟的
    你需要在springmvc.xml檔案中使用以下配置進行開啟
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven>  開啟註解驅動
// 注意:上面這兩個配置是一起的,不可以分開來使用。
> 開啟之後的作用是:當你訪問: http://localhost:8080/springmvc/static/img/touxiang.jpeg 的時候。
> 預設先走:DispatcherServlet,如果發生 404 錯誤的話,會自動走DefaultServlet,然後 DefaultServlet 幫你定位
> 靜態資源

首先需要在 springmvc.xml 檔案中新增以下配置,開啟 預設Servlet處理靜態資源 功能:

注意:下面兩個配置是一起的,不可以分開來(就是,這兩個配置都要有才行,不可以缺少其中的任意一個) 。

在這裡插入圖片描述

<!-- 開啟註解驅動 -->
<mvc:annotation-driven />

<!--開啟預設Servlet處理-->
<mvc:default-servlet-handler>

然後在 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>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

以上配置 url-pattern 使用的也是 “/”,和 DispatcherServlet 一樣。表示的含義是:同一個請求路徑,先走 DispatcherServlet,如果找不到則走預設的Servlet。

預設的 Servlet 類中的程式碼已經由 Tomcat 伺服器提供了實現了,一般不需要開發者自己編寫。

上面的示例中,我們指定了 org.apache.catalina.servlets.DefaultServlet ,則 Tomcat 伺服器會自動將請求轉發到該類處理,再處理時,該類會根據請求的 URL 去查詢 Web 應用的靜態資源(如 HTML,CSS,JavaScript 和圖片等),並將其返回給使用者。

告訴大家一個好訊息,以上在 web.xml 檔案中的配置,我們也可以省略了,因為在 Tomcat 伺服器中已經為我們提前配置好了,在 CATALINA_HOME/conf/web.xml 檔案中,如下:

在這裡插入圖片描述

因此我們只需要在springmvc.xml檔案中啟用這個預設的Servlet即可:<mvc:default-servlet-handler>

7.2 第二種方案:使用 mvc:resources 標籤配置靜態資源

第二種解決方案:配置靜態資源處理,在springmvc.xml檔案中新增如下配置
<mvc:resources mapping="/static/**" location="/static/"></mvc:resources>
<mvc:annotaiton-driven>  //開啟註解驅動
同樣這兩個是一起配合使用的,不可以分開來
> 作用:當請求路徑符合 /static/**的時候,去 /static/位置找資源

訪問靜態資源,也可以在springmvc.xml檔案中新增如下的配置:

在這裡插入圖片描述

<!-- 開啟註解驅動 -->
<mvc:annotation-driven />

<!-- 配置靜態資源處理 -->
<mvc:resources mapping="/static/**" location="/static/" />

表示凡是請求路徑是"/static/"開始的,都會去"/static/"目錄下找該資源。
注意:要想使用 <mvc:resources> 配置,必須開啟註解驅動 <mvc:annotation-driven />

在這裡插入圖片描述

8. 總結:

  1. ViewResolver 介面,檢視解析介面(ThymeleafViewResolver 實現了 ViewResolver 介面,InternalResourceViewResolver 也是實現了
    ViewResolver介面...),這個介面作用是將邏輯檢視名稱 轉換為 物理檢視名稱,並且最終返回一個 view 介面物件,核心方法是:View resolveViewName(String viewName,Locale locale) throws Exception;
  2. View 介面,檢視介面(ThymeleafView 實現了介面,InternalResourceView 也實現了 View 介面)這個介面做什麼的?這個介面負責模板語法的字串轉換成 html程式碼,並且將html程式碼響應給瀏覽器。(渲染)核心方法是 void render(@Nullable Map<String,?> model,HttpServletRequest request, HttpServletResponse response) throws Exception;
  3. 注意:預設的
在 Spring MVC 中是怎麼透過程式碼完成轉發的?
@RequestMapping("/a")
public String toA() {
    // 返回的是一個邏輯檢視名稱
    return "a";  // 轉發 ThymeleafView
}

注意,當 return "a"; 的時候,返回一個邏輯檢視名稱,這種方式跳轉到檢視,預設採用的就是 forward 方式跳轉過去的

  1. forward 的轉發格式:return "forward:/b";轉發到 /b ,這是一次請求,底層建立的檢視物件是:internalResourceView物件。

  2. redirect 重定向格式:return "redirect:/b";轉發到 /b,這是兩次請求,底層建立的檢視物件是:RedirectView物件。注意語法:必須以 : redirect:開始

  3. thymeleaf 模板字串,這個是瀏覽器不認識的。ThymeleafView進行解析將其轉換成html響應給瀏覽器。

  4. mvc:view-controller 和 mvc:annotation-driven/ 的配合使用,不需要編寫任何 Controller ,只需要指定 URL 和對應的檢視名稱就可以了。注意僅僅只是對應的 Controller 不需要寫,其中對應的 html,jsp 或者是其他的檢視是一定需要編寫的。注意:兩個配置都要寫上,缺一不可

  5. Spring MVC 中訪問靜態資源:兩種方式:

    1. 第一種方案:開啟預設的 Servlet處理
    <!-- 開啟註解驅動 -->
    <mvc:annotation-driven />
       
    <!--開啟預設Servlet處理-->
    <mvc:default-servlet-handler>
    
    1. 第二種方案:使用 mvc:resources 標籤配置靜態資源
<!-- 開啟註解驅動 -->
<mvc:annotation-driven />

<!-- 配置靜態資源處理 -->
<mvc:resources mapping="/static/**" location="/static/" />

9. 最後:

“在這個最後的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回覆是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮鬥。感謝你們,我們總會在某個時刻再次相遇。”

在這裡插入圖片描述

相關文章