我有以下控制器。我正在使用Spring创建Restful API。
@RestController
public class UserController extends RestControlValidator {
@RequestMapping(value = "/user/", method = RequestMethod.POST, headers = "Accept=application/json", consumes = "application/json", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody List newUser(@RequestBody @Valid UserInput input,BindingResult result)
{Some code}
}
UserInput
类看起来像这样:
public class UserInput{
@NotEmpty
private String emailId;
@NotEmpty
private String fName;
private String lName;
private int sex;
//getters and setters
现在,当我尝试使用数据/user/
访问{"sex":"Male"}
时,我收到以下回复:
如果有这样的请求,我想要回复:
{"errors":{"sex":"The value must be an integer"}}
有没有办法在Spring中自定义BAD REQUEST
响应?
答案 0 :(得分:0)
考虑到当前场景,最理想的解决方案是改变HandlerMethodArgumentResolve的行为,因为@RequestBody构造的json到pojo失败,因为我们没有机会检查错误的数据,这个检查很可能在自定义消息转换器
一个。首先,我们需要创建LanguageMessageConverter,如下所示
public class LanguageMessageConverter extends
AbstractHttpMessageConverter<Language> {
private Gson gson = new Gson();
public LanguageMessageConverter() {
super(new MediaType("application", "json", Charset.forName("UTF-8")));
}
@Override
protected boolean supports(Class<?> clazz) {
return Language.class.equals(clazz);
}
Map<String, String> mp = new HashMap<>();
@Override
protected Language readInternal(Class<? extends Language> clazz,
HttpInputMessage httpInputMessage) throws IOException,
HttpMessageNotReadableException {
Map langmp = gson.fromJson(
convertStreamToString(httpInputMessage.getBody()), Map.class);
for (Field field : clazz.getDeclaredFields()) {
if (!langmp.get(field.getName()).getClass().getCanonicalName().equals(field.getType().getCanonicalName())) {
if (field.getType().getCanonicalName().equals("java.lang.Integer")||field.getType().getCanonicalName().toString().equals("int")) {
langmp.put(field.getName(), "0");
} else if (field.getType().equals("java.lang.String")) {
//TODO COde needs to be improved here because this check is not efficient
langmp.put(field.getName(), "wrong");
}
}
}
Language lang = gson.fromJson(gson.toJson(langmp), clazz);
return lang;
}
langmp
(可以使用更好的JSON解析器) B中。其次,我们需要在调度程序xml中注册自定义MessageConverter,即LanguageMessageConverter
<mvc:annotation-driven >
<mvc:message-converters register-defaults="true">
<bean class="com.comp.org.controller.LanguageMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
register-defaults="true"
非常重要,因为我们正在添加自定义MessageConverter,但我们还需要其他现有转换器与我们添加的转换器一起工作℃。考虑到有关pojo填充了必要的细节,它将到达我们的控制器后处理自定义转换器现在我们将添加手动验证,例如。如果int变量为0,则应返回必要的错误json
根据您的要求,即使json包含错误的数据,自定义消息转换器也应该处理它,因此在控制器中我们可以验证所提到的条件。 代码肯定可以进一步改进。请告知我这个解决方案是否符合您的要求,或者代码的任何部分需要进一步详细说明,并希望能够解决您的问题。
答案 1 :(得分:0)
我遇到了同样的问题,而不是我解决的问题:
创建一个名为Error的对象,就像那样(不要忘记实现Serializable ......):
private String fieldName;
private String errorCode;
private String defaultMessage;
public Error() {
}
public Error(String fieldName, String errorCode, String defaultMessage) {
this.fieldName = fieldName;
this.errorCode = errorCode;
this.defaultMessage = defaultMessage;
}
/* getters, setters */
在@RestController
方法中,您需要调用inputValidator.validate()
方法(如果您没有为UserInput
创建对象验证器,那么我们确实不要说同一种语言......)
// validating the userInput
userInputValidator.validate(userInput, bindingResult);
if (bindingResult.hasErrors()) {
List<Error> errors = new ArrayList<>(bindingResult.getErrorCount());
for (FieldError fieldWithError : bindingResult.getFieldErrors()) {
errors.add(new Error(fieldWithError.getField(), fieldWithError.getCode(), fieldWithError.getDefaultMessage()));
}
return errors;
}
// in case of success:
return null;
最后,您必须将JSON对象转换为客户端。您将拥有两种对象:
3.1。 null(undefined
取决于您正在使用的语言)
3.2。像这样的JSON对象:
[
{
"fieldName": "name",
"errorCode": "user.input.name.in.blank",
"defaultMessage": "Insert a valid name!"
},
{
"fieldName": "firstPhone",
"errorCode": "user.input.first.phone.blank",
"defaultMessage": "Insert a valid first phone!"
}
]