控制器方法的参数非常灵活,Spring MVC 通过强大的 HandlerMethodArgumentResolver(参数解析器)机制来自动将 HTTP 请求中的数据绑定到方法参数上。
下面我将参数类型分为几大类,并附上示例和说明。
核心基础类型
这是最常用、最基础的参数类型,直接接收请求中的简单数据。
HttpServletRequest / HttpServletResponse
直接获取原生 Servlet API 的请求和响应对象。
@GetMapping("/api/request-info")
public String getRequestInfo(HttpServletRequest request, HttpServletResponse response) {
String userAgent = request.getHeader("User-Agent");
response.setHeader("Custom-Header", "MyValue");
return "User Agent: " + userAgent;
}
HttpSession
用于获取和操作会话(Session)。
@GetMapping("/api/session")
public String getSessionInfo(HttpSession session) {
// 从 session 中获取用户ID,如果不存在则设置一个
Object userId = session.getAttribute("userId");
if (userId == null) {
session.setAttribute("userId", "12345");
return "Session created for user 12345.";
}
return "Current user ID in session: " + userId;
}
java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap
用于向视图(View)传递数据,主要用于返回页面(@Controller)。
Model: Spring 提供的接口,推荐使用。ModelMap:Model的实现类。Map: 也可以,但功能不如Model丰富。
@GetMapping("/hello")
public String helloPage(Model model) {
model.addAttribute("name", "World");
model.addAttribute("currentTime", new Date());
// 返回视图名,Spring 会解析为 "hello.html" 或类似模板
return "hello";
}
在 Thymeleaf 模板 hello.html 中就可以使用 ${name} 和 ${currentTime}。
@PathVariable (路径变量)
用于获取 URL 路径中的变量。
// 请求 URL: /api/users/123
@GetMapping("/api/users/{userId}")
public String getUserById(@PathVariable("userId") String id) {
return "User ID: " + id; // 输出: User ID: 123
}
- 如果变量名和方法参数名一致,可以省略
value:@PathVariable String userId。 - 可以指定类型,Spring 会自动转换:
@PathVariable Long userId。
@RequestParam (请求参数)
用于获取 URL 查询参数(?key=value)或表单数据。
// 请求 URL: /api/search?name=John&age=30
@GetMapping("/api/search")
public String search(@RequestParam("name") String userName,
@RequestParam(required = false, defaultValue = "18") int age) {
return "Searching for: " + userName + ", Age: " + age;
}
name: 参数名,与 URL 中的key对应。required: 是否为必需参数,默认为true,如果为true且参数不存在,会抛出MissingServletRequestParameterException。defaultValue: 如果参数不存在或为空,则使用默认值。
接收多个值(如复选框)
// 请求 URL: /api/hobbies?hobbies=reading&hobbies=sports
@GetMapping("/api/hobbies")
public String getHobbies(@RequestParam("hobbies") List<String> hobbies) {
return "Your hobbies are: " + hobbies; // 输出: [reading, sports]
}
@RequestBody (请求体)
用于接收 HTTP 请求体中的 JSON/XML 数据,通常用于 POST/PUT 请求。必须配合 @RestController 或 @ResponseBody 使用。
使用前,需要确保有 JSON 解析库(如 Jackson)的依赖,Spring Boot 默认已包含。
// 前端发送 POST 请求,Content-Type: application/json
// 请求体: {"username": "jack", "password": "123456"}
@PostMapping("/api/users")
public String createUser(@RequestBody User user) { // User 是一个自定义的 Java 类
// Spring 会自动将 JSON 字符串解析成 User 对象
System.out.println("Creating user: " + user.getUsername());
return "User created successfully: " + user.getUsername();
}
User.java 示例:
public class User {
private String username;
private String password;
// Getters and Setters...
}
@RequestHeader (请求头)
用于获取 HTTP 请求头中的信息。
@GetMapping("/api/headers")
public String getHeaders(@RequestHeader("User-Agent") String userAgent,
@RequestHeader(value = "Accept", defaultValue = "*/*") String accept) {
return "User-Agent: " + userAgent + ", Accept: " + accept;
}
@CookieValue (Cookie)
用于获取指定的 Cookie 值。
@GetMapping("/api/cookie")
public String getCookie(@CookieValue("JSESSIONID") String sessionId) {
return "Session ID from Cookie: " + sessionId;
}
复杂对象类型
接收整个表单(@ModelAttribute)
当表单字段和 Java 对象的属性名一致时,Spring 会自动进行数据绑定(类型转换、封装),它也可以像 Model 一样向视图添加数据。
- 在
@Controller中,常用于表单提交的 GET 请求(展示表单)和 POST 请求(处理表单)。 - 在
@RestController中,作用与@RequestParam类似,用于接收x-www-form-urlencoded格式的数据。
// 请求 URL: /api/register?username=John&email=john@example.com
@GetMapping("/api/register")
public String showRegistrationForm(@ModelAttribute("user") User user) {
// user 对象已经被填充了 username 和 email 属性
// 这个对象也可以在视图中使用
return "registration-form";
}
@PostMapping("/api/register")
public String processRegistration(@ModelAttribute User user) {
// 处理 user 对象...
return "redirect:/success";
}
User.java 示例:
public class User {
private String username;
private String email;
// Getters and Setters...
}
Spring Web 特殊类型
org.springframework.web.servlet.ModelAndView
这是一个非常传统的对象,它既可以包含要渲染的数据(Model 部分),也可以指定要跳转的视图(View 部分)。
@GetMapping("/api/mav")
public ModelAndView modelAndView() {
ModelAndView mav = new ModelAndView();
mav.addObject("message", "Hello from ModelAndView");
mav.setViewName("hello"); // 设置视图名
return mav;
}
java.io.InputStream / java.io.Reader
直接获取请求体的输入流,用于处理文件上传或原始数据流。
@PostMapping("/api/upload")
public String uploadFile(InputStream inputStream) throws IOException {
// 可以直接读取 inputStream 中的内容
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
// 处理数据...
}
return "File uploaded successfully.";
}
org.springframework.http.ResponseEntity
这是 @RestController 中最常用的返回类型之一,它允许你完全控制 HTTP 响应,包括状态码、响应头和响应体。
@GetMapping("/api/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
// 模拟从数据库查找用户
if (id == 1L) {
User user = new User("Alice", "alice@example.com");
return ResponseEntity.ok(user); // 返回 200 OK 和用户对象
} else {
return ResponseEntity.notFound().build(); // 返回 404 Not Found
}
}
@PostMapping("/api/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
// 模拟创建用户
user.setId(1L);
return ResponseEntity.status(HttpStatus.CREATED).body(user); // 返回 201 Created
}
org.springframework.http.HttpEntity
与 ResponseEntity 类似,但它主要用于接收请求,可以同时获取请求体和请求头。
@PostMapping("/api/echo")
public String echo(@RequestBody HttpEntity<String> httpEntity) {
String body = httpEntity.getBody();
HttpHeaders headers = httpEntity.getHeaders();
return "Body: " + body + "\nHeaders: " + headers;
}
MultipartFile (文件上传)
这是处理文件上传的专用类型。
添加依赖
在 pom.xml 中添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(Spring Boot Web starter 已经包含了所需的一切)
配置文件上传
在 application.properties 或 application.yml 中设置:
# 单个文件最大大小 spring.servlet.multipart.max-file-size=10MB # 总请求最大大小 spring.servlet.multipart.max-request-size=10MB
编写控制器
import org.springframework.web.multipart.MultipartFile;
@PostMapping("/api/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "Please select a file to upload.";
}
try {
// 获取文件名
String fileName = file.getOriginalFilename();
// 保存文件到服务器...
// Files.write(Paths.get("/uploads/" + fileName), file.getBytes());
return "You successfully uploaded '" + fileName + "'";
} catch (IOException e) {
return "Failed to upload file: " + e.getMessage();
}
}
前端表单必须设置 enctype="multipart/form-data"。
总结表格
| 参数类型/注解 | 作用 | 适用场景 | 示例 |
|---|---|---|---|
HttpServletRequest |
获取原生请求对象 | 获取请求头、Session、输入流等 | public void method(HttpServletRequest req) |
HttpSession |
获取会话对象 | 管理用户登录状态等 | public void method(HttpSession session) |
Model |
向视图传递数据 | @Controller 返回页面时 |
public String method(Model model) |
@PathVariable |
获取 URL 路径变量 | RESTful API 设计 | @GetMapping("/users/{id}") |
@RequestParam |
获取 URL 查询参数或表单数据 | 搜索、分页、筛选 | @GetMapping("/search?name={name}") |
@RequestBody |
获取请求体中的 JSON/XML 数据 | 接收复杂对象,POST/PUT 请求 | @PostMapping("/users") |
@RequestHeader |
获取请求头信息 | 获取 User-Agent, Authorization 等 | @GetMapping("/api") |
@CookieValue |
获取 Cookie 值 | 处理客户端状态 | @GetMapping("/home") |
@ModelAttribute |
绑定表单数据到对象 | 表单提交(GET/POST) | @PostMapping("/register") |
ResponseEntity |
构建完整的 HTTP 响应 | @RestController 中精确控制响应 |
return ResponseEntity.ok(user); |
MultipartFile |
处理文件上传 | 上传图片、文档等 | @PostMapping("/upload") |
掌握这些参数类型,你就可以灵活地处理几乎所有的 Web 请求了,在实际开发中,@PathVariable、@RequestParam、@RequestBody 和 ResponseEntity 是使用频率最高的。
