文档站点
Skip to content

请求(参数绑定) ​

Laravel 的控制器方法通过 Request $request 拿到请求数据;Spring Boot 把这件事做得更「声明式」:方法签名上写什么参数,框架就帮你解析什么,不需要一个个从 $request 里取。

请求数据从哪来 ​

HTTP 请求的「数据携带点」就三个地方,Spring 各有一个注解:

数据位置Laravel 写法Spring Boot 写法
URL 路径段(/posts/{id})$request->route('id')@PathVariable Long id
URL 查询串(?page=2)$request->query('page')@RequestParam int page
请求体(JSON/表单)$request->all()@RequestBody PostDto dto

这三个注解是 Spring MVC 参数绑定的主力,必须掌握。

@PathVariable:路径参数 ​

java
@GetMapping("/posts/{id}")
public Post show(@PathVariable Long id) {
    return service.get(id);
}
  • 类型自动转换:Long id 会把字符串转成 Long,转失败抛类型异常
  • 参数名自动匹配 {id};如果方法参数名和占位符不一致,要显式指定:
java
@GetMapping("/posts/{postId}")
public Post show(@PathVariable("postId") Long id) { ... }

为什么有时要显式写名字?

Java 编译默认会把参数名丢掉(除非 -parameters)。IDEA 里「Settings → Build → Compiler → Store info about method parameters」勾上后就可以不写。项目里通常统一开启,所以示例大多直接写参数名。

@RequestParam:查询参数 ​

java
@GetMapping("/posts")
public List<Post> index(
        @RequestParam(defaultValue = "1") int page,
        @RequestParam(required = false) String keyword) {
    ...
}
属性作用
required = false可缺省(默认必填,缺了 400)
defaultValue = "1"缺省时用默认值
name / value指定参数名(区别于方法参数名)

宽松绑定

如果方法参数没有加任何注解(如 public Post show(Long id)),Spring 会智能地从「查询参数 → 路径参数 → 表单字段」里找同名数据,能自动转换就绑定。这个「宽松绑定」很方便,但团队里建议显式标注,可读性更好。

@RequestBody:JSON 请求体 ​

这是和 Laravel 差别最大的地方。Laravel 里 $request->all() 拿到的是 PHP 数组;Spring 里 @RequestBody 直接把 JSON 反序列化成你声明的 DTO 对象:

java
@PostMapping("/posts")
public Post store(@RequestBody PostDto dto) {
    return service.create(dto);
}
json
// 请求体
{ "title": "Spring Boot 入门", "content": "..." }
java
@Data
public class PostDto {
    private String title;
    private String content;
}

框架(Jackson)把 JSON 自动映射到 DTO 的字段,字段名一一对应,多余字段默认忽略。

DTO 是什么

DTO(Data Transfer Object,数据传输对象)= 定义了「请求该长什么样 / 响应该长什么样」的普通类。它扮演两个 Laravel 角色:

  • FormRequest:定义入参结构(这里是入参 DTO)
  • Resource:定义出参结构(返回 DTO) 它是 Java 世界里比 PHP 更严格的「请求体即对象」约定。

请求体里的 JSON 数组 ​

java
@PostMapping("/posts/batch")
public List<Post> batch(@RequestBody List<PostDto> dtos) { ... }

宽松模式收所有字段 ​

如果字段太多不想全声明,可以用 Map:

java
@PostMapping("/webhook")
public void webhook(@RequestBody Map<String, Object> payload) { ... }

WARNING

能不用 Map 就不用 —— 类型安全全丢了,相当于 Laravel 里到处 $request->all()。定义明确的 DTO 更安全、更可读。

完整拿 HttpServletRequest ​

需要原生请求对象时(少见),直接声明:

java
@PostMapping("/upload")
public String upload(HttpServletRequest request) {
    String token = request.getHeader("Authorization");
    String method = request.getMethod();
    String ip = request.getRemoteAddr();
    ...
}
需求LaravelSpring
请求头$request->header('X-Foo')request.getHeader("X-Foo") 或 @RequestHeader String xFoo
请求方法$request->method()request.getMethod()
客户端 IP$request->ip()request.getRemoteAddr()
上传文件$request->file('avatar')@RequestPart MultipartFile avatar(见 文件存储)

也可以用 @RequestHeader 注解直接绑定请求头:

java
@GetMapping("/info")
public String info(@RequestHeader("User-Agent") String ua) { ... }
java
@GetMapping("/cookie")
public String cookie(@CookieValue(value = "lang", defaultValue = "zh") String lang) { ... }

参数绑定对照速查 ​

场景注解类比 Laravel
路径参数@PathVariable Long id$request->route('id')
查询参数@RequestParam String kw$request->query('kw')
请求头@RequestHeader String token$request->header('token')
Cookie@CookieValue String lang$request->cookie('lang')
JSON 体@RequestBody PostDto dto$request->validate() + all()
文件@RequestPart MultipartFile f$request->file('f')

参数校验放在哪 ​

参数绑定完成后,用 @Valid 触发校验:

java
@PostMapping("/posts")
public Post store(@Valid @RequestBody PostDto dto) {
    return service.create(dto);
}

DTO 上的校验注解(类似 Laravel FormRequest::rules()):

java
@Data
public class PostDto {
    @NotBlank
    @Size(max = 100)
    private String title;

    @NotBlank
    private String content;
}

校验失败默认返回 400。如何定制错误响应、如何写更复杂的规则,见 数据校验。

面向 PHP / Laravel 开发者的 Spring Boot 中文文档