本文目录导读:

我来为您提供一个完整的Spring Boot统一返回格式的实现案例。
项目结构
src/main/java/com/example/demo/
├── DemoApplication.java
├── common/
│ ├── Result.java // 统一返回结果类
│ ├── ResultCode.java // 返回状态码枚举
│ └── GlobalExceptionHandler.java // 全局异常处理器
├── controller/
│ └── UserController.java
├── service/
│ ├── UserService.java
│ └── impl/
│ └── UserServiceImpl.java
├── entity/
│ └── User.java
└── config/
└── WebMvcConfig.java // Web配置(可选)
统一返回结果类实现
1 状态码枚举类
package com.example.demo.common;
import lombok.Getter;
/**
* 返回状态码枚举
*/
@Getter
public enum ResultCode {
SUCCESS(200, "操作成功"),
ERROR(500, "操作失败"),
PARAM_ERROR(400, "参数错误"),
UNAUTHORIZED(401, "未认证"),
FORBIDDEN(403, "无权限"),
NOT_FOUND(404, "资源不存在"),
// 业务相关错误码
USER_NOT_EXIST(1001, "用户不存在"),
USER_ALREADY_EXIST(1002, "用户已存在"),
PASSWORD_ERROR(1003, "密码错误"),
USERNAME_ERROR(1004, "用户名错误"),
// 系统错误码
SYSTEM_ERROR(5000, "系统异常"),
DATABASE_ERROR(5001, "数据库异常");
// 状态码
private final Integer code;
// 返回消息
private final String message;
ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
}
2 统一返回结果类
package com.example.demo.common;
import lombok.Data;
import java.io.Serializable;
/**
* 统一返回结果类
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 状态码
*/
private Integer code;
/**
* 返回消息
*/
private String message;
/**
* 返回数据
*/
private T data;
/**
* 时间戳
*/
private Long timestamp;
public Result() {
this.timestamp = System.currentTimeMillis();
}
/**
* 成功返回结果
*/
public static <T> Result<T> success() {
return success(null);
}
/**
* 成功返回结果
*/
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMessage(ResultCode.SUCCESS.getMessage());
result.setData(data);
return result;
}
/**
* 成功返回结果(自定义消息)
*/
public static <T> Result<T> success(String message, T data) {
Result<T> result = new Result<>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMessage(message);
result.setData(data);
return result;
}
/**
* 失败返回结果
*/
public static <T> Result<T> error() {
return error(ResultCode.ERROR);
}
/**
* 失败返回结果(自定义信息)
*/
public static <T> Result<T> error(String message) {
return error(ResultCode.ERROR.getCode(), message);
}
/**
* 失败返回结果(使用枚举)
*/
public static <T> Result<T> error(ResultCode resultCode) {
return error(resultCode.getCode(), resultCode.getMessage());
}
/**
* 失败返回结果(自定义状态码和消息)
*/
public static <T> Result<T> error(Integer code, String message) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
return result;
}
}
3 业务异常类
package com.example.demo.common;
import lombok.Getter;
/**
* 业务异常类
*/
@Getter
public class BusinessException extends RuntimeException {
private final Integer code;
private final String message;
public BusinessException(String message) {
super(message);
this.code = ResultCode.ERROR.getCode();
this.message = message;
}
public BusinessException(ResultCode resultCode) {
super(resultCode.getMessage());
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
}
4 全局异常处理器
package com.example.demo.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
/**
* 全局异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
public Result<?> handleBusinessException(BusinessException e) {
log.error("业务异常:{}", e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
/**
* 处理参数校验异常(@RequestBody)
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
log.error("参数校验异常:{}", message);
return Result.error(ResultCode.PARAM_ERROR.getCode(), message);
}
/**
* 处理参数绑定异常
*/
@ExceptionHandler(BindException.class)
public Result<?> handleBindException(BindException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
log.error("参数绑定异常:{}", message);
return Result.error(ResultCode.PARAM_ERROR.getCode(), message);
}
/**
* 处理参数校验异常(@RequestParam)
*/
@ExceptionHandler(ConstraintViolationException.class)
public Result<?> handleConstraintViolationException(ConstraintViolationException e) {
String message = e.getConstraintViolations().stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
log.error("参数约束异常:{}", message);
return Result.error(ResultCode.PARAM_ERROR.getCode(), message);
}
/**
* 处理其他未知异常
*/
@ExceptionHandler(Exception.class)
public Result<?> handleException(Exception e) {
log.error("系统异常:", e);
return Result.error(ResultCode.SYSTEM_ERROR.getCode(), ResultCode.SYSTEM_ERROR.getMessage());
}
}
实体类
package com.example.demo.entity;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Data
public class User {
private Long id;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
@NotNull(message = "年龄不能为空")
private Integer age;
}
Controller层示例
package com.example.demo.controller;
import com.example.demo.common.Result;
import com.example.demo.entity.User;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/users")
public class UserController {
/**
* 模拟用户数据
*/
private static final Map<Long, User> USER_MAP = new HashMap<>();
static {
User user1 = new User();
user1.setId(1L);
user1.setUsername("zhangsan");
user1.setPassword("123456");
user1.setEmail("zhangsan@example.com");
user1.setAge(25);
USER_MAP.put(1L, user1);
User user2 = new User();
user2.setId(2L);
user2.setUsername("lisi");
user2.setPassword("123456");
user2.setEmail("lisi@example.com");
user2.setAge(30);
USER_MAP.put(2L, user2);
}
/**
* 查询所有用户
* GET /api/users
*/
@GetMapping
public Result<List<User>> list() {
List<User> users = new ArrayList<>(USER_MAP.values());
return Result.success(users);
}
/**
* 根据ID查询用户
* GET /api/users/{id}
*/
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id) {
User user = USER_MAP.get(id);
if (user == null) {
return Result.error("用户不存在");
}
return Result.success(user);
}
/**
* 创建用户
* POST /api/users
*/
@PostMapping
public Result<User> create(@Valid @RequestBody User user) {
// 模拟创建用户
Long id = (long) (USER_MAP.size() + 1);
user.setId(id);
USER_MAP.put(id, user);
return Result.success("创建用户成功", user);
}
/**
* 更新用户
* PUT /api/users/{id}
*/
@PutMapping("/{id}")
public Result<User> update(@PathVariable Long id, @Valid @RequestBody User user) {
if (!USER_MAP.containsKey(id)) {
return Result.error("用户不存在");
}
user.setId(id);
USER_MAP.put(id, user);
return Result.success("更新用户成功", user);
}
/**
* 删除用户
* DELETE /api/users/{id}
*/
@DeleteMapping("/{id}")
public Result<?> delete(@PathVariable Long id) {
if (!USER_MAP.containsKey(id)) {
return Result.error("用户不存在");
}
USER_MAP.remove(id);
return Result.success("删除用户成功");
}
}
Service层示例(带异常处理)
package com.example.demo.service;
import com.example.demo.common.BusinessException;
import com.example.demo.common.ResultCode;
import com.example.demo.entity.User;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserService {
private static final Map<Long, User> USER_MAP = new HashMap<>();
static {
User user1 = new User();
user1.setId(1L);
user1.setUsername("zhangsan");
user1.setPassword("123456");
user1.setEmail("zhangsan@example.com");
user1.setAge(25);
USER_MAP.put(1L, user1);
}
/**
* 查询所有用户
*/
public List<User> findAll() {
return new ArrayList<>(USER_MAP.values());
}
/**
* 根据ID查询用户
*/
public User findById(Long id) {
User user = USER_MAP.get(id);
if (user == null) {
throw new BusinessException(ResultCode.USER_NOT_EXIST);
}
return user;
}
/**
* 创建用户
*/
public User create(User user) {
// 检查用户名是否已存在
boolean exists = USER_MAP.values().stream()
.anyMatch(u -> u.getUsername().equals(user.getUsername()));
if (exists) {
throw new BusinessException(ResultCode.USER_ALREADY_EXIST);
}
Long id = (long) (USER_MAP.size() + 1);
user.setId(id);
USER_MAP.put(id, user);
return user;
}
/**
* 更新用户
*/
public User update(Long id, User user) {
if (!USER_MAP.containsKey(id)) {
throw new BusinessException(ResultCode.USER_NOT_EXIST);
}
user.setId(id);
USER_MAP.put(id, user);
return user;
}
/**
* 删除用户
*/
public void delete(Long id) {
if (!USER_MAP.containsKey(id)) {
throw new BusinessException(ResultCode.USER_NOT_EXIST);
}
USER_MAP.remove(id);
}
}
配置类(可选)
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 配置跨域(如有需要)
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.maxAge(3600);
}
}
主启动类
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
测试用例
package com.example.demo;
import com.example.demo.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
class DemoApplicationTests {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
void testGetUserById() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("操作成功"))
.andExpect(jsonPath("$.data.username").value("zhangsan"));
}
@Test
void testGetUserNotExist() throws Exception {
mockMvc.perform(get("/api/users/999"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(500))
.andExpect(jsonPath("$.message").value("用户不存在"));
}
@Test
void testCreateUser() throws Exception {
String userJson = "{\"username\":\"wangwu\",\"password\":\"123456\",\"email\":\"wangwu@example.com\",\"age\":28}";
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.data.username").value("wangwu"));
}
@Test
void testCreateUserValidation() throws Exception {
// 测试参数校验
String invalidUserJson = "{\"username\":\"w\",\"password\":\"123\",\"email\":\"invalid-email\",\"age\":-1}";
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(invalidUserJson))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(400));
}
}
在Controller中使用Service
package com.example.demo.controller;
import com.example.demo.common.Result;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
/**
* 查询所有用户
*/
@GetMapping
public Result<List<User>> list() {
return Result.success(userService.findAll());
}
/**
* 根据ID查询用户
*/
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id) {
return Result.success(userService.findById(id));
}
/**
* 创建用户
*/
@PostMapping
public Result<User> create(@Valid @RequestBody User user) {
return Result.success("创建用户成功", userService.create(user));
}
/**
* 更新用户
*/
@PutMapping("/{id}")
public Result<User> update(@PathVariable Long id, @Valid @RequestBody User user) {
return Result.success("更新用户成功", userService.update(id, user));
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public Result<?> delete(@PathVariable Long id) {
userService.delete(id);
return Result.success("删除用户成功");
}
}
响应示例
成功响应:
{
"code": 200,
"message": "操作成功",
"data": {
"id": 1,
"username": "zhangsan",
"password": "123456",
"email": "zhangsan@example.com",
"age": 25
},
"timestamp": 1700000000000
}
失败响应:
{
"code": 1001,
"message": "用户不存在",
"data": null,
"timestamp": 1700000000000
}
Maven依赖
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
使用说明
应用场景:
- 前后端分离:统一接口返回格式,方便前端处理
- API设计:统一错误码和消息格式
- 异常处理:统一异常捕获和转换
优势:
- 统一规范:所有接口返回格式一致
- 错误处理:全局异常处理,避免重复代码
- 可维护性:状态码和消息集中管理
- 扩展性:易于添加新的返回类型和状态码
注意事项:
- 状态码规划:合理规划业务状态码,避免冲突
- 异常处理:根据业务需求选择合适的异常处理方式
- 参数校验:结合
@Valid实现参数验证 - 日志记录:在异常处理器中添加日志,便于问题排查
这个实现方案涵盖了统一返回格式的完整实现,包括正常返回、异常处理、参数校验等场景,您可以根据实际需求进行调整和扩展。