前言
项目中一般都会有规定好的接口返回格式,无论成功与失败,一般格式都是不变的,这样是为了方便前后端统一处理,今天就来说下前后端统一处理的较为优雅的方式;
一、统一的返回格式
一般而言都会有一个统一的返回类作为接口的返回数据的封装,例如:
@Data
public class Result<T> implements Serializable {
private int code = HttpStatus.OK.value();
private String msg;
private T data;
public static <T> Result<T> success() {
return success(null);
}
public static <T> Result<T> failure() {
return failure(HttpStatus.BAD_REQUEST.value(),HttpStatus.BAD_REQUEST.getReasonPhrase());
}
public static <T> Result<T> success(T data) {
return new Result<T>(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), data);
}
public static <T> Result<T> failure(int errorCode, String errorMsg) {
return failure(errorCode, errorMsg, null);
}
public static <T> Result<T> failure(int code, String errorMsg, T data) {
return new Result<T>(code, errorMsg, data);
}
public Result(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
然后我们通过此类作为返回参数的统一封装,这样无论成功与否,都是三个参数
code msg data
二、全局异常处理
- 项目中难免会有异常抛出
- 服务端报错的异常
- 处理逻辑中的异常(参数校验, 逻辑不通等)
- 由于我们一般都是前后端分离项目,所以都是接口方式的返回,那么我们只需要处理接口就可以了
@RestControllerAdvice
@Slf4j
public class ControllerExceptionHandel {
@ExceptionHandler(ValidationException.class)
public Result<String> handleException(ValidationException e) {
e.printStackTrace();
log.error("参数校验发生异常:{}", e.getMessage());
return Result.failure(HttpStatus.BAD_REQUEST.value(), e.getMessage());
}
@ExceptionHandler(value = NullPointerException.class)
public Result<String> exceptionHandler(NullPointerException e) {
e.printStackTrace();
log.error("空指针异常:{}", e.getMessage());
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
@ExceptionHandler(value = {Exception.class, RuntimeException.class})
public Result<String> exceptionHandler(Exception e) {
e.printStackTrace();
log.error("运行时发生异常:{}", e.getMessage());
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
@ExceptionHandler(AsyncRequestTimeoutException.class)
public Result<String> handException(AsyncRequestTimeoutException e) {
e.printStackTrace();
log.error("运行时超时异常:{}", e.getMessage());
return Result.failure(HttpStatus.BAD_REQUEST.value(), e.getMessage());
}
}
一般来说控制器可以这样用
@RestController
@RequestMapping("lang")
public class LangController {
@RequestMapping("get")
public Result get(){
return Result.success(LocalUtil.get("demo"));
}
}
三、全局返回处理(装逼用的)
还是上面的全局异常处理,不过要增加点东西
- 实现ResponseBodyAdvice接口
- 实现两个方法
完整代码如下:
@RestControllerAdvice
@Slf4j
public class ControllerExceptionHandel implements ResponseBodyAdvice<Object>{
@Autowired
private ObjectMapper objectMapper;
@ExceptionHandler(ValidationException.class)
public Result<String> handleException(ValidationException e) {
e.printStackTrace();
log.error("参数校验发生异常:{}", e.getMessage());
return Result.failure(HttpStatus.BAD_REQUEST.value(), e.getMessage());
}
@ExceptionHandler(value = NullPointerException.class)
public Result<String> exceptionHandler(NullPointerException e) {
e.printStackTrace();
log.error("空指针异常:{}", e.getMessage());
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
@ExceptionHandler(value = {Exception.class, RuntimeException.class})
public Result<String> exceptionHandler(Exception e) {
e.printStackTrace();
log.error("运行时发生异常:{}", e.getMessage());
return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
}
@ExceptionHandler(AsyncRequestTimeoutException.class)
public Result<String> handException(AsyncRequestTimeoutException e) {
e.printStackTrace();
log.error("运行时超时异常:{}", e.getMessage());
return Result.failure(HttpStatus.BAD_REQUEST.value(), e.getMessage());
}
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
Class<?> returnClass = returnType.getMethod().getReturnType();
if (body instanceof String || Objects.equals(returnClass, String.class)) {
return objectMapper.writeValueAsString(Result.success(body));
}
if (body instanceof Result) {
return body;
}
return Result.success(body);
}
}
这样控制器中既可以像之前那样使用,还可以像如下使用
它会自动封装返回结果,无需手动封装文章来源:https://www.toymoban.com/news/detail-638686.html
@RestController
@RequestMapping("lang")
public class LangController {
@RequestMapping("get")
public String get(){
return LocalUtil.get("demo");
}
}
总结
如果项目中按照这种方式 @RestControllerAdvice + ResponseBodyAdvice接口,就能实现大部分的统一返回出参功能了,无论是正常请求还是异常请求,无论是简单类型还是集合返回,相当于都有了统一的封装处理;
快试试,用到项目中吧~文章来源地址https://www.toymoban.com/news/detail-638686.html
到了这里,关于springboot全局统一返回处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!