ResponseBodyAdvice 接口实现自定义返回数据类型
api接口中都是需要定义一个统一的响应头来返回json数据
一般方法是通过在返回时构造一个响应头对象如下:
public class ApiR extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public ApiR() {
put("code", 200);
put("msg", "success");
}
public static ApiR error() {
return error(500, "未知异常,请联系管理员");
}
public static ApiR error(String msg) {
return error(500, msg);
}
public static ApiR error(int code, String msg) {
ApiR r = new ApiR();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static ApiR ok(String msg) {
ApiR r = new ApiR();
r.put("msg", msg);
return r;
}
public static ApiR ok(Object obj) {
ApiR r = new ApiR();
r.put("code",200);
r.put("results", obj);
return r;
}
public static ApiR ok(Map<String, Object> map) {
ApiR r = new ApiR();
r.putAll(map);
return r;
}
public static ApiR ok() {
return new ApiR();
}
public static ApiR setResults(Object object) {
ApiR r = ApiR.ok();
r.put("code",200);
r.put("results", object);
return r;
}
@Override
public ApiR put(String key, Object value) {
super.put(key, value);
return this;
}
}
在返回是使用ApiR
return ApiR.setResults(list);
这种弊端是每个响应都需要加响应头对象。
我们可以通过统一响应处理
统一处理的响应头对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResponse<T> implements Serializable {
private Integer code;
private String msg;
private T data;
public CommonResponse(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
通过@RestControllerAdvice来实现,ResponseBodyAdvice的作用是在响应体返回之前做一些自定义的处理工作。通常,我们会实现ResponseBodyAdvice接口,幷包装统一的响应返回。
@RestControllerAdvice
public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> {
@Override
@SuppressWarnings("all")
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
//如果类有IgnoreResponseAdvice这个注解就不处理
if(methodParameter.getDeclaringClass().isAnnotationPresent(
IgnoreResponseAdvice.class
)){
return false;
}
//如果方法有IgnoreResponseAdvice这个注解就不处理
if(methodParameter.getMethod().isAnnotationPresent(
IgnoreResponseAdvice.class
)){
return false;
}
return true;
}
//Object,这个就是原始的Controller返回的内容。我们也就是需要对它进行包装
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
CommonResponse<Object> response = new CommonResponse<>(0,"");
//如果是null response不需要设置data
if(null == o){
return response;
//如果o是CommonResponse实例 强转
}else if(o instanceof CommonResponse){
response = (CommonResponse<Object>) o;
}else{
// 否则, 把响应对象作为 CommonResponse 的 data 部分
response.setData(o);
}
return response;
}
}
统一异常处理
业务异常类
public class ReException extends Exception{
public ReException(String message){
super(message);
}
}
异常处理,也需要统一响应头
@RestControllerAdvice
public class GlobalExceptionAdvice {
@ExceptionHandler(value = ReException.class)
public CommonResponse<String> handlerReException(HttpServletRequest request,ReException re){
//统一异常接口的响应
//建议使用枚举
CommonResponse<String> response = new CommonResponse<>(-1,"business error");
response.setData(re.getMessage());
return response;
}
}
统一配置json
通过继承WebMvcConfigurer类重写configureMessageConverters方法
MappingJackson2HttpMessageConverter实现了HttpMessageConverter接口。HttpMessageConverter接口有canRead和canWrite方法。完成json转化
@Configuration
public class WebConfiguration implements WebMvcConfigurer{
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.clear();
converters.add(new MappingJackson2HttpMessageConverter());
}
}