springboot合理封装响应与异常
合格的前后端分离系统中,后端返回给前端的数据必须有一定的一致性,一种常见的json如下
{
"success": 1,
"errMsg": "runtime error",
"errCode": 5000,
"data": null
}
今天研究了一下如何在springboot中实现异常与正常响应都这样按格式返回。
响应格式
首先定义响应的格式
/* 响应格式
/utils/HttpResponse
*/
@Data
@Getter
@AllArgsConstructor
public class HttpResponse<T> {
private Boolean success;
private String errMsg;
private Integer errCode;
private T data;
public static <T> HttpResponse success(T data) {
return new HttpResponse<T>(true, "success", 1000, data);
}
public static <T> HttpResponse failure(Errors error) {
return new HttpResponse(false, error.getErrMsg(), error.getErrCode(), null);
}
public static <Void> HttpResponse failure(String errMsg) {
return new HttpResponse(false, errMsg, 5000, null);
}
}
拦截所有响应
springboot中的注解@RestControllerAdvice
与@ControllerAdvice
都可以实现对所有响应拦截并处理,我们可以对拦截的响应进行加密,鉴权等操作,这里我们将所有的响应进行类型判断,如果不符合我们定义的格式,则将其传入对应方法中转变为对应格式
/*
/utils/ResponseHandler
*/
@RestControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (!(body instanceof HttpResponse)) {
return HttpResponse.success(body);
}
return body;
}
}
bug shooter
这里有个bug,如果传入的对象类型为String会出错
因为在所有的
HttpMessageConverter
实例集合中,StringHttpMessageConverter
要比其它的Converter
排得靠前一些。我们需要将处理Object
类型的HttpMessageConverter
放得靠前一些,这可以在Configuration
类中完成
摘自
/*
/config/WebConfiguration
*/
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter());
}
}
自定义错误
使用自定义的错误与对应的errCode
/*
/enums/Errors
*/
public enum Errors {
INTERNAL_ERROR(5001, "内部错误"),
REQUEST_ERROR(4001, "请求出错"),
PERMISSION_DENY(4003, "权限错误"),
UNKNOWN_ERROR(4004, "未知错误"),
UN_LOGIN(4011, "未登录");
private Integer errCode;
private String errMsg;
Errors(Integer errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
public void setErrCode(Integer errCode) {
this.errCode = errCode;
}
public Integer getErrCode(){return errCode;}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public String getErrMsg() {return errMsg;}
}
拦截控制器并全局处理异常
使用@RestControllerAdvice
拦截响应,结合@ExceptionHandler
处理异常,
/*
/utils/exception/GlobalExceptionHandler
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(LocalRunTimeException.class)
public HttpResponse LocalRunTimeException(LocalRunTimeException e) {
log.error("内部异常", e);
if (e.getErrorEnum() != null) {
return HttpResponse.failure(e.getErrorEnum());
} else {
return HttpResponse.failure(e.getMessage());
}
}
@ExceptionHandler(RuntimeException.class)
public HttpResponse runtimeException(RuntimeException e) {
log.error("其他异常", e);
return HttpResponse.failure(e.getMessage());
}
}
Comments | NOTHING