作为一个前后端分离项目,必须要和前端规定统一的数据交互结构,这样可以更加清晰地进行前后端数据的通信。
统一响应结构体
在项目中,应该对响应给前端的 JSON 数据的格式进行统一的规定,在很多响应结构中,一般会包含 code、message、data 三个属性。
其中 code 代表状态码,这个不是 HTTP 的响应状态码,而是后端系统的业务状态码,代表了后端响应给前端的业务状态。
message 代表了后端给前端的响应信息,如果发生异常,或者系统错误,会将错误信息存储在 message 中,响应给前端。
data 代表了后端响应给前端的数据,如果请求获取了数据,会将数据放入 data 域中。
JsonUtils
JsonUtils 是对 Json 格式化工具的封装,这样封装的好处在于,一个是可以使 API 更加直观,另外则是可以在封装的工具类中添加系统自身的操作,尽可能地兼容本身的系统业务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
| @Slf4j @RequiredArgsConstructor @Component public class JsonUtils {
private final ObjectMapper objectMapper;
public String toJson(final Object object) { if (ObjectUtils.isEmpty(object)) { log.info("[Json工具类]对象{}为空", object); return null; } if (object.getClass() == String.class) { return object.toString(); } try { return objectMapper.writeValueAsString(object); } catch (JsonProcessingException e) { log.error("[Json工具类]将对象{}格式化为JSON格式的字符串失败", object); e.printStackTrace(); } return null; }
public <T> T toObject(final String json, final Class<T> classType) { if (StringUtils.isBlank(json)) { log.info("[Json工具类]JSON字符串{}为空", json); return null; } try { return objectMapper.readValue(json, classType); } catch (JsonProcessingException e) { log.error("[Json工具类]将JSON格式的字符串{}格式化为{}类型的Java对象失败", json, classType); e.printStackTrace(); } return null; }
public <T> T toObject(final HttpServletRequest request, final Class<T> classType) { try { return objectMapper.readValue(request.getInputStream(), classType); } catch (IOException e) { log.error("[Json工具类]将输入流{}格式化为{}类型的Java对象失败", request, classType); e.printStackTrace(); } return null; }
public <T> T toObject(final InputStream inputStream, final Class<T> classType) { try { return objectMapper.readValue(inputStream, classType); } catch (IOException e) { log.error("[Json工具类]将输入流{}格式化为{}类型的Java对象失败", inputStream, classType); e.printStackTrace(); } return null; }
public Map toMap(final String json) { if (StringUtils.isBlank(json)) { log.info("[Json工具类]JSON字符串{}为空", json); return null; } try { return objectMapper.readValue(json, Map.class); } catch (JsonProcessingException e) { log.error("[Json工具类]将JSON格式的字符串{}格式化为Map类型的Java对象失败", json); e.printStackTrace(); } return null; }
public Map toMap(final Object object) { if (ObjectUtils.isEmpty(object)) { log.info("[Json工具类]对象{}为空", object); return null; } String json = toJson(object); return toMap(json); } }
|
ResponseUtils
ResponseUtils 工具类是对响应过程的封装,可以将一个 Java 对象转换为一个 JSON 格式的字符串响应给前端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Slf4j @RequiredArgsConstructor @Component public class ResponseUtils {
private final JsonUtils jsonUtils;
public void responseJson(HttpServletResponse response, Object object) throws IOException { response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding(EncodingEnums.UTF_8.getValue()); PrintWriter writer = response.getWriter(); writer.write(jsonUtils.toJson(object)); writer.flush(); writer.close(); }
}
|
响应状态码
1 2 3 4 5 6 7 8 9 10
| @Getter @AllArgsConstructor public enum CodeEnum {
OK(20000);
private final Integer value; }
|
响应结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| @ApiModel(value = "响应数据实体类") @Data public class ResponseData<T> implements Serializable {
@ApiModelProperty(value = "业务状态码") private Integer code;
@ApiModelProperty(value = "业务提示消息") private String message;
@ApiModelProperty(value = "业务响应数据") private T data;
private static ResponseData responseData;
private ResponseData() { }
public static <T> ResponseData<T> code(Integer code) { responseData = new ResponseData(); responseData.setCode(code); return responseData; }
public <T> ResponseData<T> message(String message) { responseData.setMessage(message); return responseData; }
public <T> ResponseData<T> data(T data) { responseData.setData(data); return responseData; }
public static <T> ResponseData<T> ok() { return code(CodeEnum.OK.getValue()); }
public static <T> ResponseData<T> ok(T data) { return ok().data(data); }
}
|
统一响应结构体代码示例
1 2 3 4 5 6 7 8
| @GetMapping("page/{currentPage}") public ResponseData<IPage<User>> page( @PathVariable("currentPage") Integer currentPage, @RequestParam(value = "size", defaultValue = "10") Integer size, User queryUser) throws Exception { IPage<User> page = baseService.page(currentPage, size, queryUser); return ResponseData.ok(page); }
|
1 2 3 4 5 6 7
| @PutMapping("enabled/{id}") public ResponseData<Void> enabled( @PathVariable("id") Integer id, @RequestParam("enabled") Boolean enabled) throws Exception { baseService.enabled(id, enabled); return ResponseData.ok().message("更新用户状态成功"); }
|
最后
本文Github https://github.com/herenpeng/code-learn 已收录,欢迎Star。