SpringBoot项目接口统一响应处理、统一异常处理、统一配置

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章