springMVC02-視圖解析器、RESTful設計風格,靜態資源訪問配置

一、SpringMVC 的視圖

在 SpringMVC 中,視圖的作用渲染數據,將模型 Model (將控制器(Controller))中的數據展示給用戶。

在 Java 代碼中,視圖由接口 org.springframework.web.servlet.View 表示

SpringMVC 視圖的種類很多,默認轉發視圖InternalResourceView重定向視圖RedirectView

當工程引入 Jstl 的依賴,轉發視圖會自動轉換為 JstlView;

若使用的視圖技術為 Thymeleaf,在 SpringMVC 的配置文件中配置了 Thymeleaf 的視圖解析器,由此視圖解析器解析之后所得到的是 ThymeleafView。

1-1、視圖解析流程(基本原理)

當你在控制器中 return "success",SpringMVC 會做以下幾步:

  1. "success" 當作視圖名(ViewName)

  2. 使用 視圖解析器(ViewResolver) 解析這個視圖名

  3. 返回一個實現了 View 接口的視圖對象(如 InternalResourceView, JstlView, ThymeleafView

  4. 調用 view.render(...) 渲染模型數據(model)+ 轉發或重定向

?

1-2、SpringMVC 支持的視圖類型

類型說明關鍵類或說明
轉發視圖默認是 InternalResourceView,通過 RequestDispatcher.forward() 轉發不改變地址欄,可共享 request 域
重定向視圖RedirectView,使用 response.sendRedirect()地址欄改變,不能共享 request 域
JSTL 視圖加了 JSTL 依賴后,轉發視圖會自動變成 JstlView支持 <c:forEach> 等標簽
Thymeleaf 視圖配置了 Thymeleaf 解析器后使用 ThymeleafView支持 Thymeleaf 模板語法
其他VelocityView、FreeMarkerView 等可擴展視圖技術

?

1-3、Thymeleaf

若是視圖是由Thymeleaf解析器解析之后得到的,獲取到的視圖就是ThymeleafView,但是不是左右的情況,獲取的都是ThymeleafView。

當控制方法中返回的視圖名稱以“forword:”為前綴的時候,創建的是InternalResourceView

當控制方法中返回的視圖名稱以“redirect:”為前綴的時候,創建的是RedirectView

只有視圖名稱沒有任何前綴的時候,創建的才是ThymeleafView。

當控制器方法中所設置的視圖名稱沒有任何前綴時,此時的視圖名稱會被 SpringMVC 配置文件中所配置的視圖解析器解析,視圖名稱拼接視圖前綴視圖后綴所得到的最終路徑,會通過轉發的方式實現跳轉。

1-4、轉發視圖

1、瀏覽器發送一次請求,瀏覽器中的URL不會變!能獲取到請求域中的數據!

2、web-inf下的資源不能通過瀏覽器獲取到,但是可以通過服務器轉發獲取到!

3、不能跨域

SpringMVC 中默認的轉發視圖是 InternalResourceView

SpringMVC 中創建轉發視圖的情況:

當控制器方法中所設置的視圖名稱以 "forward:" 為前綴時,創建 InternalResourceView 視圖,此時的視圖名稱不會被 SpringMVC 配置文件中所配置的視圖解析器解析,而是會將前綴 "forward:" 去掉,剩余部分作為最終路徑通過轉發的方式實現跳轉。

例如 "forward:/", "forward:/employee"

用的比較少,因為Thymeleaf視圖解析器,默認就是轉發視圖!

1-5、重定向視圖

1、瀏覽器發送兩次請求,瀏覽器中的URL會變!不能獲取到請求域中的數據!

2、可以跨域!

SpringMVC 中默認的重定向視圖是 RedirectView。

當控制器方法中所設置的視圖名稱以 "redirect:" 為前綴時,創建 RedirectView 視圖,此時的視圖名稱不會被 SpringMVC 配置文件中所配置的視圖解析器解析,而是會將前綴 "redirect:" 去掉,剩余部分作為最終路徑通過重定向的方式實現跳轉。

例如 "redirect:/", "redirect:/employee"

1-6、視圖控制器:view-controller

沒有其他控制方法的處理,只需要通過請求映射,返回一個視圖名稱的時候。

此時控制中的所有的請求映射將全部失效!

<mvc:view-controller> 是 Spring XML 配置中的簡潔寫法,專門用于靜態頁面跳轉,適合“無業務邏輯”的場景現在依然常用,尤其在配置登錄頁、首頁等時非常實用

Spring Boot 中,不再使用 XML 配置 <mvc:view-controller>,而是使用 Java 配置(基于代碼的方式)來實現相同功能。


目標:實現“請求路徑直接跳轉到某個頁面”,不寫 Controller 方法

比如我們希望:

  • 訪問 /login → 顯示 login.html

  • 訪問 / → 顯示 index.html


1、Spring Boot Java 配置方式(推薦寫法)

你只需創建一個配置類,實現 WebMvcConfigurer 接口,重寫 addViewControllers() 方法

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyMvcConfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/login").setViewName("login");registry.addViewController("/").setViewName("index");}
}

2、視圖位置說明(默認)

Spring Boot 默認使用的是 Thymeleaf,默認的視圖位置是:

src/main/resources/templates/

所以你要在這里放:

src/main/resources/templates/login.html
src/main/resources/templates/index.html

(如果你用的是 JSP,需要特殊配置)


3、等價于 Spring XML 中的寫法:

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

總結一句話:

在 Spring Boot 中,你可以通過實現 WebMvcConfigurer 接口的 Java 配置類,用 addViewControllers() 實現和 XML 中 <mvc:view-controller> 一樣的功能 —— 頁面跳轉,無需寫 Controller,簡單又優雅。

二、RESTful設計風格

2-1、什么是 RESTful?

RESTful 是一種 Web 設計風格,不是技術,是一種“使用 URL + HTTP 方法 表達資源操作”的設計規范,常用于 Web API 接口開發。


?

2-2、RESTful 的核心特點

要素示例含義
URL 表示資源/user/1表示用戶 ID 為 1 的用戶
HTTP 方法表示動作GET、POST、PUT、DELETE分別對應:查、增、、刪

【注意】:

請求參數以/xxxx的方式拼接在URL中!?


?

2-3、傳統 VS RESTful 路徑對比

功能傳統風格 URLRESTful 風格 URL
查詢用戶/user/get?id=1GET /user/1
添加用戶/user/addPOST /user
修改用戶/user/update?id=1PUT /user/1
刪除用戶/user/delete?id=1DELETE /user/1

?

2-4、Spring MVC 實現 RESTful:案例說明

我們現在用一個簡單的 Spring MVC 項目說明 RESTful 怎么落地實現。

1. RESTful Controller 示例(路徑 + 方法)

package com.example.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;@Controller
@RequestMapping("/user")
public class UserController {// 查詢用戶(GET /user/admin)@GetMapping("/{username}")public String getUser(@PathVariable("username") String username) {System.out.println("查詢用戶:" + username);return "success";}// 添加用戶(POST /user)@PostMappingpublic String addUser(User user) {System.out.println("添加用戶: " + user);return "success";}// 修改用戶(PUT /user/wsbazinga/123)@PutMappingpublic String updateUser(@RequestParam("username") String username,@RequestParam("password") String password) {System.out.println("更新用戶: username = " + username + ", password = " + password);return "success";}// 刪除用戶(DELETE /user/wsbazinga)@DeleteMapping("/{username}")public String deleteUser(@PathVariable("username") String username) {System.out.println("刪除用戶:" + username);return "success";}
}

2-5、前端如何測試不同的 HTTP 方法?

1、post和get請求:

    <!-- get請求 --><a th:href="@{/user/admin}">查詢id = 1的用戶</a><br><!-- post請求 --><form th:action="@{/user}" method="post">username: <input type="text" name="username">password: <input type="text" name="password">role: <input type="text" name="role"><input type="submit" value="add"></form>

2、put請求?

瀏覽器默認只能發 GET 和 POST 請求。對于 PUT 和 DELETE,有幾種方法:

方法1:使用 Postman測試

curl -X PUT http://localhost:8080/user/1
curl -X DELETE http://localhost:8080/user/1

方法2:表單中使用 Spring 的隱藏字段 + 過濾器支持

示例:put請求

    <form th:action="@{/user}" method="post"><!-- 對用戶沒有意義 --><input type="hidden" name="_method" value="put" />username: <input type="text" name="username">password: <input type="text" name="password">role: <input type="text" name="role"><input type="submit" value="update"></form>

【注意】:

type="hidden":用戶頁面不可見

name = "_method" value="put"才能讓post請求變成put請求!?

并在 web.xml 中配置過濾器:

<!-- 支持RESTful方式提交PUT/DELETE -->
<filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

3、delete請求?

通過<a>超鏈接,點擊之后,調用form表單的delete方法,走filter執行。

    <div id="delete"><h2>form delete request</h2><a th:href="@{/user/wsbainga123}" @click="deleteUser">delete user</a><form id="deleteForm" method="post"><!-- 對用戶沒有意義 --><input type="hidden" name="_method" value="delete" /></form></div><!-- 引入 Vue --><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>new Vue({el: '#delete',methods:{deleteUser: function (event) {// 獲取form表單var deleteForm = document.getElementById("deleteForm");// 添加form表單的action屬性,若是沒有,默認提交到當前頁面// form表單的action屬性 = 點擊事件<a>的href的值deleteForm.action = event.target.href;// 提交表單deleteForm.submit();// 取消超鏈接的默認行為(跳轉頁面)event.preventDefault();}}});</script>

2-6、總結一句話:

RESTful 是一種使用“URL 表示資源 + HTTP 方法表示動作”的設計風格。Spring MVC 通過 @GetMapping@PostMapping@PutMapping@DeleteMapping 注解完美支持 RESTful,非常適合寫清晰簡潔的接口。


2-7、web.xml中多個過濾器

此時web.xml文件中有兩個過濾器,對順序有要求!

<!-- 處理編碼的過濾器 --><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 請求設置編碼 --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><!-- 響應設置編碼 --><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 支持RESTful方式提交PUT/DELETE --><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

一定要是處理編碼的過濾器在前!否則,中衛亂碼,因為?hiddenHttpMethodFilter 中會先獲取參數_method,導致處理編碼的過濾器失效!

springmvc項目的web.xml文件內容,基本上就是:一個servlet+兩個過濾器

三、default-servlet-handler配置

在 Spring MVC 中,default-servlet-handler 是一個非常關鍵但經常被忽略的配置,它的作用是:靜態資源(如圖片、CSS、JS 等)能夠被正常訪問


?

3-1、為什么需要 default-servlet-handler

Spring MVC 的核心思想是:把所有請求都交給前端控制器 DispatcherServlet 統一處理。

比如你在 web.xml 中通常是這樣配置的:

<servlet-mapping><servlet-name>springDispatcher</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

這意味著:所有請求(包括靜態資源)都會被 SpringMVC 接管

?? 問題:

SpringMVC 的 DispatcherServlet 默認只處理動態請求(Controller 處理的),對像 /css/style.css/js/app.js 這樣的靜態資源它是不會處理的,所以最終就 404 了。


3-2、<mvc:default-servlet-handler> 的作用

該配置的作用是:

告訴 SpringMVC:你不處理靜態資源,請把它們交回給默認的 Servlet(即 Tomcat 的 DefaultServlet)去處理

處理順序:

1、先交給dispatherServlet處理;

2、找不到,交給defaultServlet處理;

3、找不到,返回404!

示例配置:在springMVC.xml文件中配置

<mvc:default-servlet-handler />

配合使用 DispatcherServlet/ 映射時效果最好:

<servlet-mapping><servlet-name>springDispatcher</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

【注意】:

?

這兩個注解要一起使用,要是只配置了default-servlet-handler,所有的請求將交給default-servlet-handler處理!包括動態請求!


3-3、補充:Spring Boot 中怎么處理靜態資源?

Spring Boot 不需要配置 <mvc:default-servlet-handler>,它默認自動處理靜態資源,資源路徑為:

src/main/resources/static/
src/main/resources/public/
src/main/resources/resources/

3-4、WEB-INF下的靜態資源

即使你配置了 <mvc:default-servlet-handler/>,如果靜態資源(如 .html.css、圖片等)放在 WEB-INF 文件夾下,瀏覽器依然無法直接訪問!

Web 容器(如 Tomcat)會自動阻止用戶直接訪問 WEB-INF 及其子目錄的任何資源,這是 Java Web 的安全機制。?

正確放靜態資源的位置:

你應該把 HTML、CSS、JS、圖片 等資源放在這些位置:

放置路徑是否能被訪問說明
/webapp/static/? 可以訪問推薦:SpringMVC 中常用
/webapp/public/? 可以訪問Tomcat 支持的默認靜態目錄
/webapp/css//js/? 可以訪問可以自由命名
/WEB-INF/? 不能訪問SpringMVC 和瀏覽器都無法直接訪問

示例項目結構(推薦):

src
└── main└── webapp├── index.html         ? 可訪問:http://localhost:8080/項目名/index.html├── css/│   └── style.css      ? 可訪問:http://localhost:8080/項目名/css/style.css├── js/└── WEB-INF/└── views/└── page.jsp    ? 只能通過控制器轉發訪問,不能直接訪問

WEB-INF 的作用是什么?

  • 用來存放 JSP 文件(如視圖頁面)

  • 保證用戶不能通過 URL 直接訪問它們

  • 必須通過控制器轉發才能訪問,如:

3-5、總結:

在 Spring MVC 中,<mvc:default-servlet-handler /> 是用于將 靜態資源請求交還給 Web 容器(如 Tomcat)默認處理的關鍵配置,如果你使用了 / 映射 DispatcherServlet,就必須加它,否則 CSS/JS/圖片可能無法加載。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88169.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88169.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88169.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Go中使用Google Authenticator

現在為了安全Google二次驗證使用越來越平凡了&#xff0c;所以我們自己做的一些產品中&#xff0c;也會用到Google Authenticator。 介紹 Google Authenticator采用的算法是TOTP&#xff08;Time-Based One-Time Password基于時間的一次性密碼&#xff09;&#xff0c;其核心內…

ReactNative【實戰系列教程】我的小紅書 4 -- 首頁(含頂欄tab切換,橫向滾動頻道,頻道編輯彈窗,瀑布流布局列表等)

最終效果 頂欄 modules/index/components/topBar.tsx import icon_daily from "/assets/images/icon_daily.png"; import MaterialIcons from "expo/vector-icons/MaterialIcons"; import { useCallback, useState } from "react"; import { Im…

告別Root風險:四步構建安全高效的服務器管理體系

當整個開發團隊都使用root賬號操作服務器&#xff0c;且重要數據無備份時&#xff0c;系統如同行走在懸崖邊緣。本文將分享一套經過驗證的四步解決方案&#xff0c;幫助團隊快速提升主機安全性。 為什么必須告別Root賬號&#xff1f; 直接使用root賬號的風險&#xff1a; &am…

【IM項目筆記】1、WebSocket協議和服務端推送Web方案

這里寫自定義目錄標題 1、HTTP和WebSocket協議2、WebSocket3、Http VS WebSocket4、WebSocket - 建立連接5、服務端推送Web方案(1) 短輪詢(2) 長輪詢(3) WebSocket長連接1、HTTP和WebSocket協議 ?? HTTP請求的特點:通信只能由客戶端發起。所以,早期很多網站為了實現推送技…

【深度學習新浪潮】什么是上下文長度?

大型語言模型(LLM)的上下文長度是指模型在處理當前輸入時能夠有效利用的歷史文本長度,通常以token(如單詞、子詞或標點)為單位衡量。例如,GPT-4支持128K token的上下文,而Llama 4 Scout甚至達到了10M token的驚人規模。這一指標直接影響模型在長文檔理解、多輪對話等復雜…

Modbus TCP轉Profibus網關輕松讓流量計與DCS通訊

Modbus TCP轉Profibus網關輕松讓流量計與DCS通訊工業自動化系統中&#xff0c;協議差異常成為設備互聯的“語言障礙”。例如&#xff0c;當流量計采用Modbus TCP協議&#xff0c;而DCS系統僅支持Profibus DP時&#xff0c;如何實現無縫通信&#xff1f;本文將結合技術原理與真實…

云時代下的IT資產管理自動化實踐

前言伴隨著企業數字化轉型進程的加快&#xff0c;IT資產規模日益龐大且復雜。傳統的手工IT資產登記、跟蹤與管理方式&#xff0c;效率低下且容易出錯&#xff0c;已經無法滿足現代企業對于敏捷化、可視化和自動化運維的需求。云計算、容器化、微服務架構的普及又進一步加快了資…

Windows主機遠程桌面連接Ubuntu24.04主機

最近剛剛換了臺新電腦&#xff0c;想著空出老電腦直接裝一個Ubuntu系統給新電腦遠程連接過去進行開發&#xff0c;就可以完美避開雙系統老是要重啟切換的問題。仔細一查發現Ubuntu24.04自帶了RDP遠程工具&#xff0c;大喜&#xff01;于是探究了一番。 本篇文章將介紹本人探究…

Android WebView 性能優化指南

Android WebView 性能優化指南 WebView優化需要從多個維度綜合考慮&#xff1a;優化維度關鍵措施預期收益初始化延遲加載、實例復用降低內存峰值渲染硬件加速、合理布局提升流暢度20%內存獨立進程、泄漏防護減少OOM風險網絡緩存策略、資源攔截節省流量30%安全漏洞修復、接口限制…

Linux下SPHinXsys源碼編譯安裝及使用

目錄 軟件介紹 基本依賴 一、源碼下載 二、安裝依賴庫 1、BLAS 2、LAPACK 3、oneTBB 4、googletest 5、Boost 6、Simbody 7、pybind11 8、Eigen3 三、解壓縮 四、編譯安裝 軟件介紹 SPHinXsys是胡湘渝博士團隊采用C/C開發的一個開源無網格、多分辨率、多物理場、…

Linux中的靜態庫和動態庫

首先 我們要明白什么是庫? 庫&#xff08;Library&#xff09;是一組預編譯的代碼&#xff0c;提供特定的功能&#xff0c;可以被多個程序共享調用&#xff0c;避免重復編寫代碼。在鏈接步驟中&#xff0c;鏈接器將從庫文件取得所需的代碼&#xff0c;復制到生成的可執行文件中…

Vue3-組件化-Vue核心思想之一

一.組件及組件化1.組件化的作用由于之前的代碼全寫在一個App.vue這個文件里面&#xff0c;會到導致一個文件代碼過于多而且不易復用&#xff0c;所以有組件化的思想。2.組件的使用①創建創建一個.vue文件&#xff0c;使用setup的簡寫方式會自動導出.vue文件②導入import 組件對…

OS學習筆記

《幾個基本知識點》 一、2的冪 1024210 51229 25628 12827 6426 3225 1624 823 422 221 K210 G220 M230 T240 P250 E260 Z270 Y280 R290 Q2100 二、常用的ASCII碼 ‘1’0x31 ‘A’0x41 ‘a’0x61 空格0x20 換行0x0A 回車0x0D 三、存儲器層次中的典型速度 CPU/寄存器&#xff1a…

嵌入式學習筆記-MCU階段-DAY01

恭喜大家完成了C語言的學習&#xff0c;現在咱們來到咱們的硬件MCU階段&#xff0c;咱們這里的工程用的是keil&#xff0c;環境搭建不再贅述&#xff0c;希望大家在這一階段仍然學的愉快 1.資料部分 用的最多的就是STM32f103的手冊&#xff0c;搭配STM32F103ZET6的開發板 2.概…

three案例 Three.js波紋效果演示

波紋效果&#xff0c;在智慧城市可視化開發中經常用到&#xff0c;這里分享一個比較好玩的案例 以下是詳細的步驟&#xff1a; 初始化部分&#xff1a;設置 Three.js 環境&#xff0c;包括場景、相機、渲染器和控制器 幾何體和紋理&#xff1a;創建平面幾何體并加載波紋紋理 著…

Flutter-詳解布局

上一章我們詳細的學習了 Flutter 中的Widget&#xff0c;這一章我們將要學習 Flutter 的布局&#xff0c; 在上一章我們了解到了&#xff1a;Everything is a widget&#xff0c;在 Flutter 中幾乎所有的對象都是一個 Widget &#xff0c;當然也包括布局&#xff0c;Flutter 的…

EPLAN 電氣制圖:建立自己的部件庫,添加部件-加SQL Server安裝教程(三)上

在智能電氣設計領域&#xff0c;EPLAN 作為主流的設計軟件&#xff0c;其部件庫的完善程度直接影響項目設計的效率與質量。本文將從實際操作出發&#xff0c;詳細講解如何在 EPLAN 中建立專屬部件庫并添加部件&#xff0c;為電氣設計奠定堅實基礎。一、部件庫&#xff1a;電氣設…

靜態路由進階實戰全解

一、項目背景二、項目拓撲圖三、設備命名與IP地址規劃設備名接口編號IP地址規劃R1GE0/0192.168.1.1/24GE0/1172.16.1.1/24R2GE0/0192.168.1.2/24GE0/1192.168.2.2/24R3GE0/0192.168.2.3/24GE0/1192.168.3.3/24GE0/2192.168.4.3/24R4GE0/0192.168.3.4/24GE0/1192.168.4.4/24GE0/…

stm32hal模塊驅動(3)ssd1305 oled驅動

SD1305 OLED 驅動芯片詳細介紹SSD1305 是 Solomon Systech 公司生產的一款 OLED 顯示控制器/驅動器&#xff0c;專為 128x64 或 128x32 點陣的 OLED 顯示屏設計。下面我將從多個方面詳細介紹這款驅動芯片。一、SSD1305 基本特性顯示分辨率&#xff1a;最大支持 128 segments 6…

安全為先:如何在 Python 中安全處理數據庫連接與敏感信息

安全為先:如何在 Python 中安全處理數據庫連接與敏感信息 引言:Python 與安全的數據庫交互 自 1991 年誕生以來,Python 憑借其簡潔優雅的語法和強大的生態系統,成為 Web 開發、數據科學、人工智能和數據庫交互的首選語言。作為“膠水語言”,Python 不僅讓開發者能夠快速…