文档站点
Skip to content

控制器 ​

Laravel 控制器是「接收请求、组织业务、返回响应」的枢纽;Spring Boot 控制器概念完全一致,区别在于:方法签名声明即绑定(参数由框架填充),返回值即响应体(由转换器序列化)。

两种控制器注解 ​

注解返回值处理使用场景
@Controller返回值走「视图解析」,或需配 @ResponseBody服务端渲染页面(Thymeleaf)
@RestController返回值直接序列化为 JSON99% 的后端接口场景
java
@RestController    // = @Controller + @ResponseBody
public class PostController { ... }

只做 API 就用 @RestController

@RestController 等价于「@Controller + 每个方法都带 @ResponseBody」。写 JSON 接口用它最省事。返回值如何变成 JSON、如何定制状态码,见 响应。

一个完整控制器 ​

java
package com.example.demo.post;

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/posts")
public class PostController {

    private final PostService service;

    public PostController(PostService service) {   // 构造器注入业务服务
        this.service = service;
    }

    @GetMapping
    public List<Post> index() {
        return service.list();
    }

    @GetMapping("/{id}")
    public Post show(@PathVariable Long id) {
        return service.get(id);
    }

    @PostMapping
    public ResponseEntity<Post> store(@Valid @RequestBody PostDto dto) {
        return ResponseEntity.status(HttpStatus.CREATED).body(service.create(dto));
    }

    @PutMapping("/{id}")
    public Post update(@PathVariable Long id, @RequestBody PostDto dto) {
        return service.update(id, dto);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> destroy(@PathVariable Long id) {
        service.delete(id);
        return ResponseEntity.noContent().build();
    }
}

对照 Laravel:

LaravelSpring Boot
public function index()public List<Post> index()
public function store(Request $request)public Post store(@RequestBody PostDto dto)
return response()->json($posts, 201)return ResponseEntity.status(201).body(...)
return response()->noContent()return ResponseEntity.noContent().build()

控制器里尽量不写业务逻辑 ​

Laravel 最佳实践是「薄控制器 + 服务层」;Spring 社区同样强调。但要注意:Java 里把逻辑抽到 Service 不只是为了整洁,更是为了让「事务注解」和「依赖注入」生效。

关键:Spring 的魔法只对容器管理的 Bean 生效

@Transactional、@Cacheable 等注解靠代理实现。PostController 是 Bean,注入的 PostService 也是 Bean,所以 service.create(dto) 里的事务注解才有效。如果你在控制器里直接 new PostService(...),注解全部失效。永远通过注入拿依赖,不要自己 new Bean。

控制器方法可以返回哪些类型 ​

返回类型结果
String纯文本 / 视图名(取决于是否 @RestController)
POJO / List<POJO>自动序列化为 JSON
Map / List直接当 JSON 用(临时结构)
ResponseEntity<T>完整控制状态码 + 头 + 体
void配合 HttpServletResponse 手动写
java
@GetMapping("/stats")
public Map<String, Object> stats() {
    return Map.of("posts", 100, "users", 50);
}

TIP

临时返回 Map 很方便,但对外 API 建议用 DTO(PostDto),字段名、可空性可控,还能加 @JsonProperty 定制输出名。见 JPA 序列化与 DTO。

处理依赖:构造器注入 ​

java
@RestController
public class PostController {
    private final PostService service;

    public PostController(PostService service) {
        this.service = service;
    }
}

Spring 自动把 PostService 单例注入进来。等价于 Laravel 控制器构造函数里 app(PostService::class)。

服务层(Service)对应 Laravel 的哪一层? ​

LaravelSpring Boot
app/Services/PostService.php@Service public class PostService
控制器 -> PostService控制器注入 PostService
java
@Service
public class PostService {
    private final PostRepository repository;

    public PostService(PostRepository repository) {
        this.repository = repository;
    }

    @Transactional
    public Post create(PostDto dto) {
        return repository.save(dto.toEntity());
    }
}

常用姿势速查 ​

需求写法
注入 Service构造器注入(推荐)
返回 201ResponseEntity.status(HttpStatus.CREATED)
返回 204ResponseEntity.noContent().build()
返回 404throw new NotFoundException(...),交给全局异常处理器(见 异常处理)
拿请求体@RequestBody PostDto dto
拿路径参数@PathVariable Long id
拿查询参数@RequestParam String keyword
校验请求体@Valid @RequestBody PostDto dto

下一节,把「参数绑定」彻底讲透:请求(参数绑定)。

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