3

나는 HibernateValidator 4.3.1을 사용하고 있습니다. 유효성 검사는 전체 응용 프로그램에서 의도 한대로 수행됩니다.봄 3.2.0 유효성 확인

나는 이러한 유형의 등 Joda-Time API

에 대한 유효 기간을 보장하기위한 전 세계적으로 이러한 텍스트 필드에 숫자 값 (double, int 등) 보장으로 유효성 검사를 수행하는 일부 사용자 지정 편집기를 등록 유효성 검사를 위해, false으로 allowEmpty 매개 변수를 설정하여 null/빈 값을 허용합니다. 특히 필드를 공백으로두면 별도의 사용자에게 친숙한 오류 메시지를 표시하기 위해 별도로 검증해야합니다.

따라서 HibernateValidator 및 사용자 지정 편집기를 사용하여 유효성을 검사하는 것 외에도 다음 유효성 검사 전략을 사용하려고합니다. 다시 말하지만, 이러한 유형의 유효성 검사는 사용자 정의 편집기 에 대해 등록 된 필드의 경우에만 공백으로 두었을 때입니다.

다음은 org.springframework.validation.Validator 인터페이스를 구현하는 클래스입니다. 이 자동 유선 특정 봄 컨트롤러 클래스에 될 수 있도록

package test; 

import org.springframework.stereotype.Component; 
import org.springframework.validation.Errors; 
import org.springframework.validation.ValidationUtils; 
import org.springframework.validation.Validator; 
import validatorbeans.TempBean; 

@Component 
public final class TempValidator implements Validator { 

    @Override 
    public boolean supports(Class<?> clazz) { 
     System.out.println("supports() invoked."); 
     return TempBean.class.isAssignableFrom(clazz); 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     TempBean tempBean = (TempBean) target; 

     System.out.println("startDate = " + tempBean.getStartDate() + " validate() invoked."); 
     System.out.println("doubleValue = " + tempBean.getDoubleValue() + " validate() invoked."); 
     System.out.println("stringValue = " + tempBean.getStringValue() + " validate() invoked."); 

     ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startDate", "java.util.date.nullOrEmpty.error"); 
     ValidationUtils.rejectIfEmptyOrWhitespace(errors, "doubleValue", "java.lang.double.nullOrEmpty.error"); 
    } 
} 

클래스는 @Component 주석으로 지정되어 있습니다. 디버깅 문은 사용자가 제공 한 입력을 기반으로 정확하게 표시됩니다.

다음은 컨트롤러 클래스입니다.

package controller; 

import customizeValidation.CustomizeValidation; 
import java.util.Map; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.validation.Valid; 
import javax.validation.groups.Default; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.validation.BindingResult; 
import org.springframework.validation.DataBinder; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import test.TempValidator; 
import validatorbeans.TempBean; 

@Controller 
public final class TempController { 

    @Autowired 
    private TempService tempService; 

    private TempValidator tempValidator; 

    public TempValidator getTempValidator() { 
     return tempValidator; 
    } 

    @Autowired 
    public void setTempValidator(TempValidator tempValidator) { 
     this.tempValidator = tempValidator; 
    } 

    @RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"}) 
    public String showForm(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { 
     return "admin_side/Temp"; 
    } 

    @RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"}) 
    public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) { 
     //tempValidator.supports(TempBean.class); 
     //tempValidator.validate(tempBean, errors); 

     DataBinder dataBinder = new DataBinder(tempBean); 
     dataBinder.setValidator(tempValidator); 
     dataBinder.validate(); 

     //errors=dataBinder.getBindingResult(); 
     if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) { 
      System.out.println("Validated"); 
     } 

     return "admin_side/Temp"; 
    } 
} 

나는 유효성 검사기라는

DataBinder dataBinder = new DataBinder(tempBean); 
dataBinder.setValidator(tempValidator); 
dataBinder.validate(); 

하여 봄 컨트롤러 클래스 자체 (내가 실제로 할)에서 검증을한다 호출하고있어하지만 예상되는 검증 이 수행되지 않습니다. 단지 내가 수동 (위 주석) 다음 문을 사용하여 검증을 호출하면

, 다음 유효성 검사가 수행

tempValidator.validate(tempBean, errors); 

. 따라서 유효성 검사기가 올바르게 작동하고 있다고 생각하지 않습니다. DataBinder과 함께 작동하지 않는 이유는 무엇입니까?

application-context.xml 파일에서이 빈은 간단히 다음과 같이 구성됩니다. TempValidator 클래스 내에 포함되어있는 test 패키지를 포함하여 아래와 같이

<bean id="tempValidator" class="test.TempValidator"/> 

이 많은 패키지를 자동으로 감지합니다.

<context:component-scan base-package="controller spring.databinder validatorbeans validatorcommands test" use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
    <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/> 
</context:component-scan> 

난 내 dispatcher-servlet.xml 파일에서

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 

을 넣어 노력했다.

여기에서 무엇을 간과하겠습니까?

+0

"dataBinder.validate();"줄에 휴식을 지정하면 그리고 단계적으로 들어가면 결국 어떤 유효성 검사기가 호출되는지 볼 수 있습니까? – CodeChimp

+0

@CodeChimp - 호출 된 발리 데이터는 질문 -'tempValidator'에 지정된 것입니다. – Tiny

답변

4

나는 당신이 달성하려고 무엇을 잘 이해한다면 - 빈 필드와 입력 잘못된 값을 구별 - 당신이 훨씬 더 간단한 방법 사용할 수 있습니다

public class MyBean { 

    @NotNull 
    @DateTimeFormat(pattern="dd.MM.yyyy HH:mm") 
    private DateTime date; 

    @NotNull 
    @Max(value=5) 
    private Integer max; 

    @NotNull 
    @Size(max=20) 
    private String name; 

    // getters, setters ... 
} 

컨트롤러 매핑 :

public void submitForm(@ModelAttribute @Valid MyBean myBean, BindingResult result) { 

    if (result.hasErrors){ 
     // do something} 
    else{ 
     // do something else 
    }   
} 

확인 메시지를 :

NotNull=Required field. 
NotNull.date=Date is required field. 
NotNull.max=Max is required field. 
Size=Must be between {2} and {1} letters. 
Max=Must be lower than {1}. 
typeMismatch.java.lang.Integer=Must be number. 
typeMismatch.org.joda.time.DateTime=Required format dd.mm.yyyy HH:mm 

스프링 구성 :

@Configuration 
public class BaseValidatorConfig { 

    @Bean 
    public LocalValidatorFactoryBean getValidator() { 

     LocalValidatorFactoryBean lvfb = new LocalValidatorFactoryBean(); 
     lvfb.setValidationMessageSource(getValidationMessageSource()); 
     return lvfb; 
    } 

    protected MessageSource getValidationMessageSource() {// return you validation messages ...} 
} 

필자는 필요한 경우 자세한 설명과 설명을 제공 할 수 있습니다.

+0

아! 나는이'LocalValidatorFactoryBean'을 사용하지 않았다. '@ NotEmpty','@ NotBlank','@ NotNull' 등의 주석은 독자적으로 작동합니다 (현재 사용하고있는 Spring 3.2.2에서). 이'LocalValidatorFactoryBean'은 무엇을위한 것인가? 이상,'@ Configuration'은 XML 설정보다 낫다. 고맙습니다. – Tiny

+2

'LocalValidatorFactoryBean'은 Spring MVC Validator와 JSR-303 Bean Validation 구현 간의 가교 역할을합니다. 예를 들어 그림과 같이 바인딩 결과에 바인딩하는 즉시 검증 (out-of-box) 유효성 검사 오류를 제공하는 컨트롤러 메소드에서'@ Valid' 주석을 사용할 수 있습니다 예제 코드에서는), 또한 Spring의 방식으로 유효성 검사 메시지 (오류 코드 메시지 확인자)를 사용하십시오. '@ Configuration'은 더 많은 유연성을 제공하며 오류가 발생하기 쉽지만 java 및 XML 구성에서 동일한 것을 얻을 수 있습니다. –

0

질문에서 언급 한 접근 방식이 작동하지 않는 이유를 모르겠습니다.나는 그것을 작동시키지 않았지만 이것을 통해 걸어 다니는이 document, 나는 나의 요구에 따라 나를 위해 일한 또 다른 접근법을 발견했다.

유효성 검사기를 @InitBinder 주석으로 지정된 메소드 내에 설정했습니다. @Valid 방법 인수가 두 가지 방법으로 구성 할 수 있습니다 발생 때 호출 docs

유효성 검사기 인스턴스에서

. 먼저 @ 컨트롤러의 @InitBinder 콜백 내에서 binder.setValidator (Validator)를 호출 할 수 있습니다. 는 그 작업에 버튼을 제출 W 연관된 경우 업데이트하거나 데이터베이스 예에 데이터를 삽입하는 동안

특히, 내 요구 사항에 유효성 검사 만 수행해야합니다 이것은 당신이 당 @Controller 클래스를 Validator에 인스턴스를 구성 할 수 있습니다 (내 응용 프로그램에이 두 작업 (삽입 및 업데이트)을위한 공통 단추가 있습니다 (이름은 btnSubmit).

유효성 검사는 다른 경우 (예 : 삭제 단추를 누를 때)에서 음소거해야합니다. 이 요구 사항을 충족하기 위해 다음과 같이 유효성 검사기를 등록했습니다. 이 상황에서

@InitBinder 
protected void initBinder(WebDataBinder binder, WebRequest webRequest) { 
    if (webRequest.getParameter("btnSubmit") != null) { 
     binder.setValidator(new TempValidator()); 
    } else { 
     binder.setValidator(null); 
    } 
} 

은 발리 - TempValidator 만 이름이 속성 btnSubmit는 클라이언트가 클릭되는 버튼을 제출할 때 설정됩니다.

자동 배선뿐만 아니라 xml 구성이 필요하지 않습니다.

예시적인 컨트롤러 클래스는 이제 다음과 같이 보입니다.

@Controller 
public final class TempController { 

    @Autowired 
    private TempService tempService; 

    @InitBinder 
    protected void initBinder(WebDataBinder binder, WebRequest webRequest) { 
     if (webRequest.getParameter("btnSubmit") != null) { 
      binder.setValidator(new TempValidator()); 
     } else { 
      binder.setValidator(null); 
     } 
    } 

    //Removed the @Valid annotation before TempBean, since validation is unnecessary on page load. 
    @RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"}) 
    public String showForm(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { 
     return "admin_side/Temp"; 
    } 

    @RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"}) 
    public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) { 
     if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) { 
      System.out.println("Validated"); 
     } 
     return "admin_side/Temp"; 
    } 
} 

initBinder() 방법에 WebRequest paramenter은 명백한로 전체 HTTP 요청을 처리하기위한 것은 아닙니다. 이는 범용 요청 메타 데이터를 사용하기위한 것입니다.

약 Javadocs 약 WebRequest.

웹 요청에 대한 일반 인터페이스. 주로 일반 웹 요청 인터셉터를 대상으로 일반적인 요청 메타 데이터에 대한 액세스를 제공하기 위해 요청을 실제로 처리하지 않습니다.

내가 다음에있을 수있는 잘못된 것이 있으면 친절하게 설명하거나 다른 대답을 추가하십시오.