2. 基于Spring MVC实现用户注册接口

基于Spring MVC实现用户注册接口 学习卡片

接口契约:注册请求与响应结构

用户注册接口的核心是定义一份清晰的“契约”:客户端提交什么字段、服务端返回什么结构。本例约定请求体为 JSON,包含 username、password、email 三个字段;响应体统一包含 code、message、data 三部分,其中 data 在成功时返回新用户 ID,失败时为 null。

客户端 POST /api/users Content-Type: application/json 请求体 JSON { "username": "alice", "password": "P@ss1234", "email": "alice@ex.com" } UserController @RestController @PostMapping("/api/users") @RequestBody UserRegisterReq 基础校验 + 调用 Service 响应体 JSON { "code": 200, "message": "注册成功", "data": { "id": 1001 } } 基础校验失败 username 为空 password 长度 < 8 email 格式不合法 失败响应 { "code": 400, "message": "参数错误" } 请求经 @RequestBody 绑定为 Java 对象,校验通过后返回统一响应结构;校验失败返回 code=400

请求参数对象与控制器实现

Spring MVC 通过 @RequestBody 将 JSON 请求体反序列化为 Java 对象。先定义请求参数类 UserRegisterRequest,字段名与 JSON key 保持一致,Spring 默认使用 Jackson 完成映射。

public class UserRegisterRequest {
    private String username;
    private String password;
    private String email;

    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

统一响应结构使用泛型 ApiResponse<T>,便于后续接口复用:

public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;

    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> ApiResponse<T> ok(T data) {
        return new ApiResponse<>(200, "success", data);
    }

    public static <T> ApiResponse<T> fail(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }

    public int getCode() { return code; }
    public String getMessage() { return message; }
    public T getData() { return data; }
}

控制器方法使用 @RestController 与 @PostMapping 暴露接口,在方法体内完成基础校验(非空、长度、格式),校验通过后模拟生成用户 ID 并返回成功响应:

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/users")
    public ApiResponse<Map<String, Object>> register(@RequestBody UserRegisterRequest req) {
        // 基础校验:用户名非空
        if (req.getUsername() == null || req.getUsername().trim().isEmpty()) {
            return ApiResponse.fail(400, "用户名不能为空");
        }
        // 基础校验:密码长度至少 8 位
        if (req.getPassword() == null || req.getPassword().length() < 8) {
            return ApiResponse.fail(400, "密码长度不能少于8位");
        }
        // 基础校验:邮箱格式
        if (req.getEmail() == null || !req.getEmail().matches("^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")) {
            return ApiResponse.fail(400, "邮箱格式不正确");
        }

        // 模拟注册成功,生成用户 ID
        long newUserId = 1001L;
        Map<String, Object> data = new HashMap<>();
        data.put("id", newUserId);
        data.put("username", req.getUsername());

        return ApiResponse.ok(data);
    }
}

参数绑定要点:请求头必须为 Content-Type: application/json,否则 @RequestBody 无法正确反序列化。字段名大小写敏感,JSON 中的 username 对应 Java 字段 username;若需映射不同名称,可使用 @JsonProperty 注解。

验证方式与结果判读

启动项目后,使用 curl 或 Postman 发送请求验证接口行为。以下为三种典型场景的请求与预期响应:

场景 请求体 预期 HTTP 状态 预期响应 code 预期 message
注册成功 {"username":"alice","password":"P@ss1234","email":"alice@ex.com"} 200 200 success
用户名为空 {"username":"","password":"P@ss1234","email":"alice@ex.com"} 200 400 用户名不能为空
密码过短 {"username":"bob","password":"123","email":"bob@ex.com"} 200 400 密码长度不能少于8位
邮箱格式错误 {"username":"carol","password":"P@ss1234","email":"carol-at-ex"} 200 400 邮箱格式不正确

使用 curl 验证成功场景:

curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"P@ss1234","email":"alice@ex.com"}'

预期返回:

{"code":200,"message":"success","data":{"id":1001,"username":"alice"}}

注意:本例中的校验逻辑写在 Controller 方法体内,属于最基础的手工校验。当校验规则增多时,应改用 JSR 303 注解(如 @NotBlank、@Size、@Email)配合 @Valid 自动触发,并通过全局异常处理器统一返回错误格式,避免在每个接口中重复编写 if 判断。

关键点回顾

  • @RestController = @Controller + @ResponseBody,方法返回值自动序列化为 JSON。
  • @RequestBody 负责将请求体 JSON 绑定到 Java 对象,依赖 Jackson 反序列化。
  • 请求参数类字段名需与 JSON key 一致,否则绑定为 null。
  • 统一响应结构(code/message/data)便于前端统一处理成功与失败分支。
  • 基础校验可在 Controller 内手工完成,但更推荐后续使用 JSR 303 注解 + 全局异常处理。