springMVC01-特點、創建項目、@RequestMapping、獲取參數請求,三種域對象

一、簡介

SpringMVC 就是 Spring 框架中的 MVC 模塊,用于構建 Web 應用中的“控制層”。

SpringMVC 是 Spring 提供的一個基于 Servlet 的 Web MVC 框架模塊,是 Spring 整個體系中的“Web 層核心”。

SpringMVC 是 Spring 的一部分,Spring 框架的主要模塊包括:

1. Core(核心容器)
2. AOP(面向切面)
3. Data Access(JDBC、ORM)
4. Web(包括 Web、Web MVC、Web WebSocket)
5. Messaging
6. Test

1-1、SpringMVC 的職責是什么?

它實現了經典的 MVC 架構中的 控制器 Controller 和前端分發器 DispatcherServlet 功能。

MVC分工:

角色SpringMVC 中的實現
ModelService 層 + Java Bean
ViewJSP、Thymeleaf、Freemarker 等
Controller控制層,工程中的servlet,@Controller / @RestController 注解的類;功能:接受請求,響應瀏覽器
DispatcherDispatcherServlet,是 SpringMVC 的核心

JavaBean分為兩類:

一類稱為實體類Bean:專門存儲業務數據的,如 Student、User 等

一類稱為業務處理 Bean:指 Service 或 Dao 對象,專門用于處理業務邏輯和數據訪問。?

1-2、MVC的工作流程:

                ┌───────────────┐
瀏覽器請求 ---> │ DispatcherServlet │└───────────────┘│▼┌────────────────────┐│  Controller(控制器) │  <== 負責接收請求、調服務└────────────────────┘│▼┌────────────────────┐│  Service(業務邏輯) │  <== 處理邏輯,調數據庫└────────────────────┘│▼┌────────────────────┐│  DAO / Model(數據) │  <== 數據層/模型層└────────────────────┘│▼┌────────────────────┐│  View(JSP/HTML)   │  <== 渲染頁面└────────────────────┘

1-3、SpringMVC 和 SpringBoot 是什么關系?

  • SpringMVC 是“Spring體系中的 MVC 模塊”

  • SpringBoot 是“簡化 Spring 配置的一套框架”

  • SpringBoot 內部集成了 SpringMVC,所以你寫 SpringBoot Web 項目,底層其實就是用的 SpringMVC。

1-4、SpringMVC 和 Servlet 是什么關系?

SpringMVC 是基于 Servlet 的高級封裝

對比ServletSpringMVC
入口每個 Servlet 寫一個類一個 DispatcherServlet 就能接收所有請求
映射在 web.xml 或注解中配置路徑使用 @RequestMapping 等注解
請求處理自己解析參數自動綁定參數(甚至對象)
響應處理手動寫輸出自動 JSON 返回或視圖渲染
擴展性不好擴展支持攔截器、參數解析器、數據轉換器

二、SpringMVC的特點

2-1、SpringMVC 的核心特點(總結 + 示例 + 對比)


1. 基于注解,開發簡潔

使用注解(如 @Controller, @RequestMapping, @ResponseBody)快速定義控制器和請求路徑。

示例:

@Controller
public class UserController {@RequestMapping("/hello")@ResponseBodypublic String sayHello() {return "Hello SpringMVC!";}
}

對比傳統 Servlet:

傳統 ServletSpringMVC 注解風格
需配置 web.xml 映射路徑用注解快速映射 URL
手動解析參數自動參數綁定
寫出響應內容麻煩支持 @ResponseBody 返回 JSON

2. 請求參數自動綁定

SpringMVC 自動將請求參數綁定到方法參數、對象屬性,支持類型轉換。

示例:

@PostMapping("/addUser")
public String add(User user) {// 請求中 name=Tom&age=18 自動注入到 user 對象return "ok";
}

對比傳統 Servlet:

Servlet 中這樣寫
String name = request.getParameter("name");
手動封裝 User 實例

3. 強大的 RESTful 支持

SpringMVC 原生支持 REST 風格請求(不同方法映射到不同邏輯)。

示例:

@GetMapping("/user/{id}")
public User getUser(@PathVariable int id) { ... }@DeleteMapping("/user/{id}")
public String deleteUser(@PathVariable int id) { ... }

對比傳統方式:

Servlet 只能識別 URL,不能區分 GET/POST/DELETE/PATCH,需手動判斷 request.getMethod()


4. 內置視圖解析器支持多種視圖(JSP/Thymeleaf/JSON)

說明:
SpringMVC 可返回邏輯視圖名,由視圖解析器處理,或返回 JSON 數據(配合 @ResponseBody@RestController

示例:

@GetMapping("/list")
public String list(Model model) {model.addAttribute("students", studentService.getAll());return "studentList"; // JSP 或 Thymeleaf
}

或者:

@RestController
@RequestMapping("/api")
public class ApiController {@GetMapping("/info")public Map<String, Object> info() {return Map.of("status", "ok", "time", System.currentTimeMillis());}
}

5. 全局異常處理、攔截器、數據轉換器可插拔擴展

你可以很方便地實現:

  • 自定義參數校驗器(@Valid + @ControllerAdvice

  • 請求攔截器(HandlerInterceptor

  • 統一異常處理(@ExceptionHandler / @ControllerAdvice


2-2、總結對比表:SpringMVC vs Servlet vs Struts2

比較維度SpringMVCServletStruts2
架構模式MVC非 MVC,結構混亂MVC
開發方式注解驅動,自動裝配手動獲取 request/response配置繁瑣,OGNL 綁定
REST 支持? 原生支持? 不支持? 需要插件支持
參數綁定? 自動對象綁定 + 轉換器? 手動處理? OGNL,但性能較差
異常處理? 注解 + 全局統一? 需 try-catch? 自定義 filter 實現
視圖選擇多視圖支持JSPJSP / Freemarker
JSON 返回? 內置支持? 需寫輸出流? 支持 JSON 插件
社區活躍度? 非常高,主流標準? 已過時? 棄用趨勢

2-3、RESTful 接口

RESTful 接口開發 = “資源 URL” + “HTTP 方法”,在 SpringMVC 中,就是用 @GetMapping@PostMapping@PutMapping@DeleteMapping 來準確表達“我要對這個資源做什么”。

舉個比喻:

  • /users 是一群“用戶”

  • /users/1 是用戶 1

  • 然后你要“干什么”,就用 HTTP 方法說清楚

想干什么URL方法注解
所有用戶/usersGET@GetMapping
一個用戶/usersPOST@PostMapping
查詢某個用戶/users/1GET@GetMapping("/{id}")
修改某個用戶/users/1PUT@PutMapping("/{id}")
刪除某個用戶/users/1DELETE

@DeleteMapping("/{id}")

三、idea創建spring-mvc項目 (maven)

1、不使用maven-webapp模版,直接創建maven項目

2、在pom.xml中導入相關依賴

    <dependencies><!-- spring MVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.1</version></dependency><!-- 日志 --><!-- 日志門面 API --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><!-- slf4j 到 logback 的實現橋接器(含 core 和 classic)--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency><!-- servlet api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><!-- tomcat中自帶了servlet api和jsp的jar包的! --><!-- provided:已被提供,當項目打成war包,這個servlet的jar包就不會存在于當前war包中的web-inf的lib中 --><scope>provided</scope></dependency><!-- spring5和thymeleaf的整合包 --><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.0.11.RELEASE</version></dependency></dependencies>

【注意】:

????????pom.xml中添加的依賴對應的jar,在當前project打成war包后,會被自動加入到web-inf下的lib文件夾下,但是加了<scope>provided<scope>的,不會被加入到web-inf下的lib文件夾下。

3、添加webapp文件夾

4、添加web.xml文件

【注意】:

修改此處的路徑地址!

3-1、手動配置 DispatcherServlet —— SpringMVC 的核心組件(前端控制器)

DispatcherServlet 是整個 SpringMVC 的入口

配置 DispatcherServlet 的兩種方式(推薦 XML)?

1、默認配置方式

springMVC的配置文件默認位于web-inf下:

<!-- 注冊 DispatcherServlet,對瀏覽器發送的請求統一處理 --><servlet><!--這個 <servlet-name> 其實是給 DispatcherServlet 起的一個“別名”自定義它與配置文件名有關!當你不給 DispatcherServlet 指定配置文件路徑時(省略 <init-param>),Spring 會默認去加載這個路徑:/WEB-INF/<servlet-name>-servlet.xml示例:如果你寫成:<servlet-name>abc</servlet-name>默認加載:/WEB-INF/abc-servlet.xml但是可以通過 <init-param> 指定配置文件:--><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><!--給 Servlet(如 DispatcherServlet)指定它要攔截哪些 URL 請求設置 springMVC 的核心控制器所能處理的請求的請求路徑/ 所匹配的請求可以是 /login 或.html 或.js 或.css 方式的請求路徑但是 / 不能匹配.jsp 請求路徑的請求/*,匹配所有的請求路徑,包括.jsp 請求路徑的請求--><url-pattern>/</url-pattern></servlet-mapping>

但是maven項目,約定,所有的配置文件要統一放到resource文件夾下!

所以,推薦用擴展配置方式?

<url-pattern>/</url-pattern>:所有的請求都交給 DispatcherServlet 來處理(也就是 SpringMVC)

<url-pattern> 有哪些寫法??

寫法說明
/攔截所有請求(包括 .jsp 和靜態資源,注意需特殊配置)
*.do只攔截 .do 結尾的請求
/app/*攔截以 /app/ 開頭的路徑
/hello只攔截 /hello 這個路徑
*.action攔截 .action 的請求(老項目常見)

2、擴展配置方式 (推薦)

<!-- 注冊 DispatcherServlet,對瀏覽器發送的請求統一處理 --><servlet><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 加載 SpringMVC 配置文件:/resource/springMVC.xml --><init-param><param-name>contextConfigLocation</param-name><!-- classpath:默認就是當前項目下的resources文件夾下--><param-value>classpath:springMVC.xml</param-value></init-param><!--指定當前 Servlet 是否在服務器啟動時立即加載(初始化),以及加載的優先級。--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping>

<load-on-startup> 是干什么用的?

指定當前 DispatcherServlet 是否在服務器啟動時立即加載(初始化),以及加載的優先級。?

含義
大于等于 0啟動Tomcat時立即創建 Servlet 實例,值越小優先級越高(先加載)
小于 0 或不寫服務器啟動時不會加載這個 Servlet,第一次請求它時才創建實例(要創建的內容很懂的時候,會影響性能!)
若是:第一次請求時才會加載 DispatcherServlet(延遲初始化),可能出現“首次訪問慢”或配置未生效問題

創建springMVC.xml配置文件?

3-2、創建SpringMVC 中的“控制器”:Controller 類

@Controller 注解的類,就是 SpringMVC 中用于接收請求、處理業務邏輯、返回視圖或數據的控制器。

示例:

@Controller
public class HelloController {// "/" -->/WEB-INF/views/index.html@RequestMapping("/")public String index(){return "index";}}

3-3、配置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"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 開啟注解驅動 --><mvc:annotation-driven/><!-- 掃描 Controller 包 --><context:component-scan base-package="com.wsbazinga.controller"/><!-- 視圖解析器 --><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><!-- 可以有多個視圖解析器,用order屬性配置優先級 --><property name="order" value="1"/><property name="characterEncoding" value="UTF-8"/><property name="templateEngine"><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><!-- 視圖前綴 --><property name="prefix" value="/WEB-INF/views/"/><!-- 視圖后綴 --><property name="suffix" value=".html"/><property name="characterEncoding" value="UTF-8"/><property name="templateMode" value="HTML"/></bean></property></bean></property></bean></beans>

1、<mvc:annotation-driven/>說明:?

?啟用 SpringMVC 對注解(如 @RequestMapping@ResponseBody@RequestParam 等)的支持功能,也就是告訴 Spring:“我要用注解方式來開發控制器”。

它自動注冊以下組件:

組件名作用
RequestMappingHandlerMapping處理 URL 和方法的映射關系
RequestMappingHandlerAdapter調用控制器方法并處理參數和返回值
HttpMessageConverter負責 JSON ? Java 對象 的轉換(如使用 Jackson)
Validator表單參數校驗支持(如 @Valid

3-4、配置tomcat啟動項目?

?

此時,直接啟動tomcat,會通過域名:http://localhost:8080/WsSpringMvc/,直接訪問web-inf/views/index.html文件!

3-5、跳轉到制定頁面

inde.html

<body><h1>首頁</h1><!-- 以/開頭的路徑:絕對路徑(瀏覽器解析、服務器解析) --><!-- thymeleaf語法檢測到是絕對路徑,自動添加上下文路徑,不怕部署路徑變化。 --><a th:href="@{/target}">訪問目標頁面target.html</a></body>
HelloController.java
    @RequestMapping("/target")public String toTarget(){return "target";}

再添加target.html即可。

四、@RequestMapping注解講解

@RequestMapping 是用來 映射瀏覽器請求 URL 后端控制器Controller類?的注解,是 SpringMVC 中的“路由”。


4-1、基本用法

@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/hello")public String hello() {return "hello";}
}

當用戶訪問:http://localhost:8080/項目名/hello
就會調用這個方法,然后返回 "hello",通過視圖解析器跳轉到頁面。

【注意】:

1、@RequestMapping注解可以放在上,也可以放在方法上!?

2、確保@RequestMapping映射的URL在當前的project中是唯一的


4-2、常用屬性詳解:

屬性名作用
valuepath請求的 URL 路徑(必寫),類型是String[]數組
method限定請求方式(GET、POST 等),類型是:RequestMethod[]數組,若是不設置method屬性,任何的請求方式都能匹配!
params請求必須包含某些參數時才執行,類型:String[] 數組,多個params必須同時滿足
headers請求頭匹配時才執行
produces指定響應的內容類型(如 application/json
consumes指定請求的數據類型(如 application/json

1. 指定 GET 請求

@RequestMapping(value = "/user", method = RequestMethod.GET)
public String getUser() {return "user";
}

訪問 /user 且必須是 GET 請求,否則報錯。


2. 指定多個方法

@RequestMapping(value = "/user", method = {RequestMethod.GET, RequestMethod.POST})

支持 GET 和 POST。


3. 限定參數存在

@RequestMapping(value = "/search", params = "keyword")

只有請求中帶有 keyword 參數才會匹配這個方法。

示例:

    <form th:action="@{/testParams(password=1234)}" method="get"><input type="submit" value="測試requestmapping注解的params參數"></form>
    @RequestMapping(value = "/testParams",params = {"!username", "password!=123456"})public String testParams(){return "success";}

4. 映射類和方法組合路徑(推薦做法)

@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/add")public String addUser() {return "add";}@RequestMapping("/delete")public String deleteUser() {return "delete";}
}

最終路徑就是 /user/add/user/delete

5、請求頭屬性

6、SpringMVC支持ant風格的路徑?

Ant 風格路徑是 SpringMVC 中的一種通配符路徑匹配規則,主要用于 @RequestMappingvalue 屬性中,用來更靈活地匹配 URL。

通配符含義示例
?匹配任意的 單個字符/user? → 匹配 /user1/users(長度固定)
*匹配任意數量的 字符0 個或多個/user* → 匹配 /user/user123/user_abc
**匹配任意數量的 目錄層級/a/**/b → 匹配 /a/b/a/x/b/a/x/y/z/b

【注意】:SpringMVC 中,** 只能用于 /xx/**/yy 的結構中不能直接寫成 /** 放在中間或結尾。

?? 正確用法:

@RequestMapping("/admin/**/page")

? 錯誤用法:

@RequestMapping("/admin**page") // 無效
@RequestMapping("**/page")      // 報錯

?

4-3、和 @GetMapping / @PostMapping 的關系?

注解等價寫法
@GetMapping("/xxx")@RequestMapping(value="/xxx", method=RequestMethod.GET)
@PostMapping("/xxx")@RequestMapping(value="/xxx", method=RequestMethod.POST)
@DeleteMapping用于 DELETE 請求
@PutMapping用于 PUT 請求

所以在 RESTful 風格中,推薦使用 @GetMapping@PostMapping 等簡化注解。

@RequestMapping的派生注解

【注意】:

????????瀏覽器只能處理get和post請求,即使form表單有method屬性,可以指定請求方式,也只有get和post兩種!(put和delete請求怎么處理,見后面的內容)


?

4-4、springmvc支持路徑中的占位符

這是 RESTful 風格中非常核心的一項功能。

SpringMVC 支持通過 {} 的形式在請求路徑中定義占位符,然后通過 @PathVariable 注解將 URL 中的路徑變量綁定到方法參數上。

舉個例子說明:

@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/detail/{id}")public String getUserById(@PathVariable("id") String id) {System.out.println("查詢用戶 ID: " + id);return "user_detail";}
}

如果你訪問:

http://localhost:8080/user/detail/123

就會打印:

查詢用戶 ID: 123

1、語法說明:

用法說明
/user/{id}{id} 是路徑中的占位符
@PathVariable("id"){id} 的值綁定到參數上

2、常見變種:

(1)多個路徑變量
@RequestMapping("/user/{userId}/order/{orderId}")
public String getOrder(@PathVariable("userId") String uid,@PathVariable("orderId") String oid) {// ...
}

訪問:

/user/10/order/555

就會自動綁定:

  • uid = "10"

  • oid = "555"


?

(2)占位符名和參數名一致時,@PathVariable 可以省略參數名
@RequestMapping("/user/{id}")
public String getUserById(@PathVariable String id) {// OK,變量名和參數名一致
}

?

(3)占位符 + 通配符
@RequestMapping("/file/{path}/**")
public String getFile(@PathVariable String path) {// 捕捉一部分路徑,同時保留通配符
}

匹配/file/xxx/... 開頭所有路徑,xxx 這一段會被當作路徑變量 path** 表示后面還有任意多層路徑。?


?

(4)動態 RESTful 風格操作

你可以用路徑來表示操作行為,例如:

// 刪除用戶
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public void deleteUser(@PathVariable int id) {// DELETE 操作
}

配合前端的 RESTful 請求或 Postman 測試非常方便。


?

3、與 @RequestParam 的區別

對比項@PathVariable@RequestParam
來源URL 的路徑部分URL 的查詢參數部分
示例/user/123/user?id=123
用法@PathVariable("id")@RequestParam("id")

五、SpringMVC獲取請求參數

5-1、servletapi獲取請求參數(不推薦)

原生的獲取方法,從HttpServletRequest中獲取請求參數

請求參數通常來自:

  1. URL 查詢參數:例如 /login?username=Tom&password=123

  2. 表單提交(POST):例如 <form> 提交的數據

  3. 請求體(body):JSON、XML 等格式的原始數據

1、最常用的方式:getParameter()

示例:

    <form th:action="@{/testParams/testRequestParams}" method="post">username: <input type="text" name="username"><br>password: <input type="text" name="password"><input type="submit" value="測試testRequestParams"></form>
    @PostMapping("/testRequestParams")public String testRequestParams(HttpServletRequest request){String username = request.getParameter("username");String password = request.getParameter("password");System.out.println("username = " + username + "; password = " + password);return "success";}
  • 無論是 GET 還是 POST 請求都可以使用

  • 只能獲取 key=value 結構的表單數據或 URL 參數

  • 不能處理 JSON 請求體數據!!!

?【注意】:

1、HttpServletRequest中的值是DispatcherServlet放入的

2、這是原生的獲取請求參數的方法,SpringMVC已經做了封裝,不再建議使用!

5-2、通過控制器獲取請求參數

直接,將Controller類中的方法里面的形參的參數名 = 請求參數的參數名

示例:

    <form th:action="@{/testParams/testControllerParams}" method="post">username: <input type="text" name="username"><br>password: <input type="text" name="password"><input type="submit" value="測試testRequestParams"></form>

【備注】:當有多個同名的請求參數的時候,比如:復選框

    <form th:action="@{/testParams/testControllerParams}" method="post">username: <input type="text" name="username"><br>password: <input type="text" name="password"><br>hobby: <input type="checkbox" name="hobby" value="a">a<input type="checkbox" name="hobby" value="b">b<input type="checkbox" name="hobby" value="c">c<br><input type="submit" value="測試testRequestParams"></form>

1、直接使用String獲取(多個值逗號分離)

2、使用String[]獲取

5-3、使用 @RequestParam —— 獲取URL參數表單參數?

@RequestParam是將請求參數和控制器方法的形參創建映射關系。

示例:

@PostMapping("/login")
public String login(@RequestParam("username") String username,@RequestParam("password") String password) {System.out.println(username + " - " + password);return "success";
}

此時可以解決表單請求的參數名和controller方法里面的形參名不一致的問題!

@RequestParam 不能用來直接獲取 JSON 格式的請求體數據

?

@RequestParam注解一共有3個屬性:

用法含義
@RequestParam("xxx")從請求中取出名為 xxx 的參數
required = false表示該參數可以為空,默認是 true
defaultValue沒傳參數,或傳參為“”時,用默認值(required無關

5-4、@RequestHeader

@RequestHeader是將請求頭信息和控制器方法的形參創建映射關系

@RequestHeader注解一共有三個屬性:value、required、defaultValue,用法同@RequestParam

示例:

@GetMapping("/header")
public String testHeader(@RequestHeader("User-Agent") String userAgent) {System.out.println("客戶端瀏覽器信息:" + userAgent);return "ok";
}

如果你想獲取所有請求頭,可以使用 HttpServletRequest @RequestHeader Map

@GetMapping("/allHeaders")
public String allHeaders(@RequestHeader Map<String, String> headers) {headers.forEach((k, v) -> System.out.println(k + ": " + v));return "ok";
}

?使用場景舉例:

場景請求頭用法
判斷瀏覽器類型User-Agent適配頁面或功能
語言國際化Accept-Language根據瀏覽器語言返回不同語言的頁面
認證AuthorizationToken 認證、JWT 登錄
CORS 請求OriginReferer用于跨域校驗或來源過濾

5-5、@CookieValue

@CookieValue是將cookie數據和控制器方法的形參創建映射關系

@CookieValue注解一共有三個屬性:value、required、defaultValue,用法同@RequestParam。

示例:

@Controller
public class CookieController {@RequestMapping("/readCookie")@ResponseBodypublic String readCookie(@CookieValue("username") String username,@CookieValue(value = "token", defaultValue = "no-token") String token) {return "用戶名:" + username + ",Token:" + token;}
}

5-6、通過pojo獲取請求參數

通過 POJO(JavaBean)對象接收請求參數

相比一個個用 @RequestParam 接收參數,使用 POJO 可以自動封裝多個參數,非常方便、清晰、結構化


1、什么是 POJO 獲取請求參數?

SpringMVC 會自動根據前端傳來的請求參數名/URL參數,將它們填充進你定義的 JavaBean(POJO)對象中。


2、使用條件

只要滿足下面兩個條件,SpringMVC 就可以自動封裝:

  1. 請求參數名(form 中的 name)/URL參數 和 JavaBean 的屬性名相同

  2. JavaBean 有 無參構造器 + setter 方法


3、示例

1. 定義 POJO 類(如 User.java)

public class User {private String username;private String password;private String role;// 必須要有 setter 和 getterpublic String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public String getRole() { return role; }public void setRole(String password) { this.role = role; }
}

2. 前端 HTML 表單

<form action="/user/login?role=admin" method="post">用戶名:<input type="text" name="username"><br>密碼:<input type="password" name="password"><br><input type="submit" value="登錄">
</form>

3. Controller 中用 POJO 接收參數

@Controller
@RequestMapping("/user")
public class UserController {@PostMapping("/login")public String login(User user) {// Spring 會自動把參數封裝到 user 對象里System.out.println("用戶名: " + user.getUsername());System.out.println("密碼: " + user.getPassword());System.out.println("角色: " + user.getRole());return "success";}
}

【注意】:省略的是:@ModelAttribute注解,SpringMVC 會默認使用,只要參數名匹配!

它的解析順序大致如下:

  1. 先從請求 URL 中找參數

  2. 再從表單字段(POST)中找參數

  3. 兩邊都有,就以表單字段為準(POST 參數優先)

  4. 找到的參數會通過 JavaBean 的 setXxx() 注入到對象里


4、支持嵌套對象封裝

你可以封裝嵌套對象,比如:

public class Student {private String name;private Address address;// getter/setter ...
}public class Address {private String city;private String street;// getter/setter ...
}

表單字段名需要使用點語法(Spring 自動識別):

<input name="name">
<input name="address.city">
<input name="address.street">

5、支持集合類型(List/Map)

如果你的類中有:

private List<String> hobbies;

你可以使用以下方式提交:

<input name="hobbies" value="唱歌">
<input name="hobbies" value="跳舞">

Spring 會自動將它封裝成 List。

6、完整示例

功能目標

  1. 嵌套封裝:學生有地址信息(Student 包含 Address

  2. List 集合封裝:學生可以選多個興趣愛好(List<String>

  3. 表單提交 → SpringMVC Controller → 自動封裝 POJO → 打印輸出


(1)、定義 POJO 類

Address.java

public class Address {private String city;private String street;// getter 和 setter 必須有public String getCity() { return city; }public void setCity(String city) { this.city = city; }public String getStreet() { return street; }public void setStreet(String street) { this.street = street; }
}

Student.java

import java.util.List;public class Student {private String name;private Address address;private List<String> hobbies;public String getName() { return name; }public void setName(String name) { this.name = name; }public Address getAddress() { return address; }public void setAddress(Address address) { this.address = address; }public List<String> getHobbies() { return hobbies; }public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }
}

(2)、HTML 表單(studentForm.jsp

<form action="/student/register" method="post">姓名:<input type="text" name="name"><br>城市:<input type="text" name="address.city"><br>街道:<input type="text" name="address.street"><br>愛好:<br><input type="checkbox" name="hobbies" value="唱歌">唱歌<br><input type="checkbox" name="hobbies" value="跳舞">跳舞<br><input type="checkbox" name="hobbies" value="籃球">籃球<br><input type="submit" value="提交">
</form>

(3)、SpringMVC Controller(StudentController.java

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;@Controller
@RequestMapping("/student")
public class StudentController {@PostMapping("/register")public String register(Student student) {// 輸出接收到的學生信息System.out.println("姓名: " + student.getName());if (student.getAddress() != null) {System.out.println("城市: " + student.getAddress().getCity());System.out.println("街道: " + student.getAddress().getStreet());}if (student.getHobbies() != null) {System.out.println("愛好: ");for (String h : student.getHobbies()) {System.out.println(" - " + h);}}return "success"; // 視圖名稱}
}

【注意】:

此時獲取到的hobby的value是亂碼的!因為是中文。

7、設置請求對象編碼

亂碼問題分為兩種:

  1. get請求的亂碼;
  2. post請求的亂碼。

?

(1)、get請求的亂碼

GET 請求的參數是放在 URL 地址欄里的,例如:http://localhost:8080/app?name=張三
這些參數在到達 Servlet 之前,Tomcat 已經解析好了,此時用的默認編碼(早期是 ISO-8859-1),你設置編碼已來不及,亂碼已經發生。

所以這是tomcat的問題,需要在tomcat的server.xml 中明確指定:

{Tomcat目錄}/conf/server.xml

加上 URIEncoding="UTF-8" 就可以防止 GET 請求中文亂碼。?

(2)、post請求亂碼
請求類型參數位置解決方式
POST請求體 body使用 request.setCharacterEncoding("UTF-8")
GETURL 地址欄設置 Tomcat 的 URIEncoding="UTF-8"

【注意點】:必須在第一次獲取參數之前設置編碼!

一旦調用了以下任意方法:

request.getParameter()
request.getParameterMap()
request.getParameterNames()
request.getParameterValues()

?Servlet 容器就會立即解析請求體,并把參數緩存起來。

如果你在調用之后再設置編碼,就無效了,編碼已經決定,不會重新解析請求體。

? 錯誤做法(設置編碼太晚)

String name = request.getParameter("name"); // 已經觸發解析
request.setCharacterEncoding("UTF-8");      // ? 已經沒用了!

? 正確做法(先設置編碼)

request.setCharacterEncoding("UTF-8");      // ? 先設置編碼
String name = request.getParameter("name"); // 然后獲取參數

但是應為此時我們用的是pojo獲取請求參數,使用request.setCharacterEncoding("UTF-8");是無效的,應為dispatcherServlet已經解析了參數了!

所以過濾器統一處理,因為,過濾器在servlet之前執行!

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

5-7、【回顧】使用 @PathVariable(獲取 REST 風格路徑參數)

@GetMapping("/user/{id}")
public String getUserById(@PathVariable("id") int id) {System.out.println("id = " + id);return "user";
}

5-8、使用 @RequestBody(接收 JSON 數據)

@PostMapping("/user")
public String createUser(@RequestBody User user) {System.out.println("user = " + user);return "success";
}
  • 會從 請求體中讀取 JSON,然后通過 Jackson 自動反序列化成 User 對象

  • 需要前端設置 Content-Type: application/json

需要前端發送 Content-Type: application/json 請求頭,示例:

<!-- requestbody.html -->
<script>function register() {const user = {username: "Alice",email: "alice@example.com",password: "123456"};fetch("/json/register", {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify(user)}).then(response => {if (response.ok) {alert("Registered successfully!");}});}
</script><button onclick="register()">Register via JSON</button>

五、SpringMVC 中的三種域對象

requestsession、和 servletContext(application),它們統稱為 “三大作用域對象”

5-1、什么是域對象?

域對象(也叫作用域對象)是 Web 中用來 不同范圍內共享數據 的容器。?

域對象生命周期范圍使用場景
request一次請求內有效請求轉發、表單處理
session一個用戶會話內有效登錄狀態、用戶信息保存
servletContext整個 Web 應用范圍內都有效(太大)全局參數、在線人數統計等

?

1、區分:什么是一“次請求”,什么是一“次會話”

(1)、?什么是一“次請求”

一次請求 = 瀏覽器或客戶端 發出的一次 HTTP 請求。它從你訪問某個 URL 的那一刻開始,到服務器響應返回結果為止。

判斷是不是“一次請求”:你可以在控制器方法中打印 request 對象的地址或哈希值:

@RequestMapping("/test")
public String test(HttpServletRequest request) {System.out.println("request hash: " + request.hashCode());return "success";
}

如果你在多個方法里都打了這個語句,只有同一個請求轉發時(比如 forward:/page),request.hashCode() 是相同的。?

【注意】:

頁面刷新或重新點擊鏈接 → 就是新的請求!!!

即使訪問的是同一個地址,但每點擊一次或刷新一次,就是一個新的 request。

特點:生命周期短

  • 請求來了就創建

  • 響應完成就銷毀

  • 不同請求之間,request 互不影響

(2)、一次會話(session)?

一次會話 = 用戶打開瀏覽器 → 訪問網站 → 關閉瀏覽器長時間不操作 → 會話結束。
瀏覽器不關、用戶不斷操作,這個會話就一直保持。

判斷是不是“一次會話”:打印 session ID

@RequestMapping("/checkSession")
public String checkSession(HttpSession session) {System.out.println("session ID: " + session.getId());return "session";
}
  • 多次訪問 /checkSession,只要瀏覽器沒關,session ID 不變,說明是同一個會話。

  • 如果你關掉瀏覽器再訪問,或等上20~30分鐘,session ID 就會變,說明是新會話。

【注意】:

域名不同就不是同一個 session!

一般,同一個項目下共享 session!!!

情景:同一瀏覽器訪問兩個項目

  • http://localhost:8080/app1

  • http://localhost:8080/app2

雖然端口和瀏覽器一樣,但項目上下文不同(app1 ≠ app2),默認是兩個不同的 session,除非你顯式配置 Cookie 的路徑。

5-2、request 域對象?

特點

  • 生命周期:一次請求內有效

  • 隨著請求的完成而銷毀(如訪問頁面、轉發等)

  • 適合存儲:表單校驗信息、錯誤提示、一次性數據傳遞

1、使用ServletAPI向request域對象共享數據?

示例:

index.html頁面:

<h2>test request scope value</h2>
<a th:href="@{/testRequestByServletApi}">set request attribute and then go to success page</a>

點擊之后發送一次請求:http://localhost:8080/WsSpringMvc/testRequestByServletApi

@Controller
public class ScopeController {@RequestMapping("/testRequestByServletApi")public String testRequestByServletApi(HttpServletRequest request){// 每一個域對象都有三種方法:// setAttribute// getAttribute// removeAttributerequest.setAttribute("testRequestScope", "hello servletAPI");return "successScope";}}

【注意】:

return "success" 是“請求轉發”forward

在 Spring MVC 中,當你的控制器方法返回一個字符串(如 "success"),默認行為是:

  • Spring 會將這個字符串當作視圖名

  • 然后交給視圖解析器(ViewResolver)來處理

  • 最終會使用請求轉發(forward)到對應的頁面

?等價于:

request.getRequestDispatcher("/WEB-INF/views/success.jsp").forward(request, response);

所以,這是一次請求轉發,而不是重定向

如果你想“重定向”,需要顯式寫上:

return "redirect:/someOtherPath";
返回值行為地址欄是否變化請求是否共享 request 域
"success"請求轉發? 不變? 可以用 ${msg} 取值
"redirect:/xx"重定向? 會變? request 域不共享(已經不是一次請求了!)

successScope.html頁面

<body><h1>success</h1><p th:text="${testRequestScope}"></p></body>

【注意】:

在 Thymeleaf 中,"${}" 表達式用于獲取變量,但不同作用域(request、session、application)中的變量訪問方式有所不同

1. Request 域(HttpServletRequest):

???????<p th:text="${key}"></p>

2. Session 域(HttpSession

<p th:text="${session.key}"></p>

3. Application 域(ServletContext

<p th:text="${application.key}"></p>

2、使用ModelAndView向request域對象共享數據(Springmvc)?

下面的2,3,4,5方式,都是Springmvc中提供的向request域對象共享數據的方法,最終原碼都是包裝成一個ModelAndView對象!

ModelAndView有model和view的功能:

  • model主要用于向請求域共享數據;
  • view用于設計視圖,實現頁面跳轉!

示例:

    @RequestMapping("/testModelAndViewApi")public ModelAndView testModelAndViewApi(){ModelAndView modelAndView = new ModelAndView();// 處理model數據:即,向請求域request共享數據modelAndView.addObject("testRequestScopeModelAndView", "hello modelAndView");// 設置視圖名稱modelAndView.setViewName("successScope");return modelAndView;}

【注意】:

返回值一定要是ModelAndView,因為要把視圖返回給視圖解析器!

3、使用Model向request域對象共享數據(Springmvc)??

?

4、使用Map集合向request域對象共享數據(Springmvc)??

map集合一般key就是string類型,value就是object類型!?

5、使用ModelMap集合向request域對象共享數據(Springmvc)???

5-3、Session域對象

使用方法:

@RequestMapping("/login")
public String login(HttpSession session) {session.setAttribute("user", "Tom");return "home";
}
  • 獲取 session:HttpSession session

  • 讀取 session 數據:session.getAttribute("user")

5-4、servletContext(application)域對象

特點:

  • 生命周期:整個 Web 應用運行期間有效

  • 所有用戶共享,全局作用域

  • 適合存儲:全局配置、網站訪問量、緩存等

application域對象,范圍太大了,用的最多的還是request和session!

使用方法:

@RequestMapping("/app")
public String applicationScope(HttpSession session) {ServletContext context = session.getServletContext();context.setAttribute("count", 100);return "global";
}

也可以直接通過 @Autowired 注入:

@Autowired
ServletContext context;

5-5、總結一句話

你想用什么作用域對象(如 request、session、application),直接寫在控制器方法參數中即可獲取,Spring MVC 會自動注入,不用你手動 new 或額外配置

示例:

@RequestMapping("/demo")
public String demo(HttpServletRequest request,HttpSession session,ServletContext context) {request.setAttribute("reqData", "數據來自 request 域");session.setAttribute("sessData", "數據來自 session 域");context.setAttribute("appData", "數據來自 application 域");return "success"; // 視圖解析到 success.html 或 JSP
}

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

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

相關文章

Java基礎,反射破壞封裝性 - 單例模式的崩塌

目錄一、容易出現問題的小李代碼小李的單例設計看似完美&#xff0c;實則存在三個致命問題&#xff1a;1、反射攻擊的天然漏洞2、序列化的隱患3、性能瓶頸二、隔壁老王的優化方案三、為什么這樣優化&#xff1f;四、小結周五下午&#xff0c;代碼審查會議上&#xff0c;小李自信…

Neo4j 綜合練習作業

Neo4j 綜合練習作業 作業說明 這個作業涵蓋了 Neo4j 的多個重要知識點&#xff0c;包括節點和關系的創建、查詢、更新、刪除以及高級查詢功能。請使用 Cypher 語句完成以下所有題目。 數據準備 首先執行以下語句創建示例數據&#xff1a; ACTED_IN: 表示出演關系 DIRECTED: 表示…

基于PA算法的FTL引導

一、抽象綁定關系 1. 什么是 AF Block,什么是 NF Block,為什么要將多個 NF Block 綁定為一個 AF Block AF Block(Allocation Flash Block) 和 NF Block(NAND Flash Block) 是在 NAND Flash 存儲架構中用于管理數據的基本單位。 AF Block 定義:AF Block 是一組多個 NF…

快速入門Java中的IO操作

以下是 Java 中常用的 IO 知識點總結&#xff1a; 1. 流的分類 按數據流向&#xff1a;輸入流&#xff08;讀取數據&#xff09;和輸出流&#xff08;寫入數據&#xff09;。按數據類型&#xff1a;字節流&#xff08;處理二進制數據&#xff0c;以字節為單位&#xff09;和字符…

小程序軟裝: 組件庫開發

本節概述 經過前面小節的學習&#xff0c;我們已經搭建起了小程序的編譯構建環境&#xff0c;能夠將我們開發的小程序項目編譯成為對應的邏輯代碼文件 logic.js&#xff0c;頁面渲染文件 view.js&#xff0c;樣式文件 style.css 和配置文件 config.json 在編譯小程序的過程中…

250708-Debian系統安裝Edge瀏覽器并配置最小中文輸入法

在 Debian 系統上安裝 Microsoft Edge 瀏覽器可以通過以下幾種方式進行。Microsoft 官方提供了 .deb 安裝包&#xff0c;適用于 Debian、Ubuntu 及其衍生系統。 A. 如何安裝&#xff1f; ? 方法一&#xff1a;使用 .deb 安裝包&#xff08;推薦&#xff09; 步驟 1&#xff…

docker所占硬盤內存指令

使用下面命令可以查看docker所占的硬盤大小&#xff0c;如&#xff1a;docker system dfdocker system df -v

A1126LLHLX-T Allegro霍爾效應鎖存器,5kHz+推挽輸出,汽車級轉速檢測專家!

A1126LLHLX-T&#xff08;Allegro&#xff09;產品解析一、產品定位A1126LLHLX-T是Allegro MicroSystems推出的全極性霍爾效應鎖存器&#xff0c;采用超薄SOT-23W封裝&#xff08;1mm厚度&#xff09;&#xff0c;專為高可靠性位置檢測與轉速測量設計&#xff0c;具有低功耗、高…

【C#】File從后往前讀取文件指定行數

/// <summary>/// 從后往前讀取文件最后行數據/// </summary>/// <param name"filePath"></param>/// <param name"count"></param>/// <returns></returns>public static List<string> ReadFileRe…

暑假算法日記第五天

目標?&#xff1a;刷完靈神專題訓練算法題單 階段目標&#x1f4cc;&#xff1a;【算法題單】滑動窗口與雙指針 LeetCode題目:683. K 個關閉的燈泡2067. 等計數子串的數量2524. 子數組的最大頻率分數2269. 找到一個數字的 K 美麗值1984. 學生分數的最小差值1461. 檢查一個字符…

【05】MFC入門到精通——MFC 為對話框中的控件添加變量 和 數據交換和檢驗

文章目錄四、 為對話框中的控件添加變量五、對話框類的5.1 為編輯框添加變量面步驟中 為對話框添加了幾個控件&#xff0c;包括三個靜態文本框&#xff0c;三個編輯框&#xff0c;一個按鈕控件。 四、 為對話框中的控件添加變量 編輯框中的數據可能會經常變化&#xff0c;有必…

4-Kafka-partition(分區)概念

Kafka Topic 分區詳解 &#x1f4cc; 一、分區核心概念 1. 什么是分區&#xff1f; 物理分片&#xff1a;Topic 被劃分為多個分區&#xff08;Partition&#xff09;&#xff0c;每個分區是一個有序、不可變的消息序列存儲單位&#xff1a;每個分區對應一個物理日志文件&…

論文略讀:UniPELT: A Unified Framework for Parameter-Efficient Language Model Tuning

ACL 2021 LoRAPrefix TuningAdapter門控藍色參數是可訓練的參數

【論文閱讀】CogView: Mastering Text-to-Image Generation via Transformers

CogView&#xff1a;通過Transformers實現文本到圖像的生成簡介目標&#xff1a;通用領域中的文本到圖像生成一直是一個開放的問題&#xff0c;它既需要強大的生成模型&#xff0c;也需要跨模態的理解。為了解決這個問題&#xff0c;我們提出了CogView&#xff0c;一個具有VQ -…

Typecho與WordPress技術架構深度對比:從LAMP到輕量級設計

文章目錄 Typecho vs WordPress:深入比較兩大博客系統的優劣與選型指南引言1. 系統概述與技術架構1.1 WordPress架構分析1.2 Typecho架構特點2. 核心功能對比2.1 內容管理能力2.2 主題與模板系統3. 性能與擴展性對比3.1 系統性能基準測試3.2 擴展生態系統4. 安全性與維護成本4…

CSS揭秘:8.連續的圖像邊框

前置知識&#xff1a;CSS 漸變&#xff0c;5. 條紋背景&#xff0c;border-image&#xff0c;基本的 CSS 動畫前言 本文旨在實現圖片邊框效果&#xff0c;即在特定場景下讓圖片顯示在邊框而非背景區域。 一、傳統實現方案 正常我們面對這樣一個需求時&#xff0c;下意識會想到的…

Linux驅動學習day20(pinctrl子系統驅動大全)

一、Pinctrl作用Pinctrl(Pin Controller)&#xff1a;控制引腳引腳的枚舉與命名、引腳復用、引腳配置。Pinctrl驅動一般由芯片原廠的BSP工程師來寫&#xff0c;一般驅動工程師只需要在設備樹中指明使用哪個引腳&#xff0c;復用為哪個功能、配置為哪些狀態。二、Pin Controller…

Debiased All-in-one Image Restoration with Task Uncertainty Regularization

Abstract 一體化圖像恢復是一項基礎的底層視覺任務&#xff0c;在現實世界中有重要應用。主要挑戰在于在單個模型中處理多種退化情況。雖然當前方法主要利用任務先驗信息來指導恢復模型&#xff0c;但它們通常采用統一的多任務學習&#xff0c;忽略了不同退化任務在模型優化中的…

逆向 qq 音樂 sign,data, 解密 response 返回的 arraybuffer

解密 arraybuffer python requests 請求得到 arraybuffer&#xff0c;轉為 hex 傳遞給 js res_data sign ctx.call("decrypt", response.content.hex())function decrypt(hex) {const bytes new Uint8Array(hex.length / 2);for (let i 0; i < hex.length; i …

PPT處理控件Aspose.Slides教程:在 C# 中將 ODP 轉換為 PPTX

您是否正在尋找可靠的 PowerPoint SDK 來以編程方式開發ODP到PPTX轉換器&#xff1f;本篇博文演示了如何使用 C# 將 ODP 轉換為 PPTX。ODP是一種基于 XML 的演示文稿文件&#xff0c;可能包含圖像、視頻、文本等。但是&#xff0c;將打開的文檔演示文稿轉換為 PowerPoint 格式可…