概述
Spring MVC 数据绑定是将HTTP请求中的参数数据自动绑定到控制器方法参数的过程。这个机制极大地简化了Web开发,让开发者可以专注于业务逻辑而不是参数解析。
什么是数据绑定?
数据绑定是将请求消息数据和后台方法形参建立连接的过程。Spring MVC 提供了强大的数据绑定功能,可以自动将请求参数转换为Java对象。
请求数据来源
- URL参数:通过URL传递参数,如
localhost:8080/user?id=1 - 表单数据:通过HTML表单POST提交的数据
- 请求体:JSON、XML等格式的请求体数据
- 请求头:HTTP请求头中的数据
- Cookie:浏览器Cookie中的数据
- Session属性:会话中存储的数据
数据绑定分类
根据后台方法形参的类型,数据绑定可以分为:
- 简单数据绑定:基本类型、String、默认支持的类型
- 复杂数据绑定:数组、集合、Map、自定义对象等
数据绑定原理
Spring MVC 的数据绑定由 HandlerMethodArgumentResolver 接口实现,主要流程如下:
- 参数解析:解析HTTP请求,提取参数数据
- 类型转换:使用
ConversionService将字符串转换为目标类型 - 数据验证:使用
Validator进行数据验证 - 绑定结果:将转换后的值绑定到方法参数
简单数据绑定
默认数据类型
Spring MVC 默认支持以下几种类型的参数绑定:
- HttpServletRequest:获取原始的请求对象,可以获取请求参数、请求头等信息
- HttpServletResponse:获取响应对象,用于直接操作响应流
- HttpSession:获取会话对象,访问session中的数据
- Model/ModelMap:用于向视图传递数据
Model是一个接口ModelMap是Model的实现类- 作用是将数据填充到request域中
- ModelAndView:同时包含模型数据和视图信息
- Locale:获取请求的区域信息
- InputStream/Reader:获取请求输入流
- OutputStream/Writer:获取响应输出流
下面以 HttpServletRequest 为例进行详细讲解:
1. 创建项目并导入依赖
在 pom.xml 中添加 Spring MVC 相关依赖:
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.23</version>
</dependency>
<!-- Spring WebMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.23</version>
</dependency>
<!-- JSP 支持(可选) -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- JSTL(可选) -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
2. 配置 web.xml
在 web.xml 中配置 DispatcherServlet 和字符编码过滤器:
<?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">
<!-- 配置 Spring MVC 前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置字符编码过滤器,解决中文乱码问题 -->
<filter>
<filter-name>CharacterEncodingFilter</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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3. 创建 Spring MVC 配置文件
在 src/main/resources 目录下创建 springmvc-config.xml:
4. 创建控制器类
创建使用 HttpServletRequest 的控制器示例:
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 使用 HttpServletRequest 获取请求参数
*/
@RequestMapping("/selectUser")
public String selectUser(HttpServletRequest request) {
// 获取请求参数
String id = request.getParameter("id");
String name = request.getParameter("name");
// 获取请求头信息
String userAgent = request.getHeader("User-Agent");
// 获取请求URL信息
String requestURI = request.getRequestURI();
System.out.println("id=" + id);
System.out.println("name=" + name);
System.out.println("User-Agent=" + userAgent);
System.out.println("Request URI=" + requestURI);
return "success";
}
/**
* 使用多个默认类型参数
*/
@RequestMapping("/defaultTypes")
public String demonstrateDefaultTypes(
HttpServletRequest request,
HttpServletResponse response,
HttpSession session,
Model model,
ModelMap modelMap) {
// 使用 HttpServletRequest
String param = request.getParameter("param");
// 使用 HttpSession
session.setAttribute("user", "John Doe");
Object user = session.getAttribute("user");
// 使用 Model
model.addAttribute("message", "Hello from Model");
// 使用 ModelMap
modelMap.addAttribute("info", "Hello from ModelMap");
// HttpServletResponse 可用于直接写入响应
// response.setContentType("text/html;charset=UTF-8");
return "success";
}
}
5.创建前端页面 success.jsp
在 WEB-INF 文件夹下面创建 jsp 文件夹,然后创建前端页面
<body>
success
</body>
6. 配置 Spring MVC
完善 springmvc-config.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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开启组件扫描,扫描控制器 -->
<context:component-scan base-package="com.example.controller"/>
<!-- 开启 Spring MVC 注解支持 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 静态资源处理 -->
<mvc:default-servlet-handler/>
</beans>
7. 部署和测试
-
配置 Tomcat 服务器
- 在 IDE 中配置 Tomcat 服务器
- 部署项目到 Tomcat
- 启动服务器
-
测试默认类型绑定
发送请求:
http://localhost:8080/项目名/user/selectUser?id=1&name=John控制台输出:
id=1 name=John User-Agent=Mozilla/5.0... Request URI=/项目名/user/selectUser

基本数据类型
Spring MVC 支持自动绑定基本数据类型和包装类型:
- 基本类型:int、long、float、double、boolean、char 等
- 包装类型:Integer、Long、Float、Double、Boolean、Character 等
- 字符串类型:String
- 日期类型:Date(需要格式化)
1. 基本类型绑定示例
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Controller
@RequestMapping("/data")
public class DataBindingController {
/**
* 基本类型自动绑定
*/
@RequestMapping("/getUser")
public String getUser(int id, String name) {
System.out.println("id=" + id);
System.out.println("name=" + name);
return "success";
}
/**
* 使用包装类型(推荐)
* 包装类型可以接收 null 值,避免类型转换异常
*/
@RequestMapping("/getUserSafe")
public String getUserSafe(Integer id, String name) {
if (id != null) {
System.out.println("id=" + id);
} else {
System.out.println("id 参数未提供");
}
System.out.println("name=" + name);
return "success";
}
/**
* 多种基本类型绑定
*/
@RequestMapping("/multiTypes")
public String multipleTypes(
Integer id,
String name,
Double salary,
Boolean active,
@DateTimeFormat(pattern = "yyyy-MM-dd") Date birthDate) {
System.out.println("ID: " + id);
System.out.println("Name: " + name);
System.out.println("Salary: " + salary);
System.out.println("Active: " + active);
System.out.println("Birth Date: " + birthDate);
return "success";
}
}
2. 测试请求
发送请求测试基本类型绑定:
http://localhost:8080/项目名/data/getUser?id=4&name=John
http://localhost:8080/项目名/data/getUserSafe?name=John // id为null,不会报错
http://localhost:8080/项目名/data/multiTypes?id=1&name=John&salary=5000.50&active=true&birthDate=1990-01-01
3. @RequestParam 注解
当请求参数名与方法参数名不一致时,使用 @RequestParam 注解进行映射:
/**
* 使用 @RequestParam 注解映射参数
*/
@RequestMapping("/paramMapping")
public String paramMapping(
@RequestParam("user_id") Integer userId, // 将 user_id 映射到 userId
@RequestParam(value = "user_name", required = false) String userName, // 可选参数
@RequestParam(defaultValue = "10") int pageSize) { // 带默认值的参数
System.out.println("User ID: " + userId);
System.out.println("User Name: " + userName);
System.out.println("Page Size: " + pageSize);
return "success";
}
@RequestParam 属性说明:
value/name:指定请求参数名称required:是否必须,默认为 truedefaultValue:参数默认值

POJO绑定
POJO(Plain Old Java Object)是普通的Java对象。Spring MVC 可以自动将请求参数绑定到POJO的属性中,这种方式在处理表单数据时非常方便。
绑定规则
- 请求参数名必须与POJO的属性名一致
- 支持级联属性绑定(如 user.name)
- 自动进行类型转换
下面以用户注册为例进行说明:
1. 创建实体类 User
package com.example.domain;
import java.util.Date;
/**
* 用户实体类
*/
public class User {
private Integer id;
private String username;
private String password;
private String email;
private Date birthDate;
private Boolean active;
// 默认构造函数
public User() {}
// 带参构造函数
public User(String username, String password) {
this.username = username;
this.password = password;
}
// Getter 和 Setter 方法
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public 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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'\'' +
", password='" + password + '\'\'' +
", email='" + email + '\'\'' +
", birthDate=" + birthDate +
", active=" + active +
'}';
}
}
2. 创建注册页面 register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.form-group {
margin-bottom: 15px;
}
label {
display: inline-block;
width: 100px;
}
</style>
</head>
<body>
<h2>用户注册</h2>
<form action="${pageContext.request.contextPath}/user/registerUser" method="post">
<div class="form-group">
<label>用户名:</label>
<input type="text" name="username" required/>
</div>
<div class="form-group">
<label>密码:</label>
<input type="password" name="password" required/>
</div>
<div class="form-group">
<label>邮箱:</label>
<input type="email" name="email"/>
</div>
<div class="form-group">
<label>生日:</label>
<input type="date" name="birthDate"/>
</div>
<div class="form-group">
<label>是否激活:</label>
<input type="checkbox" name="active" value="true"/>
</div>
<div class="form-group">
<input type="submit" value="注册"/>
<input type="reset" value="重置"/>
</div>
</form>
</body>
</html>
3. 创建控制器方法
package com.example.controller;
import com.example.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.ui.Model;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 跳转到注册页面
*/
@RequestMapping("/toRegister")
public String toRegister() {
return "register";
}
/**
* 处理用户注册
* Spring MVC 会自动将表单数据绑定到 User 对象的属性上
*/
@RequestMapping(value = "/registerUser", method = RequestMethod.POST)
public String registerUser(User user, Model model) {
// 打印接收到的用户信息
System.out.println("注册用户信息:" + user);
// 模拟保存用户
// userService.save(user);
// 将用户信息传递给成功页面
model.addAttribute("user", user);
model.addAttribute("message", "注册成功!");
return "success";
}
/**
* 使用 @ModelAttribute 注解
* 可以自定义绑定的属性名
*/
@RequestMapping(value = "/registerWithModelAttribute", method = RequestMethod.POST)
public String registerWithModelAttribute(
@ModelAttribute("newUser") User user,
Model model) {
System.out.println("使用@ModelAttribute注册:" + user);
// 在视图中可以通过 ${newUser} 访问
model.addAttribute("message", "注册成功!");
return "success";
}
}
4. 创建成功页面 success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>注册成功</title>
</head>
<body>
<h2>${message}</h2>
<h3>用户信息:</h3>
<p>用户名:${user.username}</p>
<p>邮箱:${user.email}</p>
<p>生日:${user.birthDate}</p>
<p>状态:${user.active ? '已激活' : '未激活'}</p>
</body>
</html>
5. 测试 POJO 绑定
- 访问注册页面:
http://localhost:8080/项目名/user/toRegister - 填写表单并提交
- 查看控制台输出和成功页面
注意事项:
- 确保表单的
name属性与 POJO 的属性名一致 - 日期格式需要使用
@DateTimeFormat注解指定格式 - 布尔类型的 checkbox,选中时值为 true
- 中文乱码问题已通过字符编码过滤器解决

包装POJO类型
包装POJO类型用于处理复杂的嵌套对象绑定。当请求参数涉及多个相关对象时,可以使用包装类将它们组织在一起。
应用场景
- 查询条件包含多个对象的属性
- 表单数据涉及主从关系
- 需要同时提交多个相关实体的数据
绑定规则
- 使用点号(.)访问嵌套属性
- 支持多层嵌套
- 自动创建嵌套对象
1. 创建订单实体类
package com.example.domain;
import java.util.Date;
/**
* 订单实体类
*/
public class Order {
private Integer orderId;
private String orderNumber;
private Date orderDate;
private Double totalAmount;
private User user; // 关联的用户对象
private Address shippingAddress; // 配送地址
// Getter 和 Setter 方法
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getOrderNumber() {
return orderNumber;
}
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
public Double getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(Double totalAmount) {
this.totalAmount = totalAmount;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Address getShippingAddress() {
return shippingAddress;
}
public void setShippingAddress(Address shippingAddress) {
this.shippingAddress = shippingAddress;
}
@Override
public String toString() {
return "Order{" +
"orderId=" + orderId +
", orderNumber='" + orderNumber + '\'\'' +
", orderDate=" + orderDate +
", totalAmount=" + totalAmount +
", user=" + user +
", shippingAddress=" + shippingAddress +
'}';
}
}
/**
* 地址实体类
*/
class Address {
private String street;
private String city;
private String zipCode;
// Getter 和 Setter 方法
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
@Override
public String toString() {
return "Address{" +
"street='" + street + '\'\'' +
", city='" + city + '\'\'' +
", zipCode='" + zipCode + '\'\'' +
'}';
}
}
2. 创建订单控制器
package com.example.controller;
import com.example.domain.Order;
import com.example.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.Model;
@Controller
@RequestMapping("/order")
public class OrderController {
/**
* 跳转到订单查询页面
*/
@RequestMapping("/toFindOrderWithUser")
public String toFindOrderWithUser() {
return "orders";
}
/**
* 查询订单及用户信息
* 演示嵌套对象的数据绑定
*/
@RequestMapping(value = "/findOrderWithUser", method = RequestMethod.POST)
public String findOrderWithUser(Order order, Model model) {
// 获取订单信息
System.out.println("订单编号:" + order.getOrderNumber());
System.out.println("订单金额:" + order.getTotalAmount());
// 获取嵌套的用户信息
if (order.getUser() != null) {
System.out.println("下单用户:" + order.getUser().getUsername());
System.out.println("用户邮箱:" + order.getUser().getEmail());
}
// 获取嵌套的地址信息
if (order.getShippingAddress() != null) {
System.out.println("配送地址:" + order.getShippingAddress());
}
// 传递到视图
model.addAttribute("order", order);
model.addAttribute("message", "订单查询成功");
return "orderDetail";
}
/**
* 创建新订单
* 演示更复杂的嵌套绑定
*/
@RequestMapping("/toCreateOrder")
public String toCreateOrder() {
return "createOrder";
}
@RequestMapping(value = "/createOrder", method = RequestMethod.POST)
public String createOrder(Order order, Model model) {
System.out.println("创建订单:" + order);
// 模拟保存订单
// orderService.save(order);
model.addAttribute("order", order);
model.addAttribute("message", "订单创建成功");
return "orderDetail";
}
}
3. 创建订单查询页面 orders.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>订单查询</title>
<style>
.form-group {
margin-bottom: 10px;
}
label {
display: inline-block;
width: 120px;
}
fieldset {
margin-bottom: 20px;
padding: 10px;
}
</style>
</head>
<body>
<h2>订单查询</h2>
<form action="${pageContext.request.contextPath}/order/findOrderWithUser" method="post">
<fieldset>
<legend>订单信息</legend>
<div class="form-group">
<label>订单编号:</label>
<input type="text" name="orderNumber" />
</div>
<div class="form-group">
<label>订单金额:</label>
<input type="number" step="0.01" name="totalAmount" />
</div>
</fieldset>
<fieldset>
<legend>用户信息</legend>
<div class="form-group">
<label>用户名:</label>
<input type="text" name="user.username" />
</div>
<div class="form-group">
<label>用户邮箱:</label>
<input type="email" name="user.email" />
</div>
</fieldset>
<fieldset>
<legend>配送地址</legend>
<div class="form-group">
<label>街道地址:</label>
<input type="text" name="shippingAddress.street" />
</div>
<div class="form-group">
<label>城市:</label>
<input type="text" name="shippingAddress.city" />
</div>
<div class="form-group">
<label>邮政编码:</label>
<input type="text" name="shippingAddress.zipCode" />
</div>
</fieldset>
<div class="form-group">
<input type="submit" value="查询" />
</div>
</form>
</body>
</html>
4. 创建订单详情页面 orderDetail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>订单详情</title>
</head>
<body>
<h2>${message}</h2>
<h3>订单信息</h3>
<p>订单编号:${order.orderNumber}</p>
<p>订单金额:${order.totalAmount}</p>
<h3>用户信息</h3>
<p>用户名:${order.user.username}</p>
<p>邮箱:${order.user.email}</p>
<h3>配送地址</h3>
<p>街道:${order.shippingAddress.street}</p>
<p>城市:${order.shippingAddress.city}</p>
<p>邮编:${order.shippingAddress.zipCode}</p>
</body>
</html>
5. 测试包装类型绑定
- 访问订单查询页面:
http://localhost:8080/项目名/order/toFindOrderWithUser - 填写表单数据:
- 订单编号:ORDER001
- 订单金额:999.99
- 用户名:John Doe
- 用户邮箱:john@example.com
- 街道地址:123 Main St
- 城市:New York
- 邮编:10001
- 提交表单,查看控制台输出和订单详情页面
注意事项:
- 嵌套属性使用点号(.)分隔
- Spring MVC 会自动创建嵌套对象
- 确保嵌套类有无参构造函数

复杂数据绑定
数组绑定
数组绑定常用于批量操作,如批量删除、批量更新等场景。Spring MVC 可以自动将同名的多个参数值绑定到数组中。
1. 创建用户列表页面 user.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户管理</title>
<style>
table {
border-collapse: collapse;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
</style>
</head>
<body>
<h2>批量删除用户</h2>
<form method="post" action="${pageContext.request.contextPath}/user/batchDelete">
<table>
<tr>
<th>选择</th>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>状态</th>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="1"/></td>
<td>1</td>
<td>Tom</td>
<td>tom@example.com</td>
<td>激活</td>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="2"/></td>
<td>2</td>
<td>Jack</td>
<td>jack@example.com</td>
<td>激活</td>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="3"/></td>
<td>3</td>
<td>Mary</td>
<td>mary@example.com</td>
<td>未激活</td>
</tr>
<tr>
<td><input type="checkbox" name="ids" value="4"/></td>
<td>4</td>
<td>John</td>
<td>john@example.com</td>
<td>激活</td>
</tr>
</table>
<input type="submit" value="批量删除" onclick="return confirm('确定要删除选中的用户吗?')"/>
</form>
<h2>其他数组绑定示例</h2>
<form method="post" action="${pageContext.request.contextPath}/user/updateStatus">
<p>选择要更新状态的用户ID(多选):</p>
<select name="userIds" multiple size="4">
<option value="1">用户1</option>
<option value="2">用户2</option>
<option value="3">用户3</option>
<option value="4">用户4</option>
</select>
<p>新状态:
<select name="status">
<option value="active">激活</option>
<option value="inactive">未激活</option>
</select>
</p>
<input type="submit" value="更新状态"/>
</form>
</body>
</html>
2. 编写数组绑定的控制器方法
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.ui.Model;
import java.util.Arrays;
@Controller
@RequestMapping("/user")
public class UserBatchController {
/**
* 跳转到用户管理页面
*/
@RequestMapping("/toUserList")
public String toUserList() {
return "user";
}
/**
* 批量删除用户 - 基本数组绑定
*/
@RequestMapping(value = "/batchDelete", method = RequestMethod.POST)
public String batchDeleteUsers(int[] ids, Model model) {
if (ids != null && ids.length > 0) {
System.out.println("准备删除的用户ID:" + Arrays.toString(ids));
// 模拟批量删除操作
for (int id : ids) {
System.out.println("删除了ID为 " + id + " 的用户");
// userService.delete(id);
}
model.addAttribute("message", "成功删除 " + ids.length + " 个用户");
} else {
System.out.println("未选择任何用户");
model.addAttribute("message", "请至少选择一个用户");
}
return "success";
}
/**
* 批量删除用户 - 使用包装类型数组(推荐)
*/
@RequestMapping(value = "/batchDeleteSafe", method = RequestMethod.POST)
public String batchDeleteUsersSafe(Integer[] ids, Model model) {
if (ids != null && ids.length > 0) {
System.out.println("删除用户ID:" + Arrays.toString(ids));
model.addAttribute("message", "成功删除 " + ids.length + " 个用户");
} else {
model.addAttribute("message", "未选择任何用户");
}
return "success";
}
/**
* 批量更新用户状态
* 演示多个数组参数的绑定
*/
@RequestMapping(value = "/updateStatus", method = RequestMethod.POST)
public String updateUserStatus(
@RequestParam("userIds") Long[] userIds,
@RequestParam("status") String status,
Model model) {
if (userIds != null && userIds.length > 0) {
System.out.println("更新用户ID:" + Arrays.toString(userIds));
System.out.println("新状态:" + status);
// 模拟更新操作
for (Long userId : userIds) {
System.out.println("将用户 " + userId + " 的状态更新为:" + status);
// userService.updateStatus(userId, status);
}
model.addAttribute("message",
"成功将 " + userIds.length + " 个用户的状态更新为:" + status);
} else {
model.addAttribute("message", "请选择要更新的用户");
}
return "success";
}
/**
* 处理不同类型的数组
*/
@RequestMapping("/multiArrayTypes")
public String handleMultipleArrayTypes(
String[] tags, // 字符串数组
Double[] prices, // 浮点数数组
Boolean[] flags) { // 布尔数组
System.out.println("Tags: " + Arrays.toString(tags));
System.out.println("Prices: " + Arrays.toString(prices));
System.out.println("Flags: " + Arrays.toString(flags));
return "success";
}
}
3. 测试数组绑定
- 访问用户管理页面:
http://localhost:8080/项目名/user/toUserList - 选择多个用户并点击”批量删除”
- 查看控制台输出
测试结果示例:
- 选择用户1、3、4进行删除
- 控制台输出:
准备删除的用户ID:[1, 3, 4] 删除了ID为 1 的用户 删除了ID为 3 的用户 删除了ID为 4 的用户
注意事项:
- checkbox 未选中时不会提交值
- 使用包装类型数组(Integer[])比基本类型数组(int[])更安全
- 可以使用 @RequestParam 指定参数名和是否必需

集合绑定
集合绑定用于处理动态数量的对象数据,常用于批量编辑、动态表单等场景。Spring MVC 不能直接绑定集合类型的参数,需要使用包装类。
1. 创建集合包装类
package com.example.vo;
import com.example.domain.User;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 用户集合包装类
* 用于批量操作用户数据
*/
public class UserVO {
private List<User> users; // 用户列表
private Set<Integer> selectedIds; // 选中的ID集合
private Map<Integer, String> statusMap; // ID与状态的映射
// 默认构造函数
public UserVO() {}
// Getter 和 Setter 方法
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Set<Integer> getSelectedIds() {
return selectedIds;
}
public void setSelectedIds(Set<Integer> selectedIds) {
this.selectedIds = selectedIds;
}
public Map<Integer, String> getStatusMap() {
return statusMap;
}
public void setStatusMap(Map<Integer, String> statusMap) {
this.statusMap = statusMap;
}
}
/**
* 订单集合包装类
*/
public class OrderVO {
private List<Order> orders;
private List<String> orderNumbers;
private Map<String, Double> priceMap;
// Getter 和 Setter 方法
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public List<String> getOrderNumbers() {
return orderNumbers;
}
public void setOrderNumbers(List<String> orderNumbers) {
this.orderNumbers = orderNumbers;
}
public Map<String, Double> getPriceMap() {
return priceMap;
}
public void setPriceMap(Map<String, Double> priceMap) {
this.priceMap = priceMap;
}
}
2. 编写集合绑定的控制器方法
package com.example.controller;
import com.example.domain.User;
import com.example.vo.UserVO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.ui.Model;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserCollectionController {
/**
* 跳转到批量编辑页面
* 预加载用户数据
*/
@RequestMapping("/toUserEdit")
public String toUserEdit(Model model) {
// 模拟从数据库加载用户列表
List<User> userList = new ArrayList<>();
User user1 = new User();
user1.setId(1);
user1.setUsername("Tom");
user1.setEmail("tom@example.com");
user1.setActive(true);
userList.add(user1);
User user2 = new User();
user2.setId(2);
user2.setUsername("Jack");
user2.setEmail("jack@example.com");
user2.setActive(true);
userList.add(user2);
User user3 = new User();
user3.setId(3);
user3.setUsername("Mary");
user3.setEmail("mary@example.com");
user3.setActive(false);
userList.add(user3);
// 创建VO对象
UserVO userVO = new UserVO();
userVO.setUsers(userList);
model.addAttribute("userVO", userVO);
return "user_edit";
}
/**
* 批量编辑用户
* 处理List集合绑定
*/
@RequestMapping(value = "/editUsers", method = RequestMethod.POST)
public String editUsers(@ModelAttribute UserVO userVO, Model model) {
// 获取用户列表
List<User> users = userVO.getUsers();
if (users != null && !users.isEmpty()) {
System.out.println("接收到 " + users.size() + " 个用户数据");
// 处理每个用户的修改
for (int i = 0; i < users.size(); i++) {
User user = users.get(i);
if (user.getId() != null) {
System.out.println("用户[" + i + "] - ID: " + user.getId() +
", 用户名: " + user.getUsername() +
", 邮箱: " + user.getEmail() +
", 状态: " + user.getActive());
// 模拟更新操作
// userService.update(user);
}
}
model.addAttribute("message", "成功更新 " + users.size() + " 个用户信息");
} else {
model.addAttribute("message", "没有接收到用户数据");
}
return "success";
}
/**
* 动态添加用户
* 演示动态表单的集合绑定
*/
@RequestMapping("/toDynamicUserForm")
public String toDynamicUserForm(Model model) {
// 初始化空的VO对象
UserVO userVO = new UserVO();
userVO.setUsers(new ArrayList<>());
model.addAttribute("userVO", userVO);
return "user_dynamic";
}
@RequestMapping(value = "/addDynamicUsers", method = RequestMethod.POST)
public String addDynamicUsers(@ModelAttribute UserVO userVO, Model model) {
List<User> users = userVO.getUsers();
if (users != null) {
// 过滤掉空的用户对象
List<User> validUsers = new ArrayList<>();
for (User user : users) {
if (user.getUsername() != null && !user.getUsername().trim().isEmpty()) {
validUsers.add(user);
}
}
System.out.println("接收到 " + validUsers.size() + " 个有效用户");
for (User user : validUsers) {
System.out.println("新用户: " + user);
// userService.save(user);
}
model.addAttribute("message", "成功添加 " + validUsers.size() + " 个用户");
}
return "success";
}
}
3. 创建批量编辑页面 user_edit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>批量编辑用户</title>
<style>
table {
border-collapse: collapse;
margin: 20px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background-color: #f2f2f2;
}
input[type="text"], input[type="email"] {
width: 150px;
}
</style>
</head>
<body>
<h2>批量编辑用户信息</h2>
<form action="${pageContext.request.contextPath}/user/editUsers" method="post">
<table>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>状态</th>
</tr>
<c:forEach items="${userVO.users}" var="user" varStatus="status">
<tr>
<td>
<input type="hidden" name="users[${status.index}].id" value="${user.id}"/>
${user.id}
</td>
<td>
<input type="text" name="users[${status.index}].username" value="${user.username}"/>
</td>
<td>
<input type="email" name="users[${status.index}].email" value="${user.email}"/>
</td>
<td>
<input type="checkbox" name="users[${status.index}].active"
value="true" ${user.active ? 'checked' : ''}/>
激活
</td>
</tr>
</c:forEach>
</table>
<input type="submit" value="保存修改"/>
<input type="button" value="取消" onclick="history.back()"/>
</form>
<h3>集合绑定说明</h3>
<ul>
<li>使用 users[index].property 格式绑定List集合元素</li>
<li>index 必须从0开始且连续</li>
<li>Spring MVC 会自动创建List并填充数据</li>
</ul>
</body>
</html>
4. 创建动态表单页面 user_dynamic.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>动态添加用户</title>
<script>
var userIndex = 0;
function addUserRow() {
var tbody = document.getElementById('userTableBody');
var newRow = tbody.insertRow();
newRow.innerHTML = `
<td>
<input type="text" name="users[${userIndex}].username" placeholder="用户名" required/>
</td>
<td>
<input type="email" name="users[${userIndex}].email" placeholder="邮箱"/>
</td>
<td>
<input type="password" name="users[${userIndex}].password" placeholder="密码" required/>
</td>
<td>
<button type="button" onclick="removeRow(this)">删除</button>
</td>
`;
userIndex++;
}
function removeRow(button) {
button.parentNode.parentNode.remove();
}
</script>
</head>
<body>
<h2>动态添加用户</h2>
<form action="${pageContext.request.contextPath}/user/addDynamicUsers" method="post">
<table>
<thead>
<tr>
<th>用户名</th>
<th>邮箱</th>
<th>密码</th>
<th>操作</th>
</tr>
</thead>
<tbody id="userTableBody">
<!-- 动态添加的行将插入这里 -->
</tbody>
</table>
<button type="button" onclick="addUserRow()">添加用户</button>
<input type="submit" value="提交所有用户"/>
</form>
</body>
</html>
5. 测试集合绑定
-
测试批量编辑:
- 访问:
http://localhost:8080/项目名/user/toUserEdit - 修改用户信息并提交
- 查看控制台输出
- 访问:
-
测试动态表单:
- 访问:
http://localhost:8080/项目名/user/toDynamicUserForm - 点击”添加用户”按钮动态添加多个用户
- 填写信息并提交
- 访问:
注意事项:
- List集合必须通过包装类传递
- 索引必须从0开始且连续
- 动态表单需要JavaScript配合维护索引
- 使用JSTL标签库简化JSP开发

Map绑定
Map绑定用于处理键值对数据,适用于动态属性、配置项等场景。
1. Map绑定示例
/**
* Map绑定示例
*/
@RequestMapping("/mapBinding")
public String demonstrateMapBinding(
@RequestParam Map<String, String> params, // 绑定所有请求参数
@RequestParam("config") Map<String, String> configMap) { // 绑定特定格式的参数
System.out.println("所有参数:" + params);
System.out.println("配置参数:" + configMap);
return "success";
}
/**
* 使用包装类进行Map绑定
*/
public class ConfigVO {
private Map<String, String> settings;
private Map<Integer, User> userMap;
// Getter和Setter方法
}
@RequestMapping(value = "/saveConfig", method = RequestMethod.POST)
public String saveConfiguration(ConfigVO configVO) {
Map<String, String> settings = configVO.getSettings();
if (settings != null) {
for (Map.Entry<String, String> entry : settings.entrySet()) {
System.out.println("设置项:" + entry.getKey() + " = " + entry.getValue());
}
}
return "success";
}
2. Map绑定的表单
<form action="${pageContext.request.contextPath}/config/saveConfig" method="post">
<h3>系统配置</h3>
<p>
站点名称:<input type="text" name="settings['siteName']" value="My Site"/>
</p>
<p>
站点URL:<input type="text" name="settings['siteUrl']" value="http://example.com"/>
</p>
<p>
每页显示:<input type="number" name="settings['pageSize']" value="20"/>
</p>
<p>
启用缓存:<input type="checkbox" name="settings['enableCache']" value="true"/>
</p>
<input type="submit" value="保存配置"/>
</form>
数据类型转换
内置类型转换器
Spring MVC 内置了大量的类型转换器,可以自动处理常见的类型转换:
- 基本类型和包装类:String → Integer、Long、Double、Boolean等
- 日期时间类型:String → Date、LocalDate、LocalDateTime
- 集合类型:String[] → List、Set
- 文件类型:MultipartFile
- 其他类型:Locale、Currency等
日期类型转换示例
/**
* 日期类型绑定
*/
@RequestMapping("/dateBinding")
public String handleDateBinding(
@DateTimeFormat(pattern = "yyyy-MM-dd") Date date,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate localDate,
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime dateTime) {
System.out.println("Date: " + date);
System.out.println("LocalDate: " + localDate);
System.out.println("LocalDateTime: " + dateTime);
return "success";
}
自定义类型转换器
当内置的类型转换器不能满足需求时,可以创建自定义类型转换器。
1. 实现 Converter 接口
package com.example.converter;
import org.springframework.core.convert.converter.Converter;
import com.example.domain.User;
/**
* 自定义字符串到用户对象的转换器
* 格式:"id,username,email"
*/
public class StringToUserConverter implements Converter<String, User> {
@Override
public User convert(String source) {
if (source == null || source.isEmpty()) {
return null;
}
String[] parts = source.split(",");
if (parts.length < 3) {
throw new IllegalArgumentException("Invalid user format: " + source);
}
User user = new User();
user.setId(Integer.parseInt(parts[0].trim()));
user.setUsername(parts[1].trim());
user.setEmail(parts[2].trim());
return user;
}
}
2. 注册自定义转换器
在 Spring 配置文件中注册转换器:
<!-- 配置转换服务 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.example.converter.StringToUserConverter"/>
</set>
</property>
</bean>
<!-- 将转换服务注册到 Spring MVC -->
<mvc:annotation-driven conversion-service="conversionService"/>
3. 使用自定义转换器
@RequestMapping("/customConverter")
public String testCustomConverter(
@RequestParam("user") User user) { // 自动使用 StringToUserConverter
System.out.println("转换后的用户:" + user);
return "success";
}
// 请求示例:/customConverter?user=1,john,john@example.com
数据验证
JSR-303验证
Spring MVC 支持 JSR-303(Bean Validation)标准,可以使用注解进行数据验证。
1. 添加验证依赖
<!-- Hibernate Validator (JSR-303 实现) -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.0.Final</version>
</dependency>
2. 在实体类添加验证注解
package com.example.domain;
import javax.validation.constraints.*;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 带验证注解的用户实体
*/
public class User {
private Integer id;
@NotNull(message = "用户名不能为空")
@Length(min = 3, max = 20, message = "用户名长度必须在3-20之间")
private String username;
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^(?=.*[0-9])(?=.*[a-zA-Z]).{6,20}$",
message = "密码必须包含字母和数字,长度6-20")
private String password;
@Email(message = "邮箱格式不正确")
@NotEmpty(message = "邮箱不能为空")
private String email;
@Min(value = 18, message = "年龄必须大于等于18")
@Max(value = 100, message = "年龄必须小于等于100")
private Integer age;
@Past(message = "生日必须是过去的日期")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate;
@AssertTrue(message = "必须同意服务条款")
private Boolean agreeTerms;
// Getter和Setter方法...
}
3. 在控制器中使用验证
@Controller
@RequestMapping("/validation")
public class ValidationController {
/**
* 显示注册表单
*/
@RequestMapping("/toRegister")
public String toRegister(Model model) {
model.addAttribute("user", new User());
return "validation/register";
}
/**
* 处理注册请求,带数据验证
*/
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(
@Valid @ModelAttribute User user, // @Valid 触发验证
BindingResult bindingResult, // 验证结果
Model model) {
// 检查是否有验证错误
if (bindingResult.hasErrors()) {
// 获取所有错误信息
List<FieldError> errors = bindingResult.getFieldErrors();
for (FieldError error : errors) {
System.out.println(error.getField() + ": " + error.getDefaultMessage());
}
// 返回注册页面,显示错误信息
return "validation/register";
}
// 验证通过,处理注册逻辑
System.out.println("注册用户:" + user);
model.addAttribute("message", "注册成功!");
return "success";
}
/**
* 分组验证示例
*/
public interface CreateGroup {}
public interface UpdateGroup {}
@RequestMapping("/groupValidation")
public String groupValidation(
@Validated(CreateGroup.class) User user,
BindingResult result) {
if (result.hasErrors()) {
return "validation/form";
}
return "success";
}
}
4. 显示验证错误的JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册</title>
<style>
.error {
color: red;
font-size: 12px;
}
.form-group {
margin-bottom: 15px;
}
</style>
</head>
<body>
<h2>用户注册(带验证)</h2>
<form:form modelAttribute="user"
action="${pageContext.request.contextPath}/validation/register"
method="post">
<div class="form-group">
<label>用户名:</label>
<form:input path="username"/>
<form:errors path="username" cssClass="error"/>
</div>
<div class="form-group">
<label>密码:</label>
<form:password path="password"/>
<form:errors path="password" cssClass="error"/>
</div>
<div class="form-group">
<label>邮箱:</label>
<form:input path="email"/>
<form:errors path="email" cssClass="error"/>
</div>
<div class="form-group">
<label>年龄:</label>
<form:input path="age" type="number"/>
<form:errors path="age" cssClass="error"/>
</div>
<div class="form-group">
<label>生日:</label>
<form:input path="birthDate" type="date"/>
<form:errors path="birthDate" cssClass="error"/>
</div>
<div class="form-group">
<form:checkbox path="agreeTerms"/>同意服务条款
<form:errors path="agreeTerms" cssClass="error"/>
</div>
<div class="form-group">
<input type="submit" value="注册"/>
</div>
<!-- 显示全局错误 -->
<c:if test="${not empty errors}">
<div class="error">
<c:forEach items="${errors}" var="error">
<p>${error.defaultMessage}</p>
</c:forEach>
</div>
</c:if>
</form:form>
</body>
</html>
自定义验证器
创建自定义验证注解和验证器:
/**
* 自定义验证注解:手机号验证
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
public @interface PhoneNumber {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
/**
* 手机号验证器实现
*/
public class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, String> {
private static final String PHONE_PATTERN = "^1[3-9]\\d{9}$";
@Override
public void initialize(PhoneNumber constraintAnnotation) {}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || value.isEmpty()) {
return true; // 让 @NotNull 处理空值
}
return value.matches(PHONE_PATTERN);
}
}
最佳实践
-
使用包装类型而非基本类型
- 包装类型可以处理 null 值,避免类型转换异常
- 示例:使用 Integer 而不是 int
-
合理使用 @RequestParam 注解
- 明确指定参数名称、是否必需、默认值
- 提高代码可读性和健壮性
-
统一日期格式处理
- 使用 @DateTimeFormat 注解指定日期格式
- 考虑全局配置日期格式转换器
-
数据验证分层
- 前端验证:提高用户体验
- 后端验证:确保数据安全和完整性
- 数据库约束:最后一道防线
-
合理的错误处理
- 使用 BindingResult 获取验证错误
- 提供友好的错误信息
- 考虑国际化错误消息
-
避免过度嵌套
- 嵌套层级不宜过深
- 复杂场景考虑使用DTO模式
常见问题
1. 日期绑定失败
问题:日期格式不匹配导致绑定失败
解决方案:
// 使用 @DateTimeFormat 注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate;
// 或全局配置
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
2. 中文乱码问题
问题:表单提交的中文数据出现乱码
解决方案:
- 配置字符编码过滤器(见前文 web.xml 配置)
- 确保JSP页面编码设置正确
- 检查数据库连接编码
3. 复选框绑定问题
问题:复选框未选中时不提交值
解决方案:
// 使用隐藏域技巧
<input type="hidden" name="_active" value="false"/>
<input type="checkbox" name="active" value="true"/>
// 或在实体类中设置默认值
private Boolean active = false;
4. 文件上传绑定
配置 MultipartResolver:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/> <!-- 10MB -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
控制器处理:
@RequestMapping("/upload")
public String handleFileUpload(
@RequestParam("file") MultipartFile file,
@RequestParam("description") String description) {
if (!file.isEmpty()) {
String fileName = file.getOriginalFilename();
long fileSize = file.getSize();
// 保存文件逻辑
}
return "success";
}
5. RESTful 风格参数绑定
@RequestMapping("/user/{id}")
public String getUser(@PathVariable("id") Integer userId) {
// 处理路径变量
return "user";
}
@RequestMapping("/users/{userId}/orders/{orderId}")
public String getOrder(
@PathVariable Integer userId,
@PathVariable Integer orderId) {
// 处理多个路径变量
return "order";
}
相关文章
前后章节导航
- 上一章:第十二章:Spring MVC 的核心类和注解
- 下一章:第十四章:JSON 数据和 RESTful 风格的 url