简体   繁体   中英

Spring3 doesn't work @valid when json request I got 400 Bad Request error

I'm using Spring3 framework ,hibernate validator and jackson.

when I request for jsondata to server. returned 400 Bad Request error.

then my data is missmatch type.

when I request match type then it's working good.

My controller code:

@RequestMapping(consumes = MediaType.ALL_VALUE, produces = MediaType.ALL_VALUE,value =
    "doAdd", method = RequestMethod.POST)
@ResponseBody
public Customer doAdd(@RequestBody @Valid Customer inData){
    this.customerService.addData(inData);
    return inData;
}

and Error handle method is:

@ExceptionHandler
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public void ajaxValidationErrorHandle(MethodArgumentNotValidException errors ,
    HttpServletResponse response) throws BusinessException {
    List<String> resErrors = new ArrayList<String>();
    for(ObjectError error : errors.getBindingResult().getAllErrors()){
        resErrors.add(error.getCode());
    }
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    throw new BusinessException("E000001", "VALIDATION");
}

Customer.java(model) :

package test.business.model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Range;

public class Customer {
    @Size(min = 0, max = 3)
    public String id;

    @NotNull
    @Size(min = 1)
    public String name;

    @NotNull
    @Range(min = 10, max = 99)
    public Integer age;

    public String updateTime;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }
}

json data:

1.{"name":"ken","age":11,"updateTime":"2013-06-18"}
2.{"name":"ken","age":"","updateTime":""}
3.{"name":"ken","age":"joe","updateTime":""}

json data 1 is returned normally.

json data 2 is returned normally(I caught MethodArgumentNotValidException customer.age,NotNull).

json data 2 is returned 400 Bad Request error. but I hope that Server returned typeMismatch.int error.


@Pavel Horal Thank you so much!

I could catch the HttpMessageNotReadableException,and handled.

The error handle methods that have changed.

    @ExceptionHandler
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public void ajaxValidationErrorHandle(Exception errors , HttpServletResponse response) throws BusinessException {
    if(errors instanceof MethodArgumentNotValidException){
        MethodArgumentNotValidException mane = (MethodArgumentNotValidException)errors;
        for(ObjectError error : mane.getBindingResult().getAllErrors()){
            resErrors.add(error.getCode());
        }
    }
    if(errors instanceof HttpMessageNotReadableException){
        JsonMappingException jme = (JsonMappingException)errors.getCause();
        List<Reference> errorObj = jme.getPath();
        for(Reference r : errorObj){
            System.out.println(r.getFieldName());
        }
    }
・・・

However, it's that inherit to make the base class or write this code in all controllers feel like I have not seen the design concept of the spring because, it was decided to handle over there to make a ExceptionResolver new.

My new ExceptionResolver is:

public class OriginalExceptionHandler extends SimpleMappingExceptionResolver {

@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
    ModelAndView m = null;
    StringBuilder exceptionMessage = new StringBuilder(ajaxDefaultErrorMessage) ;
    if(e instanceof BusinessException){
                   ・・・
    }else if(e instanceof HttpMessageNotReadableException){
        Throwable t = e.getCause();
        if(t instanceof JsonMappingException){
            JsonMappingException jme = (JsonMappingException)t;
            List<Reference> errorObj = jme.getPath();
            for(Reference r : errorObj){
                exceptionMessage.append("VE9999:Unmatched Type Error!!("+r.getFieldName()+")");
            }
        }else{
            exceptionMessage.append(e+"\n"+o.toString());
        }
    }else if(e instanceof MethodArgumentNotValidException){
        MethodArgumentNotValidException mane = (MethodArgumentNotValidException)e;
        for(ObjectError error : mane.getBindingResult().getAllErrors()){
            if(error instanceof FieldError){
                FieldError fe = (FieldError) error;
                exceptionMessage.append("VE0001:Validation Error!!"+fe.getField()+"-"+fe.getDefaultMessage());
            }else{
                exceptionMessage.append("VE0001:Validation Error!!"+error.getDefaultMessage());
            }
        }
    }else{
                 ・・・

And, I've added incense to application-context.xml:

    <bean class="test.core.OriginalExceptionHandler" p:order="1">
    <property name="exceptionMappings">
        <props>
            <prop key="sample.core.BusinessException">
                ExceptionPage
            </prop>
            <prop key="test.core.LoginSessionException">
                LoginSessionException
            </prop>
        </props>
    </property>
    <property name="defaultErrorView" value="error" />
</bean>

This way of thinking correct?

Thank you,

Data binding (mapping request to objects) is an independent process from data validation. In Spring, data binding can contribute with its own binding errors to overall validation errors.

Binding errors are supported by Spring's standard WebDataBinder , which kicks in when the method parameter is annotated with @ModelAttribute

With @RequestBody annotation a completely different mechanism is used - HttpMessageConverter s (in you case probably the MappingJackson2HttpMessageConverter ). When the JSON unmarshalling fails a HttpMessageNotReadableException exception is thrown.

You can handle exceptions within your global HandlerExceptionResolver or a special @ExceptionHandler annotated handler method within the handler itself or a global @ControllerAdvice .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM