Spring Boot统一封装返回样式
1、定义统一返回实体类
定义响应报文格式。
public class ResponseEntity<T> implements Serializable {
private static final Long serialVersionUID = 1L;
private String status;
private String code;
private String msg;
private T data;
public String getStatus() {
return status;
}
public ResponseEntity setStatus(String status) {
this.status = status;
return this;
}
public String getCode() {
return code;
}
public ResponseEntity setCode(String code) {
this.code = code;
return this;
}
public String getMsg() {
return msg;
}
public ResponseEntity setMsg(String msg) {
this.msg = msg;
return this;
}
public T getData() {
return data;
}
public ResponseEntity setData(T data) {
this.data = data;
return this;
}
public static ResponseEntity success() {
return success(null);
}
public static <T>ResponseEntity success(T data) {
return new ResponseEntity().setStatus("S").setData(data);
}
public static ResponseEntity failed() {
return failed(null);
}
public static ResponseEntity failed(String message) {
return failed(null, message);
}
public static ResponseEntity failed(String code, String message) {
return new ResponseEntity().setStatus("F").setCode(code).setMsg(message);
}
2、对响应报文进行拦截处理以及配置
2.1、报文拦截处理
根据设计要求,对相应的响应报文进行处理。supports方法返回true时会执行beforeBodyWrite方法,beforeBodyWrite方法就是我们是否需要统一返回样式的处理。
@RestControllerAdvice
public class ResponseBodySupport implements ResponseBodyAdvice {
private final ObjectMapper objectMapper;
public ResponseBodySupport(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
Class<?> type = returnType.getMethod().getReturnType();
//如果不是规定的样式或流的话则需要特殊处理,这里为true才会执行beforeBodyWrite方法
//这里只要不是我们统一返回的实体类以及不是流响应对象,都需要对响应报文做进一步的统一样式。
return !ResponseEntity.class.isAssignableFrom(type) && !byte[].class.isAssignableFrom(type);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//设置编码为UTF-8,以及判断是否需要封装
response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
//必须判断下,否则会过度封装导致不符合预期要求。
if (body instanceof String) {
try {
return objectMapper.writeValueAsString(ResponseEntity.success(body));
} catch (JsonProcessingException e) {
log.error("返回异常", e);
}
}
return body instanceof ResponseEntity ? body : ResponseEntity.success(body);
}
}
2.2、配置
配置http消息转换器为FastJson,当然大家可以根据自己需求调整。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public HttpMessageConverters fastJsonConfigure() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//设置样式
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.BrowserCompatible,
SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect);
converter.setFastJsonConfig(fastJsonConfig);
List<MediaType> fastMediaTypes = new ArrayList<>();
//设置格式类型
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastMediaTypes.add(MediaType.APPLICATION_JSON);
converter.setSupportedMediaTypes(fastMediaTypes);
return new HttpMessageConverters(converter);
}
}
3、全局异常统一封装
如下是当有异常发生时,对异常情况的响应报文进行统一封装。(这里可以合并到2.1的步骤中)
@Slf4j
@RestControllerAdvice
public class GlobalExceptionSupport {
@ExceptionHandler(Exception.class)
public ResponseEntity exception(Exception e) {
String code = StringUtils.EMPTY, msg;
if (e instanceof BaseException) {
BaseException baseException = (BaseException) e;
code = baseException.getExceptionInfo().getCode();
msg = baseException.getExceptionInfo().getMessage();
log.error("业务异常错误。code={},msg={}", code, msg);
} else {
log.error("系统发生异常错误。msg={}", e.getMessage());
msg = e.getMessage();
}
return ResponseEntity.failed(code, msg);
}
@ExceptionHandler({BusinessException.class})
public ResponseEntity businessException(BusinessException e) {
log.error("业务异常错误。code={},msg={}", e.getExceptionInfo().getCode(), e.getExceptionInfo().getMessage());
return ResponseEntity.failed(e.getExceptionInfo().getCode(), e.getExceptionInfo().getMessage());
}
}
4、验证响应报文样式
测试统一返回的样式,这里有3个不同的返回实体。
@RestController
@RequestMapping("result")
public class BuryPointReportController {
@GetMapping("test")
public String test() {
return "成功";
}
@GetMapping("test1")
public ResponseEntity test1() {
return ResponseEntity.success();
}
@GetMapping("test2")
public void test2() {
}
}
验证结果如下
1、http://localhost:9057/api/bgDataAnalytics/result/test
{"status":"S","code":null,"msg":null,"data":"成功"}
2、http://localhost:9057/api/bgDataAnalytics/result/test1
{
"code":null,
"data":null,
"msg":null,
"status":"S"
}
3、http://localhost:9057/api/bgDataAnalytics/result/test2
{
"code":null,
"data":null,
"msg":null,
"status":"S"
}