除了对控制器返回数据进行统一的处理外,ResponseBodyAdvice还可以用于处理控制器抛出异常时的响应格式。
以下是一个示例,实现了对异常的包装,添加了响应码和响应消息:
@ControllerAdvice
public class ExceptionWrapper implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if (body instanceof ResponseWrapper) {
// 如果已经是包装类,直接返回
return body;
}
// 否则进行包装
ResponseWrapper<Object> responseWrapper = new ResponseWrapper<>();
if (body instanceof BusinessException) {
// 将业务异常的状态码和消息拷贝到responseWrapper中
BusinessException businessException = (BusinessException) body;
responseWrapper.setCode(businessException.getCode());
responseWrapper.setMessage(businessException.getMessage());
} else {
// 将服务器异常状态码和消息拷贝到responseWrapper中
responseWrapper.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
responseWrapper.setMessage(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
}
responseWrapper.setData(null);
return responseWrapper;
}
// 异常处理
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ResponseWrapper> handleBusinessException(BusinessException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e);
}
}
AI 代码解读
在上述示例中,我们实现了ResponseBodyAdvice接口,并在类上使用@ControllerAdvice注解,表示该类也会拦截所有Controller的响应。同时我们也定义了一个异常处理器,处理控制器抛出的BusinessException异常。
在beforeBodyWrite方法中,我们判断了返回的数据是否已经是一个包装类,如果是,则直接返回,否则包装成ResponseWrapper类进行返回。如果抛出的异常是BusinessException,则将其状态码和消息拷贝到responseWrapper中;否则将服务器异常的状态码和消息拷贝到responseWrapper中。
通过这种方式,我们可以统一处理控制器抛出的异常,使客户端可以统一解析异常并进行处理。