封装响应结果
当服务器端向客户端响应数据时,除了必要的提示文本以外,还应该响应“业务状态码”到客户端,以便于客户端程序能够便捷且准确的判断当前请求的执行结果!
另外,某些操作是需要向客户端响应数据的
所以,向客户端的响应数据至少需要包含以下部分:
- 业务状态码:本质上是一个数值,由服务器端和客户端共同约定每个数值的意义
- 业务执行出错时的描述文本
- 数据:当处理请求成功时,可能需要响应某些数据到客户端(通常是客户端发起GET请求,当然,某些POST请求可能也需要响应数据)
以上做法应该是针对所有请求都是如此响应的,通常,会自定义某个类型,用于封装以上3种数据,作为处理请求的方法的返回值类型,当响应时,Spring MVC框架会将返回值转换成JSON格式的字符串!
提示:Spring MVC能够将处理请求的方法的返回值转换成JSON格式的字符串,需要:
- 此方法是响应正文的
- 此项目中需要添加
jackson-databind
依赖
- 在Spring Boot中,
spring-boot-starter-web
中包含了此依赖- 此方法的返回值类型在Spring MVC中没有默认的Converter(转换器),会自动调用
jackson-databind
中的Converter,而jackson-databind
的处理方法就是将返回值转换成JSON格式的字符串
- 只要是自定义的数据类型,在Spring MVC中都没有默认的Converter
例如,在项目的根包下创建web.JsonResult
类:
@Data
public class JsonResult implements Serializable {
private Integer state;
private String message;
private Object data;
}
以上类型,将作为项目中每个处理请求的方法、每个处理异常的方法的返回值类型!
如果在Service层始终抛出ServiceException
,由于使用了统一处理异常的机制,会导致所有异常的业务状态码都是相同的!为了解决此问题,可以:
- 创建多种异常类型,针对不同的错误,在Service层抛出不同的异常
- 在Service层每次抛出异常时,向异常对象中封装业务状态码
如果采取以上第2种做法,则需要将ServiceException
调整为:
@Getter
public class ServiceException extends RuntimeException {
private Integer state;
public ServiceException(Integer state, String message) {
super(message);
this.state = state;
}
}
然后,另外自定义一个接口,用于声明各业务状态码的常量:
public interface ServiceCode {
Integer ERR_CONFLICT = 2;
Integer ERR_NOT_FOUND = 6;
Integer ERR_INSERT = 3;
Integer ERR_UPDATE = 4;
Integer ERR_DELETE = 5;
}
并且,在抛出异常时,向异常对象中封装以上业务状态码,例如:
String message = "添加相册失败!相册名称【" + name + "】已存在!";
log.warn(message);
throw new ServiceException(ServiceCode.ERR_CONFLICT, message);