Spring Boot实现统一返回格式案例

wen java案例 1

本文目录导读:

Spring Boot实现统一返回格式案例

  1. 项目结构
  2. 统一返回结果类实现
  3. 实体类
  4. Controller层示例
  5. Service层示例(带异常处理)
  6. 配置类(可选)
  7. 主启动类
  8. 测试用例
  9. 在Controller中使用Service
  10. 响应示例
  11. Maven依赖
  12. 使用说明

我来为您提供一个完整的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>

使用说明

应用场景:

  1. 前后端分离:统一接口返回格式,方便前端处理
  2. API设计:统一错误码和消息格式
  3. 异常处理:统一异常捕获和转换

优势:

  1. 统一规范:所有接口返回格式一致
  2. 错误处理:全局异常处理,避免重复代码
  3. 可维护性:状态码和消息集中管理
  4. 扩展性:易于添加新的返回类型和状态码

注意事项:

  1. 状态码规划:合理规划业务状态码,避免冲突
  2. 异常处理:根据业务需求选择合适的异常处理方式
  3. 参数校验:结合@Valid实现参数验证
  4. 日志记录:在异常处理器中添加日志,便于问题排查

这个实现方案涵盖了统一返回格式的完整实现,包括正常返回、异常处理、参数校验等场景,您可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!