2. 基于Spring MVC实现用户注册接口
接口契约:注册请求与响应结构
用户注册接口的核心是定义一份清晰的“契约”:客户端提交什么字段、服务端返回什么结构。本例约定请求体为 JSON,包含 username、password、email 三个字段;响应体统一包含 code、message、data 三部分,其中 data 在成功时返回新用户 ID,失败时为 null。
请求参数对象与控制器实现
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 注解 + 全局异常处理。