SpringMVC快速入門之請求與響應
- 一、請求處理:獲取請求參數
- 1.1 普通參數獲取(@RequestParam)
- 1.1.1 基礎用法
- 1.1.2 可選參數與默認值
- 1.2 路徑變量(@PathVariable)
- 1.3 表單數據綁定到對象
- 1.3.1 定義實體類
- 1.3.2 綁定對象參數
- 1.4 獲取請求頭與Cookie(@RequestHeader、@CookieValue)
- 1.4.1 獲取請求頭
- 1.4.2 獲取Cookie
- 1.5 獲取JSON請求體(@RequestBody)
- 1.5.1 依賴準備
- 1.5.2 接收JSON數據
- 二、響應處理:返回結果給客戶端
- 2.1 頁面跳轉(ModelAndView)
- 2.1.1 返回邏輯視圖名(推薦)
- 2.1.2 使用ModelAndView
- 2.2 重定向與轉發
- 2.2.1 重定向(redirect:)
- 2.2.2 轉發(forward:)
- 2.3 返回JSON數據(@ResponseBody)
- 2.3.1 基礎用法
- 2.3.2 @RestController簡化配置
- 三、實戰案例:用戶注冊與查詢
- 3.1 注冊頁面(register.jsp)
- 3.2 結果頁面(result.jsp)
- 3.3 Controller完整實現
- 3.4 測試流程
- 四、常見問題與避坑指南
- 4.1 參數綁定失敗(400 Bad Request)
- 4.2 JSON解析失敗(400 Bad Request)
- 4.3 @ResponseBody返回406 Not Acceptable
- 總結:請求與響應的核心要點
SpringMVC中請求(Request)與響應(Response)是核心交互流程:客戶端通過請求傳遞數據,服務器處理后通過響應返回結果,掌握請求參數的接收和響應結果的處理,是開發Web接口的基礎。
一、請求處理:獲取請求參數
SpringMVC提供了多種注解簡化請求參數的獲取,無需像原生Servlet那樣手動調用request.getParameter()
。
1.1 普通參數獲取(@RequestParam)
適用于獲取URL查詢參數(?name=張三&age=25
)或表單提交的參數。
1.1.1 基礎用法
@Controller
@RequestMapping("/user")
public class UserController {/*** 獲取普通參數* URL示例:/user/query?name=張三&age=25*/@GetMapping("/query")public String queryUser(// @RequestParam:綁定參數(默認必填)@RequestParam String name,// 可指定參數名(若參數名與變量名一致,可省略@RequestParam)@RequestParam("age") Integer userAge,Model model) {model.addAttribute("message", "姓名:" + name + ",年齡:" + userAge);return "result"; // 跳轉結果頁面}
}
1.1.2 可選參數與默認值
若參數非必填,可通過required=false
設置,或指定默認值:
/*** 可選參數與默認值* URL示例:/user/search?keyword=Spring(或無參數)*/
@GetMapping("/search")
public String search(// 可選參數(required=false)@RequestParam(required = false) String keyword,// 默認值(若參數為空,使用默認值)@RequestParam(defaultValue = "10") Integer size,Model model) {model.addAttribute("message", "關鍵詞:" + (keyword == null ? "無" : keyword) + ",每頁條數:" + size);return "result";
}
核心說明:
- 若參數名與方法參數名一致,
@RequestParam
可省略(如String name
等價于@RequestParam String name
); - 基本類型(
int
)需確保參數存在,否則會報錯,建議使用包裝類(Integer
)并設置required=false
。
1.2 路徑變量(@PathVariable)
適用于REST風格的URL(如/user/1
),從URL路徑中獲取參數。
/*** 路徑變量* URL示例:/user/1/detail*/
@GetMapping("/{id}/detail")
public String getUserDetail(// 從路徑中獲取id(與URL中的{id}對應)@PathVariable Integer id,Model model) {model.addAttribute("message", "查詢ID為" + id + "的用戶詳情");return "result";
}
進階用法:多路徑變量
/*** 多路徑變量* URL示例:/user/1/order/100*/
@GetMapping("/{userId}/order/{orderId}")
public String getOrder(@PathVariable("userId") Integer uId,@PathVariable Integer orderId, // 變量名與{orderId}一致,可省略valueModel model) {model.addAttribute("message", "用戶ID:" + uId + ",訂單ID:" + orderId);return "result";
}
1.3 表單數據綁定到對象
當參數較多時(如用戶注冊),可將參數自動綁定到Java對象。
1.3.1 定義實體類
package com.example.pojo;import lombok.Data;@Data // Lombok注解,自動生成getter/setter
public class User {private String username;private Integer age;private String email;
}
1.3.2 綁定對象參數
/*** 表單數據綁定到對象* 表單提交示例:username=張三&age=25&email=test@example.com*/
@PostMapping("/register")
public String registerUser(// 自動將參數綁定到User對象(參數名與對象屬性名一致)User user,Model model) {model.addAttribute("message", "注冊用戶:" + user.getUsername() + ",年齡:" + user.getAge() + ",郵箱:" + user.getEmail());return "result";
}
核心說明:
- 要求表單參數名或查詢參數名與對象的屬性名一致(如
username
對應user.getUsername()
); - 支持嵌套對象(如
User
包含Address
對象,參數名需為address.city
)。
1.4 獲取請求頭與Cookie(@RequestHeader、@CookieValue)
1.4.1 獲取請求頭
/*** 獲取請求頭*/
@GetMapping("/header")
public String getHeader(// 獲取User-Agent請求頭@RequestHeader("User-Agent") String userAgent,// 獲取Accept請求頭@RequestHeader("Accept") String accept,Model model) {model.addAttribute("message", "瀏覽器信息:" + userAgent + ",Accept:" + accept);return "result";
}
1.4.2 獲取Cookie
/*** 獲取Cookie*/
@GetMapping("/cookie")
public String getCookie(// 獲取名為JSESSIONID的Cookie值@CookieValue(value = "JSESSIONID", required = false) String sessionId,Model model) {model.addAttribute("message", "JSESSIONID:" + (sessionId == null ? "無" : sessionId));return "result";
}
1.5 獲取JSON請求體(@RequestBody)
適用于接收前端發送的JSON數據(如Ajax請求),需結合@ResponseBody
使用。
1.5.1 依賴準備
確保添加Jackson依賴(用于JSON解析):
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.3</version>
</dependency>
1.5.2 接收JSON數據
/*** 接收JSON請求體* 請求體示例:{"username":"張三","age":25}*/
@PostMapping("/json")
@ResponseBody // 返回JSON(而非跳轉頁面)
public User receiveJson(@RequestBody User user) {// 處理邏輯(如保存用戶)user.setUsername(user.getUsername() + "_processed"); // 修改用戶名return user; // 返回處理后的對象(自動轉為JSON)
}
測試方式:
使用Postman發送POST請求:
- URL:
http://localhost:8080/user/json
- 請求頭:
Content-Type: application/json
- 請求體:
{"username":"張三","age":25}
響應結果(JSON):
{"username":"張三_processed","age":25,"email":null}
二、響應處理:返回結果給客戶端
SpringMVC的響應方式分為兩類:頁面跳轉(返回視圖)和數據響應(返回JSON、字符串等)。
2.1 頁面跳轉(ModelAndView)
通過返回邏輯視圖名或ModelAndView
實現頁面跳轉,適用于傳統JSP開發。
2.1.1 返回邏輯視圖名(推薦)
/*** 返回邏輯視圖名(默認跳轉頁面)*/
@GetMapping("/toIndex")
public String toIndex(Model model) {model.addAttribute("title", "首頁"); // 向視圖傳遞數據return "index"; // 邏輯視圖名,由視圖解析器轉為/WEB-INF/views/index.jsp
}
2.1.2 使用ModelAndView
/*** 使用ModelAndView跳轉頁面*/
@GetMapping("/toDetail")
public ModelAndView toDetail() {ModelAndView mav = new ModelAndView();mav.setViewName("detail"); // 設置邏輯視圖名mav.addObject("id", 1); // 添加數據(等價于Model.addAttribute)mav.addObject("name", "商品詳情");return mav;
}
2.2 重定向與轉發
2.2.1 重定向(redirect:)
重定向會發起新的請求,地址欄URL會變化,之前的Model
數據會丟失:
/*** 重定向*/
@GetMapping("/redirect")
public String redirect() {// 重定向到首頁(可跳轉至其他Controller接口)return "redirect:/toIndex";
}
2.2.2 轉發(forward:)
轉發是服務器內部跳轉,地址欄URL不變,Model
數據可共享:
/*** 轉發*/
@GetMapping("/forward")
public String forward() {// 轉發到詳情頁(僅能跳轉至當前應用內的路徑)return "forward:/toDetail";
}
2.3 返回JSON數據(@ResponseBody)
適用于Ajax請求或前后端分離項目,通過@ResponseBody
將對象轉為JSON返回。
2.3.1 基礎用法
@Controller
@RequestMapping("/api/user")
public class UserApiController {/*** 返回單個對象* URL:/api/user/1*/@GetMapping("/{id}")@ResponseBody // 將返回值轉為JSONpublic User getUser(@PathVariable Integer id) {// 模擬查詢數據庫User user = new User();user.setUsername("張三");user.setAge(25);user.setEmail("zhangsan@example.com");return user; // 自動轉為JSON}/*** 返回集合* URL:/api/user/list*/@GetMapping("/list")@ResponseBodypublic List<User> getUserList() {List<User> list = new ArrayList<>();list.add(new User("張三", 25, "zhangsan@example.com"));list.add(new User("李四", 28, "lisi@example.com"));return list; // 自動轉為JSON數組}/*** 返回自定義結果(統一響應格式)* URL:/api/user/login*/@PostMapping("/login")@ResponseBodypublic Result login(@RequestParam String username,@RequestParam String password) {if ("admin".equals(username) && "123456".equals(password)) {// 登錄成功return Result.success("登錄成功", new User(username, 0, null));} else {// 登錄失敗return Result.error("用戶名或密碼錯誤");}}
}// 統一響應結果類
@Data
class Result {private int code; // 狀態碼(200成功,400失敗)private String message; // 提示信息private Object data; // 數據// 成功響應public static Result success(String message, Object data) {Result result = new Result();result.code = 200;result.message = message;result.data = data;return result;}// 錯誤響應public static Result error(String message) {Result result = new Result();result.code = 400;result.message = message;return result;}
}
測試結果:
訪問/api/user/1
,響應JSON:
{"username":"張三","age":25,"email":"zhangsan@example.com"}
訪問/api/user/login?username=admin&password=123456
,響應JSON:
{"code":200,"message":"登錄成功","data":{"username":"admin","age":0,"email":null}}
2.3.2 @RestController簡化配置
若控制器所有方法都返回JSON,可使用@RestController
替代@Controller
(自動為所有方法添加@ResponseBody
):
// @RestController = @Controller + @ResponseBody
@RestController
@RequestMapping("/api/book")
public class BookApiController {// 無需添加@ResponseBody,自動返回JSON@GetMapping("/{id}")public Book getBook(@PathVariable Integer id) {return new Book(id, "SpringMVC教程", "技術書籍");}
}
三、實戰案例:用戶注冊與查詢
結合請求與響應的核心知識點,實現用戶注冊(表單提交)和查詢(JSON響應)功能。
3.1 注冊頁面(register.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>用戶注冊</title>
</head>
<body>
<form action="/user/register" method="post">用戶名:<input type="text" name="username"><br>年齡:<input type="number" name="age"><br>郵箱:<input type="email" name="email"><br><button type="submit">注冊</button>
</form>
</body>
</html>
3.2 結果頁面(result.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>結果頁</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
3.3 Controller完整實現
@Controller
@RequestMapping("/user")
public class UserController {// 跳轉注冊頁面@GetMapping("/toRegister")public String toRegister() {return "register";}// 處理注冊(表單提交)@PostMapping("/register")public String register(User user, Model model) {// 模擬保存用戶(實際項目中調用Service)model.addAttribute("message", "注冊成功!用戶信息:" + user);return "result";}// 按條件查詢(返回JSON)@GetMapping("/api/query")@ResponseBodypublic Result query(@RequestParam(required = false) String username,@RequestParam(required = false) Integer minAge) {// 模擬查詢List<User> users = new ArrayList<>();users.add(new User("張三", 25, "zhangsan@example.com"));users.add(new User("李四", 30, "lisi@example.com"));return Result.success("查詢成功", users);}
}
3.4 測試流程
- 訪問
/user/toRegister
,填寫表單提交; - 注冊成功后跳轉至結果頁,顯示用戶信息;
- 訪問
/user/api/query?username=張三
,獲取JSON格式的查詢結果。
四、常見問題與避坑指南
4.1 參數綁定失敗(400 Bad Request)
錯誤信息:Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'
原因:
- 參數類型不匹配(如前端傳遞字符串,后端接收為
Integer
); - 缺少必填參數(
@RequestParam
默認必填)。
解決方案:
- 確保參數類型匹配(如年齡參數傳遞數字,而非字符串);
- 非必填參數添加
required=false
; - 若參數可能為空,使用包裝類(
Integer
)而非基本類型(int
)。
4.2 JSON解析失敗(400 Bad Request)
錯誤信息:HttpMessageNotReadableException: JSON parse error
原因:
- 請求頭未設置
Content-Type: application/json
; - JSON格式錯誤(如缺少引號、逗號);
- JSON字段與對象屬性不匹配(如拼寫錯誤)。
解決方案:
- 發送JSON請求時,務必設置
Content-Type: application/json
; - 檢查JSON格式(可通過JSON校驗工具驗證);
- 確保JSON字段名與對象屬性名一致(區分大小寫)。
4.3 @ResponseBody返回406 Not Acceptable
錯誤信息:406 Not Acceptable
原因:
- 缺少Jackson依賴,無法將對象轉為JSON;
- 請求頭
Accept
設置不當(如僅接受text/html
,但返回JSON)。
解決方案:
- 添加Jackson依賴(
jackson-databind
); - 檢查請求頭
Accept
是否包含application/json
(或不限制Accept
)。
總結:請求與響應的核心要點
SpringMVC的請求與響應是前后端交互的核心:
-
請求處理:
- 普通參數用
@RequestParam
,路徑參數用@PathVariable
; - 多參數用對象綁定,JSON參數用
@RequestBody
; - 靈活使用可選參數和默認值,避免參數缺失錯誤。
- 普通參數用
-
響應處理:
- 頁面跳轉返回邏輯視圖名,配合
Model
傳遞數據; - JSON響應用
@ResponseBody
或@RestController
; - 重定向與轉發需區分使用場景(重定向適合外部鏈接,轉發適合內部跳轉)。
- 頁面跳轉返回邏輯視圖名,配合
-
避坑關鍵:
- 參數綁定注意類型匹配和必填性;
- JSON處理確保依賴正確和格式規范;
- 前后端約定參數名和數據格式,減少溝通成本。
若這篇內容幫到你,動動手指支持下!關注不迷路,干貨持續輸出!
ヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノ