在 Spring Boot 项目中写出“优雅的 Controller”意味着代码清晰、结构规范、责任明确、异常处理完善、接口文档清晰,同时遵循一些业界最佳实践。以下是编写优雅 Controller 的全面指南。
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUserById(@PathVariable Long id) {
UserDto user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<Void> createUser(@Valid @RequestBody UserCreateRequest request) {
userService.createUser(request);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Map
、String
)定义统一响应类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class R<T> {
private int code;
private String message;
private T data;
public static <T> R<T> ok(T data) {
return new R<>(200, "success", data);
}
public static R<Void> error(String message) {
return new R<>(500, message, null);
}
}
Controller 使用:
@GetMapping("/{id}")
public R<UserDto> getUser(@PathVariable Long id) {
return R.ok(userService.getUserById(id));
}
@Valid
/ @Validated
)@PostMapping
public R<Void> save(@Valid @RequestBody UserCreateRequest request) {
userService.save(request);
return R.ok(null);
}
DTO 示例:
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
}
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Void> handleValidationException(MethodArgumentNotValidException ex) {
String errorMsg = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return R.error(errorMsg);
}
@ExceptionHandler(BizException.class)
public R<Void> handleBizException(BizException ex) {
return R.error(ex.getMessage());
}
@ExceptionHandler(Exception.class)
public R<Void> handleOtherExceptions(Exception ex) {
// log error
return R.error("服务器内部错误");
}
}
这样做的好处是单元测试、维护都方便。
@RequestParam
、@PathVariable
、@RequestBody
语义清晰注解 | 说明 |
---|---|
@RequestParam |
URL 参数 |
@PathVariable |
URL 路径中的参数 |
@RequestBody |
JSON 请求体 |
例:
@GetMapping("/search")
public R<List<UserDto>> search(@RequestParam String keyword) {...}
@GetMapping("/{id}")
public R<UserDto> detail(@PathVariable Long id) {...}
@PostMapping
public R<Void> create(@RequestBody @Valid UserCreateRequest request) {...}
@Operation(summary = "创建用户", description = "传入用户信息进行创建")
@PostMapping
public R<Void> createUser(@Valid @RequestBody UserCreateRequest request) {
...
}
配合 Springdoc-OpenAPI 使用:
<dependency>
<groupId>org.springdocgroupId>
<artifactId>springdoc-openapi-starter-webmvc-uiartifactId>
<version>2.0.4version>
dependency>
访问地址:http://localhost:8080/swagger-ui.html
分页响应结构建议封装:
@Data
public class PageResult<T> {
private long total;
private List<T> list;
public PageResult(Page<?> page) {
this.total = page.getTotal();
this.list = page.getRecords();
}
}
Controller 示例:
@GetMapping("/page")
public R<PageResult<UserDto>> pageQuery(@Valid PageRequest request) {
Page<UserDto> page = userService.pageQuery(request);
return R.ok(new PageResult<>(page));
}
“优雅的 Controller = 少逻辑、多转发、返回一致、参数可校验、异常有处理、文档可生成”