引言
轻舟采用先后端分离架构,先后端数据传输主要使用 json 格式。对 json 格式数据进行统一约定,将为 HTTP 接口对接,调试带来方便。java
格式约定
清单1:返回信息格式约定源码示例git
package site.syksy.qingzhou.web.response; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import java.io.Serializable; /** * @author Raspberry */ @Schema(title = "返回信息") public class ResponseMessage<T> implements Serializable { private static final long serialVersionUID = 1L; @Schema(title = "是否成功") private Boolean success; @Schema(title = "数据") private T data; @Schema(title = "错误码") private String errorCode; @Schema(title = "错误信息") private String errorMessage; /** * error display type: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 page */ @Schema(title = "错误信息显示类型") private Integer showType; /** * Convenient for back-end Troubleshooting: unique request ID */ @Schema(title = "惟一请求ID") private String traceId; /** * onvenient for backend Troubleshooting: host of current access server */ @Schema(title = "当前访问服务器的主机") private String host; ......省略部分代码,详细请到轻舟源码中查找...... }
ResponseMessage 类中的属性是依据 ant design pro 文档中推荐。github
统一包装
约定好先后端交互数据格式后,咱们将在每一个 HTTP 接口方法中对返回结果进行包装,但这样显得冗余。这些重复冗余的代码可否集中处理呢?固然是能够的!只需建立一个类,实现 **ResponseBodyAdvice **接口,再加上一个注解 **@RestControllerAdvice **就能实现统一对返回结果进行包装处理,具体请看清单2中的源码。web
清单2:统一包装返回信息源码示例spring
package site.syksy.qingzhou.web.response; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; /** * @author Raspberry */ @RestControllerAdvice public class GeneralResponseBodyAdvice implements ResponseBodyAdvice<Object> { private final static String PACKAGE_PATH = "site.syksy.qingzhou"; @Override public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { String className = methodParameter.getMethod().getDeclaringClass().getName(); if (className.startsWith(PACKAGE_PATH)) { return true; } else { return false; } } @Override public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if (o instanceof ResponseMessage) { return o; } if (o instanceof String) { return ResponseMessage.success(o).toJSON(); } return ResponseMessage.success(o); } }
**GeneralResponseBodyAdvice **类中的两个方法解释以下:json
- supports:经过检查 Controller 类包路径是否匹配 site.syksy.qingzhou,返回 ture ,则会执行 beforeBodyWrite 方法。
- beforeBodyWrite:先对 Controller 返回结果进行判断,是否已包装过(类型属于 ResponseMessage ),是不是 String 类型( String 类型,后续转换器不会将其转成 json)。若是以上判断皆未经过,将对结果包装成 ResponseMessage 格式。
清单2示例中经过包路径来约束,也可经过其它方式来约束。不过注意,必定要约束范围,不然如 springdoc-openapi 的接口也将包装,则访问 swagger ui 时将不能正确解析。后端
结束语
本文介绍了轻舟先后端格式的约定,以及如何实现结果统一包装。这个方案并不是完美无瑕,其中一个问题是 springdoc-openapi 生成的 swagger 文档中,返回结果未加上统一包装格式。不知是否有读者对解决这个问题感兴趣,能够给 springdoc-openapi 贡献一个pr,为开源世界添砖加瓦。api
参考文献
[1] Spring [EB/OL].https://spring.io/.2021-04-25 [2] Ant Design Pro [EB/OL].https://pro.ant.design/.2021-04-25服务器
附录
轻舟源码地址:https://gitee.com/syksy/qingzhou架构
本文由博客一文多发平台 OpenWrite 发布!