<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: JavaPub</title>
    <description>The latest articles on Forem by JavaPub (@javapub).</description>
    <link>https://forem.com/javapub</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1690676%2F8563f5a7-eee4-4519-a1d9-9c6e54e820fe.jpeg</url>
      <title>Forem: JavaPub</title>
      <link>https://forem.com/javapub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/javapub"/>
    <language>en</language>
    <item>
      <title>程序员在企业中是如何做需求的</title>
      <dc:creator>JavaPub</dc:creator>
      <pubDate>Thu, 27 Jun 2024 02:19:11 +0000</pubDate>
      <link>https://forem.com/javapub/cheng-xu-yuan-zai-qi-ye-zhong-shi-ru-he-zuo-xu-qiu-de-3g6a</link>
      <guid>https://forem.com/javapub/cheng-xu-yuan-zai-qi-ye-zhong-shi-ru-he-zuo-xu-qiu-de-3g6a</guid>
      <description>&lt;p&gt;在后端接口封装中，我们一般都会对返回的数据做一个封装，以防止系统出现不可预期的数据结构和类型。比如这样：&lt;/p&gt;

&lt;p&gt;结构体 1&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "success": true,&lt;br&gt;
  "code": 200,&lt;br&gt;
  "message": "成功",&lt;br&gt;
  "data": {&lt;br&gt;
    "items": [&lt;br&gt;
      {&lt;br&gt;
        "id": "1",&lt;br&gt;
        "name": "小王",&lt;br&gt;
        "identified": "JavaPub博主"&lt;br&gt;
      }&lt;br&gt;
    ]&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
结构体 2&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "ret": 200,&lt;br&gt;
    "data": {&lt;br&gt;
        "title": "Default Api",&lt;br&gt;
        "content": "王哥 您好，欢迎使用 apifather!",&lt;br&gt;
        "version": "1.1.0",&lt;br&gt;
        "time": 14231428021&lt;br&gt;
    },&lt;br&gt;
    "msg": ""&lt;br&gt;
}&lt;br&gt;
不论如何定义，多一个或少一个字段，我们都需要统一规范。接下来我们拆解一下，&lt;/p&gt;

&lt;p&gt;首先，通过观察，一定要有状态码，也就是案例中的 code 和 ret ，通过状态码可以知道当前程序哪里出了问题，比如 200 就是成功。有同学会问，为何不用 data 来判断，为空或者为 0 就是错误，当然不行。&lt;/p&gt;

&lt;p&gt;比如：下面这个结构，data 长度虽然等于 0，但是这属于确实没查到数据，而不是程序出错。&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "ret": 200,&lt;br&gt;
    "data": [],&lt;br&gt;
    "msg": ""&lt;br&gt;
}&lt;br&gt;
再看 data，这个毋庸置疑，它是接口的核心数据，也是接口对外提供的业务数据。&lt;/p&gt;

&lt;p&gt;再看 message 或者称为 msg，它是给状态做一个文字说明。比如，有个老六在定义了一个状态码（666），第一次调用这个接口的同学可能并不知道返回的状态码含义、也不想去查接口文档，我加个描述：（老六的接口不通啦），调用者就一目了然了。&lt;/p&gt;

&lt;p&gt;最后看 success 字段，这个字段是为了更规范而加的，方便前端直接将接口响应状态展示。比如：用户登录成功，可以展示一个 true，或者前端在判断时也可以写更简洁的代码 if result.success:。毕竟将（老六的接口不通啦）描述直接展示出来显得不太正式。&lt;/p&gt;

&lt;p&gt;基于以上几点，我们的返回结构这样定义：&lt;/p&gt;

&lt;p&gt;ApiResponse.class&lt;/p&gt;

&lt;p&gt;// 定义API响应结构体&lt;br&gt;
public class ApiResponse {&lt;br&gt;
    private int status; // HTTP状态码&lt;br&gt;
    private String message; // 状态信息&lt;br&gt;
    private T data; // 返回的数据，泛型支持返回不同类型的数据&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 构造函数
public ApiResponse(ResponseStatus status) {
    this.status = status.getCode();
    this.message = status.getMessage();
}

// 带数据的构造函数
public ApiResponse(ResponseStatus status, T data) {
    this(status);
    this.data = data;
}

// Getter和Setter方法
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
定义完返回结构后，我们需要定义状态的枚举值。这是为了定一个统一的规范，方便开发时状态码搞混。&lt;/p&gt;

&lt;p&gt;// 定义状态码枚举&lt;br&gt;
public enum ResponseStatus {&lt;br&gt;
    SUCCESS(200, "操作成功"),&lt;br&gt;
    ERROR(500, "服务器内部错误"),&lt;br&gt;
    BAD_REQUEST(400, "请求参数错误"),&lt;br&gt;
    NOT_FOUND(404, "资源未找到"),&lt;br&gt;
    UNAUTHORIZED(401, "未授权"),&lt;br&gt;
    FORBIDDEN(403, "禁止访问");&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private final int code;
private final String message;

ResponseStatus(int code, String message) {
    this.code = code;
    this.message = message;
}

public int getCode() {
    return code;
}

public String getMessage() {
    return message;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
如何使用呢&lt;/p&gt;

&lt;p&gt;@GetMapping("/users/{id}")&lt;br&gt;
public ResponseEntity&amp;gt; getUser(@PathVariable Long id) {&lt;br&gt;
    try {&lt;br&gt;
        User user = userService.getUserById(id);&lt;br&gt;
        if (user != null) {&lt;br&gt;
            return ResponseEntity.ok(new ApiResponse&amp;lt;&amp;gt;(ResponseStatus.SUCCESS, user));&lt;br&gt;
        } else {&lt;br&gt;
            return ResponseEntity.status(HttpStatus.NOT_FOUND)&lt;br&gt;
                                 .body(new ApiResponse&amp;lt;&amp;gt;(ResponseStatus.NOT_FOUND));&lt;br&gt;
        }&lt;br&gt;
    } catch (Exception e) {&lt;br&gt;
        // 这里可以根据异常类型返回不同的错误状态码和消息&lt;br&gt;
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)&lt;br&gt;
                             .body(new ApiResponse&amp;lt;&amp;gt;(ResponseStatus.ERROR));&lt;br&gt;
    }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;这里使用了 Spring 自带的返回结构体 ResponseEntity 进行封装。&lt;/p&gt;

&lt;p&gt;获取到的结果是这样的：&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "code": 200,&lt;br&gt;
  "message": "操作成功",&lt;br&gt;
  "data": {&lt;br&gt;
    "id": "1",&lt;br&gt;
    "name": "javapub",&lt;br&gt;
    "age": 18&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;原文地址：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javapub.net.cn/star/project/user-center/"&gt;https://javapub.net.cn/star/project/user-center/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>用户中心项目组</category>
      <category>java</category>
    </item>
  </channel>
</rss>
