Проверка параметров JSR 303 Проверка на Java SpringBoot

задняя часть

Недавно начал переходить с оригинальной инженерки Android на Java Web.Не много ерунды,картинка выше

задний план

JSR 303 — Bean Validation — это спецификация для проверки данных, завершенная в ноябре 2009 года. Hibernate Validator является эталонной реализацией Bean Validation. Hibernate Validator предоставляет все встроенные ограничения в спецификации JSR 303. Обычно мы проверяем и оцениваем входящие параметры при написании интерфейса, например, не является ли строка пустой, сколько значений возвращается и т. д. Для этого необходимо использовать проверку параметров Spring, здесь мы используем spring-boot-starter- веб-пакет содержит пакет hibernate-validator,

Существует несколько способов проверки параметров, а именно:

  • 1. Используйте @Valid+BindingResult
  • 2. Аннотировать с помощью @Valid + глобальная обработка захвата исключений

Ниже описано использование этих двух методов.

Проверка с параметрами @Valid+BindingResult

1. В соответствии с международной спецификацией JSP 303 сначала определите bean-компонент, а другие добавляют аннотации проверки к имени поля, имя поля @NotBlank не может быть нулевым, а длина больше 0. Общие типы проверки:

Constraint    详细信息

@Null    被注释的元素必须为 null
@NotNull    被注释的元素必须不为 null
@AssertTrue    被注释的元素必须为 true
@AssertFalse    被注释的元素必须为 false
@Min(value)    被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)    被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)    被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)    被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min)    被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction)    被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past    被注释的元素必须是一个过去的日期
@Future    被注释的元素必须是一个将来的日期
@Pattern(value)    被注释的元素必须符合指定的正则表达式
/**
 * @author Lang.Chen
 * @date 2018/6/20 下午4:39
 */
public class User {

    //账号
    @NotBlank(message = "账号不能为空")
    private String phone;
    //密码
    @NotBlank(message = "密码不能为空")
    private String password;

    public void setPhone(String phone) {
        this.phone = phone;
    }

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

    public String getPhone() {
        return phone;
    }

    public String getPassword() {
        return password;
    }
}



2. Добавьте проверку @Valid+BindingResult в соответствующий интерфейс в классе Controller.После добавления, если проверка параметра не удалась, перейдите непосредственно к оператору if и верните результат в операторе.

 if(bindingResult.hasErrors()){

 }

@RestController
@RequestMapping(value = "/user")
public class UserController implements IUser {


 @Override
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public User login( @Valid User userInfo, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            System.out.print(bindingResult.getFieldError().getDefaultMessage());
            return null;
        }
        return userInfo;
    }

}


Что ж, мы закончили первую проверку, но подумайте хорошенько, если у меня несколько интерфейсов, нужно ли мне каждый раз писать @Valid+BindgResult bingingResult, а затем переходить к оператору If, чтобы судить, если это только Ошибка информация противоречива, но возвращенная структура клиента непротиворечива, например


 {"code":"1002","message":"parameters are missing","data":"{}"}
 

Разным проверкам нужно только изменить сообщение, а затем можно ли его обрабатывать единообразно, чтобы уменьшить объем кода, поэтому второй метод представлен ниже.

Используйте @Valid + глобальную проверку параметров захвата исключений.

Проще говоря, удалите BindingResult из первого метода, а затем определите глобальный класс исключения, такой же

1. Или определить POJO

/**
 * @author Lang.Chen
 * @date 2018/6/20 下午4:39
 */
public class User {

    //账号
    @NotBlank(message = "账号不能为空")
    private String phone;
    //密码
    @NotBlank(message = "密码不能为空")
    private String password;

    public void setPhone(String phone) {
        this.phone = phone;
    }

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

    public String getPhone() {
        return phone;
    }

    public String getPassword() {
        return password;
    }
}

2. Метод в контроллере определяет @Valid для проверки


public class UserController implements IUser {

 @Override
    @RequestMapping(value = "/login2", method = RequestMethod.POST)
    public User login2(@RequestBody @Valid User userInfo) {
        return null;
    }

 }   

3. Определите глобальный класс исключений

Все результаты неудачной проверки будут зафиксированы в методе defaultExcepitonHandler класса GlobalExceptionHandler.


@RestControllerAdvice
@Component
public class GlobleExceptionHandler {



    @ResponseBody
    @ExceptionHandler(Exception.class)
    public String defultExcepitonHandler(Exception ex) {

        ex.printStackTrace();
        if(ex instanceof  BindException){
            //处理返回的错误信息
            StringBuffer errorMsg = new StringBuffer();
            BindException c = (BindException) ex;
            List<ObjectError> errors = c.getBindingResult().getAllErrors();
            for (ObjectError error : errors) {
                errorMsg.append(error.getDefaultMessage()).append(";");
            }

            return errorMsg.toString();

        }
        return "";

    }

}

Что касается пользовательской проверки и групповой проверки, я не буду вводить их одну за другой, а воспользуюсь двумя вышеуказанными.

Q&A

1. Как использовать один параметр для проверки и ввода глобального захвата исключения, возврата?

Иногда, когда передается только несколько проверок, мы не можем создать новый объект для принятия. Как использовать проверку одного параметра в это время? Посмотрите онлайн-использование и добавьте его в класс параметр @Validated, а затем через глобальный метод захвата исключений

@RestController
@RequestMapping("/order")
@Validated
public class OrderController implements IOrder {


   @RequestMapping(value = "/byId",method = RequestMethod.POST)
   public OrderInfo byId( @Max(value = 50) int orderId) {
       return null;
   }

}

Но при каждом обращении к интерфейсу выдает одну и ту же ошибку, так что этот способ бесполезен.Если кто найдет решение, подскажите, спасибо

{
    "timestamp": "2018-06-24T07:09:14.235+0000",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/order/byId"
}

Разница между @Valid и @Validated

@Valid находится в javax.validation @Validated — это инкапсуляция @Valid, которая используется механизмом проверки, предоставляемым Spring. @Validated обеспечивает функциональность группировки