@Valid ek açıklaması Baharda neyi gösterir?


88

Aşağıdaki örnekte, ScriptFileparametre bir @Validaçıklama ile işaretlenmiştir .

Ne geliyor @Validek açıklama yapmak?

@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();        
}    

Yanıtlar:


63

Doğrulama amaçlı.

Doğrulama Kullanıcı girdisini ona bağladıktan sonra bir modeli doğrulamak yaygındır. Spring 3, JSR-303 ile bildirim temelli doğrulama için destek sağlar. Sınıf yolunuzda Hibernate Validator gibi bir JSR-303 sağlayıcısı varsa bu destek otomatik olarak etkinleştirilir. Etkinleştirildiğinde, bir Controller yöntemi parametresine @Valid ek açıklaması ekleyerek doğrulamayı tetikleyebilirsiniz: Gelen POST parametrelerini bağladıktan sonra, AppointmentForm doğrulanır; bu durumda, tarih alanı değerinin boş olmadığını ve gelecekte olduğunu doğrulamak için.


Daha fazla bilgi için buraya bakın:
http://blog.springsource.com/2009/11/17/spring-3-type-conversion-and-validation/


37

Yukarıdaki cevaplara ek olarak, aşağıdakilere bir göz atın. AppointmentFormbireyin datekolon ek açıklamaları çift açıklandı. (Bu durumda ve ) @Validüzerinde doğrulamaları tetikleyen ek açıklamaya sahip olarak . Bu ek açıklamalar farklı JSR-303 sağlayıcılarından (örn. Hibernate, Spring..vb) gelebilir.AppointmentForm@NotNull@Future

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

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }

1
Benzer bir kodum var. Parametreden kaldırmıştım @Valid, ApplicationFormancak yine de doğrulamalar date(ayarlandı null) alanında tetikleniyordu . Lütfen açıkla.
lupchiazoem

18

@ValidSpring ile hiçbir ilgisi yoktur. Bean Validation spesifikasyonunun bir parçasıdır (bunlardan birkaçı vardır, en sonuncusu 2017'nin ikinci yarısından @Validitibaren JSR 380'dir ), ancak çok eskidir ve JSR 303'ten türetilmiştir.

Hepimizin bildiği gibi, Spring genel olarak tüm farklı JSR'ler ve java kitaplıkları ile entegrasyon sağlamada çok iyidir (JPA, JTA, Caching vb. Düşünün) ve tabii ki bu adamlar da doğrulama ile ilgilendi. Bunu kolaylaştıran temel bileşenlerden biri MethodValidationPostProcessor'dur .

Sorunuzu cevaplamaya çalışmak - @Validkarmaşık bir grafiği doğrulamak istediğinizde ve bir nesnenin üst düzey öğelerini değil, sözde doğrulama basamaklaması için çok kullanışlıdır. Ne zaman daha derine inmek istersen, kullanmalısın @Valid. JSR'nin dikte ettiği şey budur. Spring, bazı küçük sapmalarla uyumlu olacaktır (örneğin , RestController yöntemi ve doğrulama çalışmaları @Validatedyerine koymayı denedim @Valid, ancak aynısı normal bir "servis" fasulyesi için geçerli olmayacak).


Ama neyi doğrular?
yeğenim

Lütfen ayrıntı verin, @nephewtom. Neyi açıklığa kavuşturmak istersiniz?
yuranos

JSR 303: Bean Validation, beanvalidation.org/1.0/spec okudum, ancak yine de hangi doğrulamanın gerçekleştirileceğini anlamıyorum ScriptFile scriptFile.
yeğen

ScriptFile içinde muhtemelen bir sürü alan vardır ve bu alanların üzerinde de açıklamalar vardır. Doğrulamanın başladığı yer burasıdır. Orijinal soruya göre ScriptFile sınıfının içinde tam olarak ne olduğu net değildir.
yuranos

Tamam teşekkürler. Bir String, bir Integer ve a Bean'in olduğu alanları neyin doğrulayabileceğine dair bir örnek verebilir misiniz?
nephewtom

17

IIRC @Valid bir Bahar ek açıklaması değil, bir JSR-303 ek açıklaması (Bean Doğrulama standardıdır). Yaptığı şey, temelde yönteme gönderdiğiniz verilerin geçerli olup olmadığını kontrol etmektir (sizin için scriptFile'ı doğrular).


2
"Sizin için scriptFile'ı doğrulayacak" ne anlama geliyor? Boş olmadığını, bazı sözdizimi veya içeriğin olduğunu kontrol edin. Başka bir deyişle, neyi ve nasıl doğrular? Kullanıcı bir şey uygulamalı mı? Bununla ilgili nereden bilgi alabilirim? Teşekkür ederim!
yeğenim

Lütfen @ nephewtom'un sorusunu cevaplayın, "neye karşı" olan eksik ana nokta ile doğrulamak için yeterli cevap değil?
monami

2
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        

Sanırım bu @NotNullek açıklama, bu nedenle koşul gerekmiyorsa geçerlidir.


2

Sanırım sorunun nereye gittiğini biliyorum. Ve bu soru, Google'ın arama ana sonuçlarında açılan soru olduğu için, @Valid ek açıklamasının ne yaptığına dair sade bir cevap verebilirim.

@ Valid'i nasıl kullandığıma dair 3 senaryo sunacağım

Model:

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>
...

Senaryo 1 için kontrolör:

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

Bu senaryoda, formunuzu boş bir lastName alanıyla gönderdikten sonra, doğrulama kurallarını uyguladığınız ancak bununla hiçbir şekilde ilgilenmediğiniz için bir hata sayfası alırsınız.

Bahsedilen hataya örnek: İstisna sayfası

Senaryo 2 için kontrolör:

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

Bu senaryoda, bu doğrulamadan tüm sonuçları bindingResult'a geçiriyorsunuz, bu nedenle bu formun doğrulama sonuçlarıyla ne yapacağınıza karar vermek size kalmış.

Senaryo 3 için kontrolör:

@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
}

Bu senaryoda, ilk senaryodaki gibi hataları hala işlemiyorsunuz , ancak bunu , form modelini işlerken @Valid'in tetiklediği istisnayı dikkate alacak başka bir yönteme aktarıyorsunuz . Kontrol bu haritalama ve bütün bu ne yapacağını görmem.

Özetlemek gerekirse : @Valid, JSR 303 ek açıklamalı alanların ( @NotNull, @Email, @Size, vb. ) Doğrulamasını tetikleyen başka bir şey yapmadan kendi başına ne yapmanız gerektiğine dair bir strateji belirlemeniz gerekir. söz konusu doğrulamanın sonuçları ile.

Umarım bununla karşılaşabilecek insanlar için bir şeyi açıklığa kavuşturabilmişimdir.


1

Yukarıdaki yanıta @validek olarak, doğrulanacak fasulyenin ayrıca doğrulama notları ile açıklandığı bir web uygulamasında kullanılır @NotNull, örneğin @Email(hazırda bekletme notu), böylece kullanıcıdan girdi alırken değerler doğrulanabilir ve bağlama sonucu doğrulamaya sahip olacaktır. Sonuçlar. bindingResult.hasErrors()herhangi bir doğrulamanın başarısız olup olmadığını söyleyecektir.


1

@Valid'in yukarıda bahsedilmeyen bir başka kullanışlı yönü (yani: bir uç noktayı test etmek için Postman'ı kullanmak) @Valid, zar zor okunabilen bir metin bloğu yerine, yanlış bir REST çağrısının çıktısını biçimlendirilmiş JSON'a biçimlendirmesidir. Kullanıcılarınız için ticari olarak tüketilebilir bir API oluşturuyorsanız bu çok kullanışlıdır.


1

Nasıl olduğu hakkında daha fazla ayrıntı eklemek istedim @ValidÖzellikle baharda çalıştığına .

İlkbaharda doğrulama hakkında bilmek isteyeceğiniz her şey https://reflectoring.io/bean-validation-with-spring-boot/ adresinde açıkça ve ayrıntılı olarak açıklanmıştır , ancak yanıtı nasıl kopyalayacağım@Valid bağlantıda çalıştığına iner.

@ValidAçıklama bunları doğrulamak için bir dinlenme kontrol yönteminde değişkenler eklenebilir. Doğrulanabilen 3 tür değişken vardır:

  • istek gövdesi,
  • yol içindeki değişkenler (ör. / foos / {id} içindeki id) ve,
  • sorgu parametreleri.

Öyleyse şimdi ... bahar nasıl "geçerli kılıyor"? Bir sınıfın alanlarına belirli açıklamalar ekleyerek bunlara kısıtlamalar tanımlayabilirsiniz. Ardından, bu sınıfın bir nesnesini, kısıtlamaların karşılanıp karşılanmadığını kontrol eden bir Doğrulayıcıya iletirsiniz.

Örneğin, şöyle bir denetleyici yöntemim olduğunu varsayalım:

@RestController
class ValidateRequestBodyController {

  @PostMapping("/validateBody")
  ResponseEntity<String> validateBody(@Valid @RequestBody Input input) {
    return ResponseEntity.ok("valid");
  }

}

Bu, bir yanıt gövdesini alan bir POST isteğidir ve bu yanıt gövdesini bir sınıfa eşleştiriyoruz Input.

İşte sınıf Input:

class Input {

  @Min(1)
  @Max(10)
  private int numberBetweenOneAndTen;

  @Pattern(regexp = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$")
  private String ipAddress;
  
  // ...
}

@Valid ek açıklaması, spring'e gidip denetleyiciye aktarılan verileri doğrulamasını söyler ve tam sayının numberBetweenOneAndTenbu minimum ve maksimum ek açıklamalar nedeniyle 1 ile 10 arasında olduğunu kontrol eder . Ayrıca, iletilen ip adresinin açıklamadaki normal ifadeyle eşleşip eşleşmediğini de kontrol eder.

yan not: normal ifade mükemmel değildir .. 255'ten büyük 3 basamaklı sayılar geçebilirsiniz ve yine de normal ifadeyle eşleşir.


Bir sorgu değişkenini ve yol değişkenini doğrulamanın bir örneğini burada bulabilirsiniz:

@RestController
@Validated
class ValidateParametersController {

  @GetMapping("/validatePathVariable/{id}")
  ResponseEntity<String> validatePathVariable(
      @PathVariable("id") @Min(5) int id) {
    return ResponseEntity.ok("valid");
  }
  
  @GetMapping("/validateRequestParameter")
  ResponseEntity<String> validateRequestParameter(
      @RequestParam("param") @Min(5) int param) { 
    return ResponseEntity.ok("valid");
  }
}

Bu durumda, sorgu değişkeni ve yol değişkeni sadece karmaşık sınıflar yerine tamsayılar olduğundan, kısıtlama açıklamasını @Min(5)kullanmak yerine doğrudan parametrenin üzerine koyarız @Valid.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.