使用 Java Bean 来体现统一返回数据这个结构,可以解决接口返回格式一致性,但也有几个新问题诞生了:
- 接口返回值不明显,不能一眼看出来该接口的返回值
- 每一个接口都需要增加额外的代码量
- 不利于swagger对接口的返回类型的支持
所幸Spring Boot已经为我们提供了更好的解决办法,只需要在项目中加上以下代码,就可以无感知的为我们统一全局返回值。
import java.lang.reflect.Executable;
import java.util.Collection;
import java.util.LinkedHashMap;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
@ControllerAdvice
public class ApiResponseBody implements ResponseBodyAdvice<Object> {
@Override
@SuppressWarnings("rawtypes")
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
boolean hasMethodAnnotation = methodParameter.hasMethodAnnotation(ResponseBody.class);
if(!hasMethodAnnotation) {
Executable executable = methodParameter.getExecutable();
Object clazz = ReflectUtil.getFieldValue(executable, "clazz");
Object annotationData = ReflectUtil.getFieldValue(clazz, "annotationData");
Object annotations = ReflectUtil.getFieldValue(annotationData, "annotations");
if(ObjectUtil.isNotNull(annotations)) {
LinkedHashMap map = (LinkedHashMap)annotations;
Collection values = map.values();
if(ObjectUtil.isNotNull(values)) {
for (Object object : values) {
if(StrUtil.containsAny(object.toString(), "RestController")) {
return true;
}
}
}
}
}
return hasMethodAnnotation;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if(o instanceof ApiResponses) {
return o;
}
return ApiResponses.success(o);
}
}
复制代码
此时请求 hello接口,会报ApiResponses不能转为string的异常
{
"timestamp": "2019-12-09T12:22:53.776+0000",
"status": 500,
"error": "Internal Server Error",
"message": "com.gitee.web.api.ApiResponses cannot be cast to java.lang.String",
"path": "/users"
}
java.lang.ClassCastException: com.gitee.web.api.ApiResponses cannot be cast to java.lang.String
at org.springframework.http.converter.StringHttpMessageConverter.getContentLength(StringHttpMessageConverter.java:44) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.http.converter.AbstractHttpMessageConverter.addDefaultHeaders(AbstractHttpMessageConverter.java:260) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:211)
复制代码
解决
package com.gitee.config;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyConfig implements WebMvcConfigurer{
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.set(0, new MappingJackson2HttpMessageConverter());
}
}
复制代码
重写WebMvcConfigurerAdapter
,覆盖了原有的HttpMessageConverters
,此处采用:Jackson
epom-web工程pom添加jackson依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
复制代码
效果
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END