Spring验证器:同时具有注释和验证器实现

发布于 2024-11-29 14:18:12 字数 178 浏览 1 评论 0原文

是否可以同时拥有表单和注释约束的验证器?

例如,在表单对象中包含此字段:

@NotEmpty
private String date;

,然后在验证器中验证日期的模式。

我知道有模式注释,但我只是想看看是否可以使用这两种类型的验证。

Is it possible to have both a validator for a form and annotation constraints?

For example to have in a form object this field:

@NotEmpty
private String date;

but then validate the date's pattern in a validator.

I know there is the pattern annotation but I just want to see if I can use both types of validating.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心在旅行 2024-12-06 14:18:12

这里是链接访问一个非常好的网站,其中解释了如何将 JSR-303 验证器与 spring 验证器结合起来。

接下来我将介绍我的有效解决方案。希望有帮助。

我的抽象验证器:

import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.validation.Errors;


public abstract class AbstractValidator implements org.springframework.validation.Validator, ApplicationContextAware,
    ConstraintValidatorFactory {

@Autowired
private Validator validator;

private ApplicationContext applicationContext;

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}

public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
    Map<String, T> beansByNames = applicationContext.getBeansOfType(key);
    if (beansByNames.isEmpty()) {
        try {
            return key.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("Could not instantiate constraint validator class '" + key.getName() + "'", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Could not instantiate constraint validator class '" + key.getName() + "'", e);
        }
    }
    if (beansByNames.size() > 1) {
        throw new RuntimeException("Only one bean of type '" + key.getName() + "' is allowed in the application context");
    }
    return (T) beansByNames.values().iterator().next();
}

public boolean supports(Class<?> c) {
    return true;
}

public void validate(Object objectForm, Errors errors) {
    Set<ConstraintViolation<Object>> constraintViolations = validator.validate(objectForm);
    for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
        String propertyPath = constraintViolation.getPropertyPath().toString();
        String message = constraintViolation.getMessage();
        errors.rejectValue(propertyPath, "", message);
    }
    addExtraValidation(objectForm, errors);
}

protected abstract void addExtraValidation(Object objectForm, Errors errors);

}

实际的验证器:

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;

import ro.scorpionsoftware.demo3.dao.AbstractValidator;


@Component(value="doctorValidator")
public class DoctorValidator extends AbstractValidator {

    @Override
    protected void addExtraValidation(Object objectForm, Errors errors) {
        //perform typical validation
        //can autowire to context
    }


}

控制器:(最后它是 @Valid 与验证器的绑定)

@Controller
public class DoctorEditController {

@Autowired
    private DoctorValidator doctorValidator;

@RequestMapping(value = "/doctorEdit", method = RequestMethod.POST)
    public String processSubmit(
            @ModelAttribute("doctorForm") @Valid DoctorForm df,
            BindingResult result,
            ModelMap model) {
     ...
}
@InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(doctorValidator);
    }
}

在上下文中声明 JSR-303 验证器:

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

通过这种方法,您可以在实际验证器和验证器中获取上下文您想要实现的任何其他自定义注释。

Here is the link to a very good site where it's explained how you can combine the JSR-303 validator with the spring validator.

I'll present next my solution that works. Hope it helps.

My abstract Validator:

import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.validation.Errors;


public abstract class AbstractValidator implements org.springframework.validation.Validator, ApplicationContextAware,
    ConstraintValidatorFactory {

@Autowired
private Validator validator;

private ApplicationContext applicationContext;

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}

public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
    Map<String, T> beansByNames = applicationContext.getBeansOfType(key);
    if (beansByNames.isEmpty()) {
        try {
            return key.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("Could not instantiate constraint validator class '" + key.getName() + "'", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Could not instantiate constraint validator class '" + key.getName() + "'", e);
        }
    }
    if (beansByNames.size() > 1) {
        throw new RuntimeException("Only one bean of type '" + key.getName() + "' is allowed in the application context");
    }
    return (T) beansByNames.values().iterator().next();
}

public boolean supports(Class<?> c) {
    return true;
}

public void validate(Object objectForm, Errors errors) {
    Set<ConstraintViolation<Object>> constraintViolations = validator.validate(objectForm);
    for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
        String propertyPath = constraintViolation.getPropertyPath().toString();
        String message = constraintViolation.getMessage();
        errors.rejectValue(propertyPath, "", message);
    }
    addExtraValidation(objectForm, errors);
}

protected abstract void addExtraValidation(Object objectForm, Errors errors);

}

An actual Validator:

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;

import ro.scorpionsoftware.demo3.dao.AbstractValidator;


@Component(value="doctorValidator")
public class DoctorValidator extends AbstractValidator {

    @Override
    protected void addExtraValidation(Object objectForm, Errors errors) {
        //perform typical validation
        //can autowire to context
    }


}

A controller: (At the end it's the binding of the @Valid with the validator)

@Controller
public class DoctorEditController {

@Autowired
    private DoctorValidator doctorValidator;

@RequestMapping(value = "/doctorEdit", method = RequestMethod.POST)
    public String processSubmit(
            @ModelAttribute("doctorForm") @Valid DoctorForm df,
            BindingResult result,
            ModelMap model) {
     ...
}
@InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(doctorValidator);
    }
}

In context declare the JSR-303 validator:

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

With this approach you can get the context in both the actual validator and any other custom annotation you'd like to implement.

狼性发作 2024-12-06 14:18:12

您可以将注释组合在一起以使用多个验证器,所以它会是这样的。

@NotEmpty
@Pattern("") // not sure of syntax here
@Target(ElementType.METHOD)
@Retention( RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface DatePattern {
    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

You can compose together annotations to use multiple validators, so it would be something like this.

@NotEmpty
@Pattern("") // not sure of syntax here
@Target(ElementType.METHOD)
@Retention( RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface DatePattern {
    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文