ServerResponse(服务器统一响应数据格式)

本文介绍了ServerResponse作为服务器统一响应数据格式的设计过程,从最初简单的返回数据到包含状态码、错误信息的逐步演进。在SpringCloud的Feign调用中遇到的反序列化问题以及解决方案。强调了最佳实践不一定适用于每个项目,需要根据实际需求进行调整和优化。
摘要由CSDN通过智能技术生成

场景:

这个场景我真的觉得只要写过接口的,都需要这个。

其实,在刚刚接触代码的时候,看到大佬接口返回的JSON。JSON里面除了必要的data外,还有各种状态码,状态说明什么的,感觉很厉害。后来渐渐明白了,这个东西是必须的,你不写试试,看与你交互的大佬会不会把你拍成肉饼。
演进:
1.直接返回请求的数据:

后端:呀,前端发来的这个请求,数据库没有对应数据啊。返回一个null吧。

前端:大哥,你返回给我一个null,是不是接口有问题啊?

后端:那是你请求的数据在数据库中没有。

前端:哦。那我知道了。

后端:呀,前端发来的这个请求,参数不对啊(可能必要参数为空什么的)。我要返回null。

前端:大哥,你给我返回个null,是数据库没有对应数据嘛?但是这个条件应该有数据啊。

后端:不是的,你请求的参数有问题啊。

前端:大哥,那你倒是给我要给回馈啊。否则,我还以为是你接口没数据呢。

后端:好的吧。让我想想。
2.返回一个对象ResultVo(包含data与code,data为请求的数据,code为状态码):

后端:嘿,兄弟。我想到了一个好办法,我写了一个ResultVo,它是这样的……%¥&¥……。

前端:好的。我了解了。

后端:呀,前端发来的这个请求,没有足够的权限啊。我要返回data=null&code=10。然后在常量表中设置一下。

前端:我刚刚无意间发现,你的code又增加了10,什么意思?

后端:啊。忘了告诉你了。code=10表示权限不足。

前端:那我需要就这个情况,给用户提供专门的说明呀。

后端:这样效率太低了。而且以后可能会有更复杂多变的情况。我得想想办法。
3.返回一个对象ResultVo2(新增msg属性,充当响应的说明):

后端:嘿,兄弟。我将原来的ResultVo进行了升级,它是这样的&……%&%&……。

前端:这挺不错的,以后很多地方,我可以直接显示msg就行了。但是,现在有一个问题,现在的code太多了。我每次进行处理时都要遍历判断,而我常常只需要判断这个响应是否成功了。

后端:这样啊。我还得再改进一下。
4.ServerResponse:

后端:请教大佬后,我得到了非常棒的解决方案。并且,我根据自己的业务情况,进行细微的调整,这下就没什么问题了。

前端&后端:我们感受到了效率的显著提升,以及最为重要的代码规范(契约)。
作用:

ServerResponse就是用来统一服务器接口调用的响应
代码:

package tech.jarry.learning;


import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonSerialize;

import java.io.Serializable;

/**
 * @Author: jarry
 */
// 确保序列化JSON时,如果是null对象,其key也会消失。
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
// 生成无参构造,确保在RPC调用时,不会出现反序列失败
@NoArgsConstructor
public class ServerResponse<T> implements Serializable {

	private int status;
	private String msg;
	private T data;

	private ServerResponse(int status) {
		this.status = status;
	}

	private ServerResponse(int status, String msg) {
		this.status = status;
		this.msg = msg;
	}

	//  这里存在一个问题,如果构造函数传入的参数列表为(int,String),那么是调用上面的(int,String),还是这里的(int,T),毕竟T作为泛型是可以表示String的
	//  答案是调用上面的(int,String)(可以理解为上面的是专业的)。那么有时候data作为T类型传入的就是String啊,岂不是就出问题了。这里会在下方对应的public函数处理
	private ServerResponse(int status, T data) {
		this.status = status;
		this.data = data;
	}

	private ServerResponse(int status, String msg, T data) {
		this.status = status;
		this.msg = msg;
		this.data = data;
	}

	//    使之不在JSON序列化结果当中
	@JsonIgnore
	// 可以快速进行成功与否的条件判断
	public boolean isSuccess() {
		return this.status == ResponseCode.SUCCESS.getCode();
	}

	@JsonIgnore
	// 可以快速进行成功与否的条件判断,判断false时,不用加!。囧
	public boolean isFail() {
		return this.status != ResponseCode.SUCCESS.getCode();
	}

	public int getStatus() {
		return status;
	}

	public String getMsg() {
		return msg;
	}

	public T getData() {
		return data;
	}

	// 快速构建返回结果
	//    成功时的调用
	public static <T> ServerResponse<T> createBySuccess() {
		return new ServerResponse<T>(ResponseCode.SUCCESS.getCode());
	}

	public static <T> ServerResponse<T> createBySuccessMessage(String msg) {
		return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), msg);
	}

	public static <T> ServerResponse<T> createBySuccess(T data) {
		return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), data);
	}

	public static <T> ServerResponse<T> createBySuccess(String msg, T data) {
		return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), msg, data);
	}

	//    失败时的调用
	public static <T> ServerResponse<T> createByError() {
		return new ServerResponse<T>(ResponseCode.ERROR.getCode(), ResponseCode.ERROR.getDesc());
	}

	public static <T> ServerResponse<T> createByErrorMessage(String errorMessage) {
		return new ServerResponse<T>(ResponseCode.ERROR.getCode(), errorMessage);
	}

	public static <T> ServerResponse<T> createByErrorCodeMessage(int errorCode, String errorMessage) {
		return new ServerResponse<T>(errorCode, errorMessage);
	}
}

依赖:

lombok

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值