1. 初始SpringMVC

捞月亮的小北發表於2024-06-25

1. 學習本套教程前的知識儲備

  • JavaSE
  • HTML+CSS+JavaScript
  • Vue
  • AJAX + axios
  • Thymeleaf
  • Servlet
  • Maven
  • Spring

2. 什麼是MVC

MVC架構模式相關課程,在老杜的JavaWeb課程中已經詳細的講解了,如果沒有學過的,可以看這個影片:https://www.bilibili.com/video/BV1Z3411C7NZ

MVC是一種軟體架構模式(是一種軟體架構設計思想,不止Java開發中用到,其它語言也需要用到),它將應用分為三塊:

  • M:Model(模型)
  • V:View(檢視)
  • C:Controller(控制器)

應用為什麼要被分為三塊,優點是什麼?

  • 低耦合,擴充套件能力增強
  • 程式碼複用性增強
  • 程式碼可維護性增強
  • 高內聚,讓程式設計師更加專注業務的開發

MVC將應用分為三塊,每一塊各司其職,都有自己專注的事情要做,他們屬於分工協作,互相配合:

  • Model:負責業務處理及資料的收集。
  • View:負責資料的展示
  • Controller:負責排程。它是一個排程中心,它來決定什麼時候呼叫Model來處理業務,什麼時候呼叫View檢視來展示資料。

MVC架構模式如下所示:

img

MVC架構模式的描述:前端瀏覽器傳送請求給web伺服器,web伺服器中的Controller接收到使用者的請求,Controller負責將前端提交的資料進行封裝,然後Controller呼叫Model來處理業務,當Model處理完業務後會返回處理之後的資料給Controller,Controller再呼叫View來完成資料的展示,最終將結果響應給瀏覽器,瀏覽器進行渲染展示頁面。

面試題:什麼是三層模型,並說一說MVC架構模式與三層模型的區別?

三層模型:

MVC 和三層模型都採用了分層結構來設計應用程式,都是降低耦合度,提高擴充套件力,提高元件複用性。區別在於:他們的關注點不同,三層模型更加關注業務邏輯元件的劃分。

MVC架構模式關注的是整個應用程式的層次關係和分離思想。現代的開發方式大部分都是MVC架構模式結合三層模型一起用。

3. 什麼是SpringMVC

3.1. SpringMVC概述

SpringMVC是一個實現了MVC架構模式的Web框架,底層基於Servlet實現。

SpringMVC已經將MVC架構模式實現了,因此只要我們是基於SpringMVC框架寫程式碼,編寫的程式就是符合MVC架構模式的。(MVC的架子搭好了,我們只需要添添補補

Spring框架中有一個子專案叫做Spring Web,Spring Web子專案當中包含很多模組,例如:

  • Spring MVC
  • Spring WebFlux
  • Spring Web Services
  • Spring Web Flow
  • Spring WebSocket
  • Spring Web Services Client

可見 SpringMVC是Spring Web子專案當中的一個模組。因此也可以說SpringMVC是Spring框架的一部分。

所以學習SpringMVC框架之前要先學習Spring框架中的IoC和AOP等內容。

另外,使用SpringMVC框架的時候同樣也可以使用IoC和AOP。

以下就是Spring官方給出的Spring架構圖,其中Web中的servlet指的就是Spring MVC:

img

3.2. SpringMVC幫我們做了什麼

SpringMVC框架幫我們做了什麼,與純粹的Servlet開發有什麼區別?

  1. 入口控制:SpringMVC框架透過DispatcherServlet作為入口控制器,負責接收請求和分發請求。而在Servlet開發中,需要自己編寫Servlet程式,並在web.xml中進行配置,才能接受和處理請求。
  2. 在SpringMVC中,表單提交時可以自動將表單資料繫結到相應的JavaBean物件中,只需要在控制器方法的引數列表中宣告該JavaBean物件即可,無需手動獲取和賦值表單資料。而在純粹的Servlet開發中,這些都是需要自己手動完成的。
  3. IoC容器:SpringMVC框架透過IoC容器管理物件,只需要在配置檔案中進行相應的配置即可獲取例項物件,而在Servlet開發中需要手動建立物件例項。
  4. 統一處理請求:SpringMVC框架提供了攔截器、異常處理器等統一處理請求的機制,並且可以靈活地配置這些處理器。而在Servlet開發中,需要自行編寫過濾器、異常處理器等,增加了程式碼的複雜度和開發難度。
  5. 檢視解析:SpringMVC框架提供了多種檢視模板,如JSP、Freemarker、Velocity等,並且支援國際化、主題等特性。而在Servlet開發中需要手動處理檢視層,增加了程式碼的複雜度。

總之,與Servlet開發相比,SpringMVC框架可以幫我們節省很多時間和精力,減少程式碼的複雜度,更加專注於業務開發。同時,也提供了更多的功能和擴充套件性,可以更好地滿足企業級應用的開發需求。

3.3. SpringMVC框架的特點

  1. 輕量級:相對於其他Web框架,Spring MVC框架比較小巧輕便。(只有幾個幾百KB左右的Jar包檔案)
  2. 模組化:請求處理過程被分成多個模組,以模組化的方式進行處理。
    1. 控制器模組:Controller
    2. 業務邏輯模組:Model
    3. 檢視模組:View
  3. 依賴注入:Spring MVC框架利用Spring框架的依賴注入功能實現物件的管理,實現鬆散耦合。
  4. 易於擴充套件:提供了很多口子,允許開發者根據需要插入自己的程式碼,以擴充套件實現應用程式的特殊需求。
    1. Spring MVC框架允許開發人員透過自定義模組和元件來擴充套件和增強框架的功能。
    2. Spring MVC框架與其他Spring框架及第三方框架整合得非常緊密,這使得開發人員可以非常方便地整合其他框架,以獲得更好的功能。
  5. 易於測試:支援單元測試框架,提高程式碼質量和可維護性。 (對SpringMVC中的Controller測試時,不需要依靠Web伺服器。)
  6. 自動化配置:提供自動化配置,減少配置細節。
    1. Spring MVC框架基於約定大於配置的原則,對常用的配置約定進行自動化配置。
  7. 靈活性:Spring MVC框架支援多種檢視技術,如JSP、FreeMarker、Thymeleaf、FreeMarker等,針對不同的檢視配置不同的檢視解析器即可。

4. 本套教程相關版本

  • JDK版本:Java21
  • Maven版本:3.9.6
  • Tomcat版本:10
  • Spring版本:6.1.4
  • SpringMVC版本:6.1.4
  • IDEA版本:2023.3
  • Thymeleaf版本:3.1.2

5. 第一個SpringMVC程式

5.1. 建立Maven模組

第一步:建立Empty Project,起名:springmvc。

img

第二步:設定springmvc工程的JDK版本:Java21。

img

第三步:設定maven。

img

第四步:建立Maven模組

img

img

第五步:將pom.xml檔案中的打包方式修改為war

<groupId>com.powernode.springmvc</groupId>
<artifactId>springmvc-001</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 打包方式設定為war方式 -->
<packaging>war</packaging>

第六步:新增以下依賴

<dependencies>
    <!-- Spring MVC依賴 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>6.1.4</version>
    </dependency>
    <!--日誌框架Logback依賴-->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.5.3</version>
    </dependency>
    <!--Servlet依賴-->
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>6.0.0</version>
        <scope>provided</scope>
    </dependency>
    <!--Spring6和Thymeleaf整合依賴-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring6</artifactId>
        <version>3.1.2.RELEASE</version>
    </dependency>
</dependencies>

5.2. 新增web支援

第一步:在main目錄下建立一個webapp目錄

img

第二步:新增web.xml配置檔案

img

注意 web.xml 檔案的位置:E:\Spring MVC\code\springmvc\springmvc-001\src\main\webapp\WEB-INF\web.xml

注意版本選擇:6.0

img

新增web支援後的目錄結構:

img

5.3. 配置web.xml檔案

Spring MVC是一個web框架,在javaweb中誰來負責接收請求,處理請求,以及響應呢?當然是Servlet。在SpringMVC框架中已經為我們寫好了一個Servlet,它的名字叫做:DispatcherServlet,我們稱其為前端控制器。既然是Servlet,那麼它就需要在web.xml檔案中進行配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">

    <!--SpringMVC提供的前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- /* 表示任何一個請求都交給DispatcherServlet來處理 -->
        <!-- / 表示當請求不是xx.jsp的時候,DispatcherServlet來負責處理本次請求-->
        <!-- jsp本質就是Servlet,因此如果請求是jsp的話,應該走它自己的Servlet,而不應該走DispatcherServlet -->
        <!-- 因此我們的 url-pattern 使用 / -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

DispatcherServlet是SpringMVC框架為我們提供的最核心的類,它是整個SpringMVC框架的前端控制器,負責接收HTTP請求、將請求路由到處理程式、處理響應資訊,最終將響應返回給客戶端。DispatcherServlet是Web應用程式的主要入口點之一,它的職責包括:

  1. 接收客戶端的HTTP請求:DispatcherServlet監聽來自Web瀏覽器的HTTP請求,然後根據請求的URL將請求資料解析為Request物件。
  2. 處理請求的URL:DispatcherServlet將請求的URL(Uniform Resource Locator)與處理程式進行匹配,確定要呼叫哪個控制器(Controller)來處理此請求。
  3. 呼叫相應的控制器:DispatcherServlet將請求傳送給找到的控制器處理,控制器將執行業務邏輯,然後返回一個模型物件(Model)。
  4. 渲染檢視:DispatcherServlet將呼叫檢視引擎,將模型物件呈現為使用者可以檢視的HTML頁面。
  5. 返回響應給客戶端:DispatcherServlet將為使用者生成的響應傳送回瀏覽器,響應可以包括表單、JSON、XML、HTML以及其它型別的資料

5.4. 編寫控制器FirstController

DispatcherServlet接收到請求之後,會根據請求路徑分發到對應的Controller,Controller來負責處理請求的核心業務。在SpringMVC框架中Controller是一個普通的Java類(一個普通的POJO類,不需要繼承任何類或實現任何介面),需要注意的是:POJO類要納入IoC容器來管理,POJO類的生命週期由Spring來管理,因此要使用註解標註:

package com.powernode.springmvc.controller;

import org.springframework.stereotype.Controller;

/**
 * ClassName: FirstController
 * Description:
 * Datetime: 2024/3/13 11:56
 * Author: 老杜@動力節點
 * Version: 1.0
 */
@Controller
public class FirstController {
}

5.5. 配置springmvc-servlet.xml檔案

SpringMVC框架有它自己的配置檔案,該配置檔案的名字預設為:-servlet.xml,預設存放的位置是WEB-INF 目錄下:

<?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"/>
        <!--當 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>

在WEB-INF目錄下新建springmvc-servlet.xml檔案,並且提供以上配置資訊。

img

以上配置主要兩項:

  • 第一項:元件掃描。spring掃描這個包中的類,將這個包中的類例項化並納入IoC容器的管理。
  • 第二項:檢視解析器。檢視解析器(View Resolver)的作用主要是將Controller方法返回的邏輯檢視名稱解析成實際的檢視物件。檢視解析器將解析出的檢視物件返回給DispatcherServlet,並最終由DispatcherServlet將該檢視物件轉化為響應結果,呈現給使用者。

注意:如果採用了其它檢視,請配置對應的檢視解析器,例如:

  • JSP的檢視解析器:InternalResourceViewResolver
  • FreeMarker檢視解析器:FreeMarkerViewResolver
  • Velocity檢視解析器:VelocityViewResolver

5.6. 提供檢視

在WEB-INF目錄下新建templates目錄,在templates目錄中新建html檔案,例如:first.html,並提供以下程式碼:

<!DOCTYPE html>
<!--指定 th 名稱空間,讓 Thymeleaf 標準表示式可以被解析和執行-->
<!--th不是固定的,可以指定其它的名稱空間,只不過大部分情況下用th-->
<!--表示程式中出現的 th 開頭的後面程式碼都是 Thymeleaf語法,需要被 Thymeleaf識別-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>first springmvc</title>
</head>
<body>
<h1>我的第一個Spring MVC程式</h1>
</body>
</html>

對於每一個Thymeleaf檔案來說 xmlns:th="http://www.thymeleaf.org" 是必須要寫的,為了方便後續開發,可以將其新增到html模板檔案中:

img

5.7. 控制器FirstController處理請求返回邏輯檢視名稱

package com.powernode.springmvc.controller;

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

/**
 * ClassName: FirstController
 * Description:
 * Datetime: 2024/3/13 11:56
 * Author: 老杜@動力節點
 * Version: 1.0
 */
@Controller
public class FirstController {
    @RequestMapping(value="/haha")
    public String 名字隨意(){
        System.out.println("正在處理請求....");
        // 返回邏輯檢視名稱(決定跳轉到哪個頁面)
        return "first";
    }
}

image

5.8. 測試

第一步:配置Tomcat伺服器

img

第二步:部署web模組到Tomcat伺服器

img

第三步:啟動Tomcat伺服器。如果在控制檯輸出的資訊有中文亂碼,請修改tomcat伺服器配置檔案:apache-tomcat-10.1.19\conf\logging.properties

img

第四步:開啟瀏覽器,在瀏覽器位址列上輸入地址:http://localhost:8080/springmvc/haha

img

後端控制檯輸出:

img

5.9. 執行流程總結

  1. 瀏覽器傳送請求:http://localhost:8080/springmvc/haha
  2. SpringMVC的前端控制器DispatcherServlet接收到請求
  3. DispatcherServlet根據請求路徑 /haha 對映到 FirstController#名字隨意(),呼叫該方法
  4. FirstController#名字隨意() 處理請求
  5. FirstController#名字隨意() 返回邏輯檢視名稱 first 給檢視解析器
  6. 檢視解析器找到 /WEB-INF/templates/first.html 檔案,並進行解析,生成檢視解析物件返回給前端控制器DispatcherServlet
  7. 前端控制器DispatcherServlet響應結果到瀏覽器。

5.10. 一個Controller可以編寫多個方法

一個Controller可以提供多個方法,每個方法通常是處理對應的請求,例如:

@Controller
public class FirstController {
    @RequestMapping(value="/haha")
    public String 名字隨意(){
        System.out.println("正在處理請求....");
        // 返回邏輯檢視名稱(決定跳轉到哪個頁面)
        return "first";
    }
    
    @RequestMapping("/other")
    public String other(){
        System.out.println("正在處理其它請求...");
        return "other";
    }
}

提供 other.html 檔案

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

在 first.html 檔案中,新增超連結,用超連結傳送 /other 請求:

<!DOCTYPE html>
<!--指定 th 名稱空間,讓 Thymeleaf 標準表示式可以被解析和執行-->
<!--th不是固定的,可以指定其它的名稱空間,只不過大部分情況下用th-->
<!--表示程式中出現的 th 開頭的後面程式碼都是 Thymeleaf語法,需要被 Thymeleaf識別-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>first springmvc</title>
</head>
<body>
<h1>我的第一個Spring MVC程式</h1>
<!-- th: 表示後面的程式碼可以編寫Thymeleaf語法,可以被Thymeleaf語法解析 -->
<!-- Thymeleaf檢測到以 / 開始,表示絕對路徑,自動會將webapp的上下文路徑加上去 -->
<!-- 最終的效果是:href="/springmvc/other" -->
<a th:href="@{/other}">other請求</a>
</body>
</html>

啟動Tomcat,開啟瀏覽器,輸入請求路徑:http://localhost:8080/springmvc/haha

img

點選超連結:other請求

img

6. 第二個SpringMVC程式

6.1. 建立Maven模組

  1. pom.xml檔案中新增依賴
    1. springmvc依賴
    2. logback依賴
    3. servlet依賴(scope為provided)
    4. thymeleaf與spring6整合依賴
  2. 打包方式war

6.2. 新增web支援

img

webapp目錄沒有小藍點怎麼辦?新增web支援

img

img

6.3. 配置web.xml檔案

重點:SpringMVC配置檔案的名字和路徑是可以手動設定的,如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--手動設定springmvc配置檔案的路徑及名字-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!--為了提高使用者的第一次訪問效率,建議在web伺服器啟動時初始化前端控制器-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

透過<init-param>來設定SpringMVC配置檔案的路徑和名字。在DispatcherServlet的init方法執行時設定的。

<load-on-startup>1</load-on-startup>建議加上,這樣可以提高使用者第一次訪問的效率。表示在web伺服器啟動時初始化DispatcherServlet。

6.4. 編寫IndexController

package com.powernode.springmvc.controller;

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

/**
 * ClassName: IndexController
 * Description:
 * Datetime: 2024/3/13 15:47
 * Author: 老杜@動力節點
 * Version: 1.0
 */
@Controller
public class IndexController {
    @RequestMapping("/")
    public String toIndex(){
        return "index";
    }
}

表示請求路徑如果是:http://localhost:8080/springmvc/ ,則進入 /WEB-INF/templates/index.html 頁面。

這就是專案的首頁效果!!!!!

6.5. 在resources目錄下配置springmvc.xml檔案

img

配置內容和之前一樣,一個是檢視解析器,一個是元件掃描。

6.6. 提供檢視

img

<!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>

6.7. 測試

部署到web伺服器,啟動web伺服器,開啟瀏覽器,在位址列上輸入:http://localhost:8080/springmvc/

img

相關文章