java - 在 REST API 中自定义/修补 400 响应
问题描述
我已经使用 Spring & Swagger 构建了一个 rest api。持久性是通过 Hibernate 实现的。其余的 api 以不同的格式公开数据,然后它在数据库中,所以我使用的是 dto 模式。客户与 CustomerDto。一切都很好。我用@ApiModel(value="Customer") 掩盖了 Swagger 中的 CustomerDto。这一切也都很好。
这就是问题所在。我正在使用@Size、@NotNull 等验证注释。所以我得到了很好的 400 响应 json:
{
"timestamp": "2019-11-15T22:25:37.943+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"NotNull.customerDto.firstName",
似乎 MethodArgumentNotValidException 不知道 @ApiModel 注释,因此它将对象名称显示为 customerDto。
有什么办法可以修补响应或类似的东西吗?我知道我可以捕获 400 异常并建立自己的响应,但我宁愿不重新发明整个轮子来重现整个 json。
我的公司与金融机构合作,因此出于安全目的,我们不应该透露应用程序内部结构。
编辑:应该明确表示我不想替换库存 json,我只想将 customerDto 更改为 customer。除了消息之外,json 中还有一些元素,比如代码和东西。也试图接近那些。
解决方案
默认情况下,所有错误消息都是内置的DefaultErrorAttributes
,因此您可以对其进行扩展以修改错误属性映射。
这是一个例子:
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
@Component
public class ExtendedDefaultErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
final Map<String, Object> errorAttributes =
super.getErrorAttributes(webRequest, includeStackTrace);
// MethodArgumentNotValidException includes errors key
Object errors = errorAttributes.get("errors");
// .. now you can do whatever you want here... something like completely remove it.
if (errors != null) {
errorAttributes.remove("errors");
}
// In here for what you are looking for , you should be doing something like //below, just as an example, but do it properly, I just typed it without checking:
List<ObjectError> errors = (List<ObjectError>) errorAttributes.get("errors");
errors.get(0).getCodes()[0].replaceAll("customerDto", "customer");
return errorAttributes;
}
}
或者在 ControllerAdvice 或 Controller 类中使用 @ExceptionHandler 来根据需要进行修改。
例子:
@ExceptionHandler({MethodArgumentNotValidException.class})
public void handleMethodArgumentNotValidException(
MethodArgumentNotValidException manve, HttpServletResponse response) throws IOException {
exceptionLog.error(manve.getMessage());
Map<String, String> errors =
manve
.getBindingResult()
.getFieldErrors()
.stream()
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
String errorMessage = "...."
if (!errors.isEmpty()) {
ObjectMapper mapper = new ObjectMapper();
errorMessage = mapper.writeValueAsString(errors);
}
response.sendError(400, errorMessage);
}
推荐阅读
- postgresql - Postgres 数据库中的批量复制错误,同时使用复制语法将 CSV 文件导入表
- python - 如何在 cv2.ellipse 图中填充颜色?
- powershell - 如何使用 Powershell 获取计算机上所有文件的列表
- sparql - 有没有办法在 SPARQLWrapper 中获取错误代码?
- html - 输入类型=时间不适用于 min 和 max 属性
- python - UnboundLocalError:在discord.py中分配之前引用了局部变量'member_id'
- javascript - 如何在反应钩子数组中获取其对象的值?
- python - 读取 csv 文件时 Kaggle 中的错误消息
- keras - 如何在单个代码中使用 3 个不同版本的 keras?
- angular - 如何访问在父模块中声明的组件