如何为请求者发送自定义验证Json对象?

时间:2017-02-16 13:25:06

标签: java spring-boot

如何发送自定义JSON错误而不是spring提供的错误?我需要自定义验证和默认验证,如@NotNull, @NotEmpty, @Email等等。

只有在未违反POJO类级别的验证约束时才会触发该函数

代码

package com.flasher.controller.rest;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.flasher.dto.UserRegistrationInfo;
import com.flasher.service.RegistrationService;
import com.flasher.validator.UserRegistrationInfoValidator;

@RestController
@RequestMapping(value = "/api")
public class RegistrationControllerRest {

    @Autowired
    RegistrationService registrationService;

    @Autowired
    UserRegistrationInfoValidator userRegistrationInfoValidator;

    @RequestMapping(value = "/v1/user", method = RequestMethod.POST)
    public void registerUser(@RequestBody @Valid UserRegistrationInfo userRegistrationInfo, HttpServletRequest request,
            BindingResult bindingResult) {
        userRegistrationInfoValidator.setRemoteAddr(request.getRemoteAddr());
        userRegistrationInfoValidator.validate(userRegistrationInfo, bindingResult);
        if(bindingResult.hasErrors()){
            System.out.println("has errors--");
            List<FieldError>   fieldErrors =bindingResult.getFieldErrors();
            fieldErrors.stream().forEach(fieldError->{
                System.out.println(fieldError.getField()+" "+fieldError.getDefaultMessage());
            });
        }

    }

}


package com.flasher.dto;

import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;

public class UserRegistrationInfo {
    @NotNull
    @NotEmpty
    @Length(min = 4, max = 30)
    private String userName;
    @NotNull
    @NotEmpty
    @Email
    private String email;
    @NotNull
    @NotEmpty
    @Length(min = 4, max = 15)
    private String password;
    @NotNull
    @NotEmpty
    private String reCaptcha;
    @NotNull
    private Boolean isAgreedTerms;

    public UserRegistrationInfo() {
    }

    public UserRegistrationInfo(String userName, String email, String password, String reCaptcha,
            Boolean isAgreedTerms) {
        this.userName = userName;
        this.email = email;
        this.password = password;
        this.reCaptcha = reCaptcha;
        this.isAgreedTerms = isAgreedTerms;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getReCaptcha() {
        return reCaptcha;
    }

    public void setReCaptcha(String reCaptcha) {
        this.reCaptcha = reCaptcha;
    }

    public Boolean getIsAgreedTerms() {
        return isAgreedTerms;
    }

    public void setIsAgreedTerms(Boolean isAgreedTerms) {
        this.isAgreedTerms = isAgreedTerms;
    }

}



package com.flasher.validator;

import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

import com.flasher.dto.UserRegistrationInfo;
import com.flasher.util.GoogleReCaptchaChecker;

public class UserRegistrationInfoValidator implements Validator {
    @Autowired
    GoogleReCaptchaChecker googleReCaptchaChecker;
    String remoteAddr;
    @Override
    public boolean supports(Class<?> className) {

        return UserRegistrationInfo.class.equals(className);
    }

    @Override
    public void validate(Object obj, Errors errs) {
        UserRegistrationInfo userRegistrationInfo = (UserRegistrationInfo) obj;

        if(Pattern.compile("[^\\w]").matcher(userRegistrationInfo.getUserName()).find()){
            errs.rejectValue("userName","", "Username cannot contain special characters");  
        }   
        if(Pattern.compile("[^(\\w!@#$%^&*())]").matcher(userRegistrationInfo.getUserName()).find()){
            errs.rejectValue("userName","", "Password cannot contain disallowed characters");   
        }
        if(!userRegistrationInfo.getIsAgreedTerms()){
            errs.rejectValue("isAgreedTerms", "you have to agree the terms and condition  in order to register");   
        }
        if(!googleReCaptchaChecker.validateGoogleReCaptcha(userRegistrationInfo.getReCaptcha(),remoteAddr)){
            errs.rejectValue("reCaptcha", "","invalid reCaptcha");  

        }

    }

    public void setRemoteAddr(String remoteAddr) {
        this.remoteAddr = remoteAddr;
    }

}

回复

{
  "timestamp": 1487250555542,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
  "errors": [
    {
      "codes": [
        "Length.userRegistrationInfo.userName",
        "Length.userName",
        "Length.java.lang.String",
        "Length"
      ],
      "arguments": [
        {
          "codes": [
            "userRegistrationInfo.userName",
            "userName"
          ],
          "arguments": null,
          "defaultMessage": "userName",
          "code": "userName"
        },
        30,
        4
      ],
      "defaultMessage": "length must be between 4 and 30",
      "objectName": "userRegistrationInfo",
      "field": "userName",
      "rejectedValue": "",
      "bindingFailure": false,
      "code": "Length"
    },
    {
      "codes": [
        "NotEmpty.userRegistrationInfo.userName",
        "NotEmpty.userName",
        "NotEmpty.java.lang.String",
        "NotEmpty"
      ],
      "arguments": [
        {
          "codes": [
            "userRegistrationInfo.userName",
            "userName"
          ],
          "arguments": null,
          "defaultMessage": "userName",
          "code": "userName"
        }
      ],
      "defaultMessage": "may not be empty",
      "objectName": "userRegistrationInfo",
      "field": "userName",
      "rejectedValue": "",
      "bindingFailure": false,
      "code": "NotEmpty"
    }
  ],
  "message": "Validation failed for object='userRegistrationInfo'. Error count: 2",
  "path": "//api/v1/user"
}

2 个答案:

答案 0 :(得分:2)

@ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationErrorResponse handleMathodArgumentNotValidException(
            MethodArgumentNotValidException methodArgumentNotValidException) {

        BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();
        List<ValidationError> validationErrors = new ArrayList<ValidationError>();
        if (bindingResult.hasErrors()) {
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            fieldErrors.stream().forEach(fieldError -> {
                validationErrors.add(new ValidationError(fieldError.getField(), fieldError.getDefaultMessage()));
            });

        }
        return new ValidationErrorResponse(validationErrors);
    }

答案 1 :(得分:0)

像这样创建pojo:

public class ValidationError {
    private String name;
    private String msg;*

并创建另一个pojo:

public class ValidationErrorResponse {
    private  List<ValidationError> errors;

添加此方法:

 @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ValidationErrorResponse handleValidationException(
            BindingResult exception) {
        List<ValidationError> errors = new ArrayList<ValidationError>();
        for (ObjectError er : exception.getAllErrors()) {
            FieldError fl = (FieldError) er;
            errors.add(new ValidationError(fl.getField(), er
                    .getDefaultMessage()));
        }
            return new ValidationErrorResponse(errors);

        }

并更改您的方法:

 @RequestMapping(value = "/v1/user", method = RequestMethod.POST)
    public ResponseEntity<?>registerUser(@RequestBody @Valid UserRegistrationInfo userRegistrationInfo, HttpServletRequest request,
            BindingResult bindingResult) {
   if(bindingResult.hasErrors()){
                    return new ResponseEntity<ValidationErrorResponse>(
                    handleValidationException(br), HttpStatus.BAD_REQUEST);

      }
   // your bussines logic here

  return new  ResponseEntity .... 


}