1 统一定义Json响应体{ code msg data}
通常情况我们在Controller
层进行返回数据时候,对具体的业务数据要再次包装一下返回,如:
{
"code":"0",
"msg" :"success",
"data":{}
}
-
code
状态码,如成功默认"0",失败默认"-1" -
msg
状态码对应的提示信息 -
data
业务数据,成功有数据时填充。如成功无数据、失败状态 只有code
、msg
为此我们在Controller
层进行一层封装ResponseJson.java
,该类采用继承HashMap形式进行封装:
/**
* 返回体封装,以json格式返回,包括 code msg data等信息
*
* @author jockeys
* @since 2020/3/11
*/
public final class ResponseJson extends HashMap<String, Object> {
/**
* 默认错误码
*/
private static final String DEFAULT_ERROR_CODE = "-1";
/**
* 默认构造函数私有化
*/
private ResponseJson() {
put("code", ResponseEnum.SUCCESS.getCode());
put("msg", ResponseEnum.SUCCESS.getMessage());
}
/**
* 重新设置提示信息
*
* @param msg 提示信息
* @return this object
*/
public ResponseJson setMsg(String msg) {
this.put("msg", msg);
return this;
}
/**
* 错误-消息返回体设置
*
* @param code 错误状态码
* @param msg 错误提示信息
* @return this object
*/
public static ResponseJson error(String code, String msg) {
ResponseJson ans = new ResponseJson();
ans.put("code", code);
ans.put("msg", msg);
return ans;
}
/**
* 错误-消息返回体设置(默认错误状态码为 -1)
*
* @param msg 错误提示信息
* @return this object
*/
public static ResponseJson error(String msg) {
return error(DEFAULT_ERROR_CODE, msg);
}
/**
* 错误-信息返回体设置,默认错误码和错误提示
*
* @return this object
*/
public static ResponseJson error() {
return error(ResponseEnum.SERVER_ERROR.getCode(), ResponseEnum.SERVER_ERROR.getMessage());
}
/**
* 错误-信息返回体设置,返回信息状态定义
*
* @return this object
*/
public static ResponseJson error(ResponseEnum responseEnum) {
return error(responseEnum.getCode(), responseEnum.getMessage());
}
/**
* 成功-信息返回体设置
*
* @param data 响应数据
* @return the object with response data
*/
public static ResponseJson ok(Object data) {
ResponseJson ans = new ResponseJson();
ans.put("data", data);
return ans;
}
/**
* 成功-信息返回体设置 (无响应数据)
*
* @return this object without response data
*/
public static ResponseJson ok() {
return new ResponseJson();
}
}
对于 code
/ msg
组成的键值对,我们用Enum进行定义(注意代码中使用了lombok插件):
/**
* 返回码封装,用枚举类实现
*
* @author jockeys
* @since 2020/3/11
*/
@Getter
@AllArgsConstructor
public enum ResponseEnum {
/**
* 成功状态码
*/
SUCCESS("0", "success"),
/**
* 系统异常相关错误
*/
SERVER_ERROR("-1", "未知异常,请联系管理员"),
SYSTEM_ERROR("system-err", "系统内部错误,请联系管理员..."),
NETWORK_ERROR("network-err", "网络故障,请检查网络连接..."),
BUSINESS_ERROR("business-err", "业务处理中,请稍后重试..."),
/**
* 通用的校验错误
*/
ILLEGAL_ARGS_ERROR("args-illegal-err", "非法参数错误"),
ARGS_PASSWORD_WRONG("password-format-err", "密码格式不正确"),
ARGS_PHONE_WRONG("phone-format-err", "手机格式不正确"),
;
private String code;
private String message;
}
接下来我们可以在Controller层中进行应用,e.g.
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@ApiOperation(value = "Swagger注释:包装体封装Json格式返回测试接口")
@GetMapping("/hello")
public ResponseJson sayHello() {
log.info("进入方法...")
String baby = "what’s happening to you?";
return ResponseJson.ok(baby);
}
}
当然,上述步骤封装完毕后,我们已经能够正常使用进行统一的格式返回。
2 统一包装处理 @ResponseBodyAdvice
但是在Controller层所有的返回类型均为ResponseJson
,我们在Controller层无法感知具体的业务含义,那我们为什么不能够将该步骤的封装在延后一下,在Http请求获得响应返回进行包装? 这当然是可行的!spring框架提供的ResponseBodyAdvice
和@ControllerAdvice
可以用来实现这一想法。
@Slf4j
@ControllerAdvice
public class ResponseJsonFormatHandler implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter,
Class<? extends HttpMessageConverter<?>> aClass) {
// 判断请求是否需要包装,默认true
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
log.info("进入返回体重写过程,封装code msg data...");
return null == o? ResponseJson.ok():ResponseJson.ok(o);
}
}
这样,我们Controller层代码就可以直接返回业务体
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public String sayHello() {
log.info("进入方法...")
String baby = "what’s happening to you?";
return baby;
}
}
网友评论