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());
}
}