Что обозначает аннотация @Valid в Spring?

87

В следующем примере ScriptFileпараметр отмечен @Validаннотацией.

Что делает @Validаннотация?

@RequestMapping(value = "/scriptfile", method = RequestMethod.POST)    
public String create(@Valid ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        
    if (result.hasErrors()) {        
        modelMap.addAttribute("scriptFile", scriptFile);            
        modelMap.addAttribute("showcases", ShowCase.findAllShowCases());            
        return "scriptfile/create";            
    }        
    scriptFile.persist();        
    return "redirect:/scriptfile/" + scriptFile.getId();        
}    
Гэри Форд
источник

Ответы:

63

Это для целей проверки.

Валидация Обычно модель проверяют после привязки к ней вводимых пользователем данных. Spring 3 обеспечивает поддержку декларативной проверки с помощью JSR-303. Эта поддержка включается автоматически, если в вашем пути к классам присутствует поставщик JSR-303, например Hibernate Validator. Если этот параметр включен, вы можете инициировать проверку, просто аннотируя параметр метода контроллера с помощью аннотации @Valid: после привязки входящих параметров POST будет проверена форма AppointmentForm; в этом случае, чтобы убедиться, что значение поля даты не равно нулю и происходит в будущем.


Смотрите здесь для получения дополнительной информации:
http://blog.springsource.com/2009/11/17/spring-3-type-conversion-and-validation/

mhshams
источник
36

Добавляя к приведенным выше ответам, взгляните на следующие. AppointmentForm«S dateстолбец помечается парой аннотаций. Имея @Validаннотацию, которая запускает проверки для AppointmentForm(в данном случае @NotNullи @Future). Эти аннотации могут поступать от разных поставщиков JSR-303 (например, Hibernate, Spring и т. Д.).

    @RequestMapping(value = "/appointments", method = RequestMethod.POST)
    public String add(@Valid AppointmentForm form, BindingResult result) {
        ....
    }

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }
Чарит Де Сильва
источник
1
У меня похожий код. Я удален @Validот ApplicationFormпараметра , но, по- прежнему валидации были выпущены на date(набор в null) поле. Пожалуйста, объясни.
lupchiazoem
17

IIRC @Valid - это не аннотация Spring, а аннотация JSR-303 (которая является стандартом проверки компонентов). Что он делает, так это в основном проверяет, действительны ли данные, которые вы отправляете методу (он проверит за вас scriptFile).

Матеуш Дымчик
источник
2
Что значит «он проверит файл скрипта за вас»? Проверить, не является ли он нулевым, имеет какой-то синтаксис или какое-то содержание? Другими словами, что он подтверждает и как? Должен ли пользователь что-то реализовать? Где я могу получить информацию об этом? Спасибо!
племянник,
Пожалуйста, ответьте на вопрос @nephewtom, этого недостаточно для подтверждения с отсутствующим основным пунктом, который "против чего"?
monami
17

@Validсам по себе не имеет ничего общего с Spring. Это часть спецификации Bean Validation (их несколько, последняя из которых - JSR 380 на вторую половину 2017 года), но @Validона очень старая и полностью унаследована от JSR 303.

Как мы все знаем, Spring очень хорош в обеспечении интеграции со всеми различными JSR и Java-библиотеками в целом (подумайте о JPA, JTA, кешировании и т. Д.), И, конечно, эти ребята позаботились и о проверке. Одним из ключевых компонентов, способствующих этому, является MethodValidationPostProcessor .

Попытка ответить на ваш вопрос - @Validочень удобна для так называемого каскадирования валидации, когда вы хотите проверить сложный граф, а не только элементы верхнего уровня объекта. Каждый раз, когда вы хотите пойти глубже, вы должны использовать @Valid. Это то, что диктует JSR. Spring будет соответствовать этому с некоторыми незначительными отклонениями (например, я попытался поставить @Validatedвместо @Validметода RestController, и проверка работает, но то же самое не применимо к обычным "служебным" компонентам).

Юранос
источник
Но что подтверждает?
племянник,
Пожалуйста, поясните, @nephewtom. Что вы хотите уточнить?
yuranos
Я прочитал JSR 303: Bean Validation, beanvalidation.org/1.0/spec, но до сих пор не понимаю, над чем будет выполняться проверка ScriptFile scriptFile.
племянник
В ScriptFile, вероятно, есть несколько полей, и эти поля также имеют аннотации. Здесь и начинается проверка. Исходя из исходного вопроса, неясно, что именно находится внутри класса ScriptFile.
yuranos
Хорошо, спасибо. Не могли бы вы привести пример того, что можно проверить, если в его полях есть String, Integer и Bean?
племянник,
2
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        

Я предполагаю, что эта @NotNullаннотация действительна, поэтому, если условие не требуется.

Мзлобецкий
источник
1

Просто добавить в ответе выше, в веб - приложении @validиспользуется там , где боб быть подтверждено также аннотацию проверки аннотаций , например @NotNull, @Email(спящий режим аннотаций) , поэтому , когда при получении ввода от пользователя значения могут быть проверены и связывания результат будет иметь подтверждение полученные результаты. bindingResult.hasErrors()сообщит, если какая-либо проверка не удалась.

Пунит Гоял
источник
1

Другой удобный аспект @Valid, не упомянутый выше, заключается в том, что (например, использование Postman для тестирования конечной точки) @Valid форматирует вывод неправильного вызова REST в форматированный JSON вместо капли с труднодоступным текстом. Это очень полезно, если вы создаете коммерчески доступный API для своих пользователей.

Шон Гилдеа
источник
1

Думаю, я знаю, к чему ведет ваш вопрос. И поскольку именно этот вопрос появляется в основных результатах поиска Google, я могу дать простой ответ о том, что делает аннотация @Valid.

Я представлю 3 сценария того, как я использовал @Valid

Модель:

public class Employee{
private String name;
@NotNull(message="cannot be null")
@Size(min=1, message="cannot be blank")
private String lastName;
 //Getters and Setters for both fields.
 //...
}

JSP:

...
<form:form action="processForm" modelAttribute="employee">
 <form:input type="text" path="name"/>
 <br>
 <form:input type="text" path="lastName"/>
<form:errors path="lastName"/>
<input type="submit" value="Submit"/>
</form:form>
...

Контроллер для сценария 1:

     @RequestMapping("processForm")
        public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
        return "employee-confirmation-page";
    }

В этом сценарии после отправки формы с пустым полем lastName вы получите страницу с ошибкой, так как вы применяете правила проверки, но не обрабатываете ее вообще.

Пример указанной ошибки: страница исключения

Контроллер для сценария 2:

 @RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee,
BindingResult bindingResult){
                return bindingResult.hasErrors() ? "employee-form" : "employee-confirmation-page";
            }

В этом сценарии вы передаете все результаты этой проверки в bindingResult, поэтому вам решать, что делать с результатами проверки этой формы.

Контроллер для сценария 3:

@RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
                return "employee-confirmation-page";
            }
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> invalidFormProcessor(MethodArgumentNotValidException ex){
  //Your mapping of the errors...etc
}

В этом сценарии вы по-прежнему не обрабатываете ошибки, как в первом сценарии, но вы передаете это другому методу, который позаботится об исключении, которое запускает @Valid при обработке модели формы. Проверьте это, посмотрите, что делать с отображением и всем остальным.

Подводя итог : @Valid сам по себе, не делая ничего, что запускает проверку аннотированных полей JSR 303 ( @NotNull, @Email, @Size и т. Д. ), Вам все равно нужно указать стратегию того, что делать с результатами указанной проверки.

Надеюсь, я смог кое-что прояснить для людей, которые могут с этим споткнуться.

Алан Бальдерас Санчес
источник