核心概念:请求参数 vs. 请求体
在开始之前,必须区分两个概念:

-
请求参数:
- 来源:通常来自 URL 的查询字符串(
?key1=value1&key2=value2)或POST请求的application/x-www-form-urlencoded格式的请求体。 - 特点:数据量通常较小,键值对形式,用于筛选、分页、排序等。
- 获取方式:通过
HttpServletRequest对象的getParameter()系列方法获取。
- 来源:通常来自 URL 的查询字符串(
-
请求体:
- 来源:
POST、PUT、PATCH等请求方法中,承载实际数据的地方。 - 特点:数据量可以很大,格式可以是 JSON、XML、纯文本、文件等。
- 获取方式:通过
HttpServletRequest对象的getInputStream()或getReader()获取原始流,然后手动解析,在框架中,通常通过@RequestBody注解自动解析。
- 来源:
使用原生 Servlet API
这是最基础的方式,适用于所有遵循 Java Servlet 规范的容器(如 Tomcat, Jetty)。
获取单个参数
request.getParameter(String name) 方法用于获取指定名称的第一个参数值。

示例:
假设请求 URL 是 http://localhost:8080/user?id=123&name=张三
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServlet extends javax.servlet.http.HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. �名为 "id" 的参数
String id = request.getParameter("id");
if (id != null) {
System.out.println("ID: " + id); // 输出: ID: 123
}
// 2. 获取名为 "name" 的参数
String name = request.getParameter("name");
if (name != null) {
System.out.println("Name: " + name); // 输出: Name: 张三
}
// 3. 如果参数不存在,getParameter() 返回 null
String email = request.getParameter("email");
System.out.println("Email: " + email); // 输出: Email: null
}
}
获取多个同名参数
当表单中有多个同名输入框(例如复选框)时,request.getParameter(String name) 只会返回第一个值,此时需要使用 getParameterValues(String name),它返回一个字符串数组。
示例:
假设请求 URL 是 http://localhost:8080/hobby?hobby=reading&hobby=music
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// 获取名为 "hobby" 的所有参数值
String[] hobbies = request.getParameterValues("hobby");
if (hobbies != null) {
System.out.println("Hobbies:");
for (String hobby : hobbies) {
System.out.println("- " + hobby); // 输出: - reading, - music
}
}
}
获取所有参数名
如果你不知道请求中会有哪些参数,可以先获取所有参数的名称,然后再遍历获取值。

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// 获取所有参数名的 Enumeration
java.util.Enumeration<String> parameterNames = request.getParameterNames();
System.out.println("All Parameters:");
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
String value = request.getParameter(name);
System.out.println(name + " = " + value);
}
}
获取所有参数到一个 Map
request.getParameterMap() 方法将所有参数名和值(第一个值)存储在一个 Map<String, String[]> 中,键是参数名,值是字符串数组。
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// 获取所有参数的 Map
java.util.Map<String, String[]> parameterMap = request.getParameterMap();
System.out.println("All Parameters in Map:");
for (java.util.Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
String name = entry.getKey();
String[] values = entry.getValue();
System.out.println(name + " = " + java.util.Arrays.toString(values));
}
}
使用 Spring MVC / Spring Boot
在现代 Java Web 开发中,我们几乎都使用 Spring 框架,它极大地简化了参数获取的过程,并且提供了更强大的功能,如数据绑定、类型转换和验证。
获取单个参数(最常用)
直接在 Controller 方法的参数列表中声明一个与请求参数名相同的参数,并加上 @RequestParam 注解,Spring 会自动从请求中获取值并绑定到该参数。
示例:
请求 URL: http://localhost:8080/user?id=123
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
public String getUser(@RequestParam("id") String userId) {
// Spring 会自动将 "id" 参数的值 "123" 赋给 userId 变量
System.out.println("User ID: " + userId); // 输出: User ID: 123
return "Hello, User " + userId;
}
}
@RequestParam 的常用属性:
value(或name): 指定请求参数的名称,如果方法参数名和请求参数名一致,可以省略。public String getUser(@RequestParam String id) { // 省略 value // ... }required: 指定该参数是否必须,默认为true,如果设置为false,当参数不存在时,Java 变量会被赋值为null(对于对象类型) 或0(对于基本类型,但会抛出HttpMessageNotReadableException,所以推荐使用包装类型)。@GetMapping("/greet") public String greet(@RequestParam(value = "name", required = false) String userName) { return "Hello, " + (userName != null ? userName : "Guest"); } // 访问 /greet 或 /greet?name=Alice 都可以defaultValue: 如果参数不存在或为空,则使用指定的默认值。@GetMapping("/page") public String getPage(@RequestParam(defaultValue = "1") int pageNum) { return "Showing page " + pageNum; } // 访问 /page 或 /page?pageNum=5 都可以
获取多个同名参数
同样使用 @RequestParam,但参数类型需要是数组或 List。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class HobbyController {
@GetMapping("/hobby")
public String getHobbies(@RequestParam("hobby") List<String> hobbies) {
// Spring 会将所有 "hobby" 参数的值收集到 List 中
System.out.println("Hobbies: " + hobbies); // 输出: Hobbies: [reading, music]
return "Your hobbies are: " + String.join(", ", hobbies);
}
}
获取整个请求体中的 JSON 数据
对于 POST/PUT 请求,尤其是发送 JSON 数据时,我们使用 @RequestBody 注解。
示例:
前端发送一个 POST 请求,Content-Type 为 application/json,请求体为:
{"username": "john", "age": 30}
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
// 定义一个与 JSON 结构匹配的 POJO (Plain Old Java Object)
class User {
private String username;
private int age;
// 必须要有无参构造器、getter 和 setter
public User() {}
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
@RestController
public class UserController {
@PostMapping("/user/create")
public String createUser(@RequestBody User user) {
// Spring 会自动将 JSON 请求体解析成 User 对象
System.out.println("Creating user: " + user.getUsername() + ", age: " + user.getAge());
return "User created successfully: " + user.getUsername();
}
}
获取路径变量
参数也可以是 URL 路径的一部分,这被称为“路径变量”或“URI 模板”,使用 @PathVariable 注解。
示例:
请求 URL: http://localhost:8080/users/123
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{userId}")
public String getUserById(@PathVariable("userId") String id) {
// Spring 会将路径中的 "123" 赋给 id 变量
System.out.println("Fetching user with ID: " + id); // 输出: Fetching user with ID: 123
return "Details for User " + id;
}
}
总结与最佳实践
| 场景 | 推荐方式 | 原生 Servlet API | Spring MVC / Spring Boot |
|---|---|---|---|
| 简单参数获取 | @RequestParam |
request.getParameter(name) |
public void method(@RequestParam String name) |
| 必选/可选参数 | @RequestParam(required = false) |
手动判断 request.getParameter(name) != null |
@RequestParam(required = false) |
| 默认值 | @RequestParam(defaultValue = "val") |
手动判断和赋值 | @RequestParam(defaultValue = "val") |
| 多选框/多值 | @RequestParam List<String> |
request.getParameterValues(name) |
public void method(@RequestParam List<String> items) |
| JSON 数据体 | @RequestBody |
手动读取 request.getInputStream() 并解析(如用 Jackson/Gson) |
public void method(@RequestBody MyObject obj) |
| URL 路径参数 | @PathVariable |
手动解析 URL 路径(不推荐) | public void method(@PathVariable String id) |
核心建议:
- 优先使用框架:除非你在编写一个非常底层的库或学习 Servlet 原理,否则请直接使用 Spring Boot,它能让你从繁琐的
HttpServletRequest操作中解放出来,专注于业务逻辑。 - 明确参数来源:始终清楚你要获取的是请求参数还是请求体,这决定了你使用
@RequestParam还是@RequestBody。 - 处理必需参数:对于关键参数,使用
@RequestParam(required = true)(默认)或提供defaultValue,这样可以尽早失败,避免后续代码因NullPointerException而出错。 - 使用 POJO:当处理复杂的 JSON 或表单数据时,创建一个对应的 Java 对象(POJO)并使用
@RequestBody或表单自动绑定,代码会非常清晰和易于维护。
