springboot项目如何写出优雅的controller?

在 Spring Boot 项目中写出“优雅的 Controller”意味着代码清晰、结构规范、责任明确、异常处理完善、接口文档清晰,同时遵循一些业界最佳实践。以下是编写优雅 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();
    }
}

✅ 二、最佳实践详解

1. 接口返回结构统一(避免直接返回 MapString

定义统一响应类:

@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));
}

2. ✅ 参数校验(@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;
}

3. ✅ 异常统一处理(全局异常处理器)

@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("服务器内部错误");
    }
}

4. ✅ 明确职责划分(Controller 只做转发)

  • Controller:只处理请求、调用 Service、返回结果
  • Service:处理业务逻辑
  • Repository/Mapper:数据访问

这样做的好处是单元测试、维护都方便。


5. ✅ 使用 @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) {...}

6. ✅ 增加接口文档支持(Swagger/OpenAPI)

@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


7. ✅ 分页查询结构统一

分页响应结构建议封装:

@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 = 少逻辑、多转发、返回一致、参数可校验、异常有处理、文档可生成”


你可能感兴趣的:(#,Spring,#,后端面试题,spring,boot,后端)