[英]Custom response on bad request using spring RestController
I have the following controller. 我有以下控制器。 I am using Spring to create Restful APIs.
我正在使用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}
}
The UserInput
class looks like this: UserInput
类如下所示:
public class UserInput{
@NotEmpty
private String emailId;
@NotEmpty
private String fName;
private String lName;
private int sex;
//getters and setters
Now when I try and access /user/
with data {"sex":"Male"}
, I get the following response: 现在,当我尝试使用数据
{"sex":"Male"}
访问/user/
时,得到以下响应:
I want the response in case of such a request to be: 我希望这样的请求的响应是:
{"errors":{"sex":"The value must be an integer"}}
Is there any way of customising BAD REQUEST
responses in Spring? 有什么方法可以在Spring中自定义
BAD REQUEST
响应?
Considering the current scenario the most ideal solution would be to alter the behavior of HandlerMethodArgumentResolve as the json to pojo constructed by @RequestBody fails because we dont get a chance to check the wrong data and this check can very well be done in the custom message converter 考虑到当前情况,最理想的解决方案是更改HandlerMethodArgumentResolve的行为,因为@RequestBody构造的json转换为pojo失败,因为我们没有机会检查错误的数据,并且此检查可以很好地在自定义消息转换器中完成
A. first we would need to create LanguageMessageConverter as follows 答:首先,我们需要创建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
(There are better JSON Parsers which can be used) langmp
(可以使用更好的JSON解析器) B. Secondly we need to register the custom MessageConverter in the dispatcher xml ie LanguageMessageConverter
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"
is very important since we are adding Custom MessageConverter but we also need the other existing converters working along with the one we have added register-defaults="true"
非常重要,因为我们要添加Custom MessageConverter,但是我们还需要其他现有的转换器与我们添加的转换器一起工作 C. Considering the concerned pojo is populated with the necessary details it would reach our controller post processing in the custom converter now we would add the manual validation eg. C.考虑到相关的pojo填充有必要的详细信息,它将在自定义转换器中到达我们的控制器后处理,现在我们将添加手动验证,例如。 if the int variable has 0 the necessary error json should be returned
如果int变量为0,则应返回必要的错误json
As per your request even if the json consists of the wrong data the custom message converter should process it and accordingly in the controller we can validate the condition mentioned. 根据您的请求,即使json包含错误的数据,自定义消息转换器也应对其进行处理,因此在控制器中,我们可以验证上述条件。 The code definitely can be improved further.
该代码肯定可以进一步改进。 Kindly let me know if this solution fulfilled your requirement or any part of the code requires further elaboration and hopefully addressed your concern.
请让我知道此解决方案是否满足您的要求或代码的任何部分需要进一步阐述,并希望能解决您的问题。
I had the same issue, than I solved that way: 我有同样的问题,而不是我这样解决的:
Create an Object called Error, like that (don't forget to implement Serializable...): 创建一个名为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 */
Inside the @RestController
method you ave to call inputValidator.validate()
method (if you didn't create an Object Validator for your UserInput
then we're really don't speaking the same language...) 在
@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;
Finally you'll have to translate the JSON object to your client side. 最后,您必须将JSON对象转换为客户端。 You'll have two kind of objects:
您将拥有两种对象:
3.1. 3.1。 null (
undefined
depending on the language you're using) null(根据您使用的语言
undefined
)
3.2. 3.2。 A JSON object like that:
像这样的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!" } ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.