从JSON请求正文创建POJO字段时,带注释的spring验证有效。但是,当我手动(使用设置器)创建同一对象并想要触发验证时,我不确定该怎么做。
这是Registration类,它具有可以构建对象的Builder内部类。在构建方法中,我想触发弹簧验证。请滚动到底部并检查Builder.build()和Builder.valiate()方法以查看当前的实现。我正在使用javax.validation.Validator触发验证,但是如果可能的话,我更喜欢利用spring验证。
package com.projcore.dao; import com.projcore.util.ToString; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.hibernate.validator.constraints.NotEmpty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.validation.ConstraintViolation; import javax.validation.Valid; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.constraints.Size; import java.util.List; import java.util.Set; /** * The data transfer object that contains the information of a Registration * and validation rules for attributes. */ @JsonIgnoreProperties(ignoreUnknown = true) public final class Registration { private static final Logger LOGGER = LoggerFactory.getLogger(Registration.class); private String id; @NotEmpty @Size(max = 255) private String messageId; @NotEmpty @Size(max = 255) private String version; @Size(max = 255) private String system; public Registration() { } private Registration(Builder builder) { this.id = builder.id; this.messageId = builder.messageId; this.version = builder.version; this.system = builder.system; } public static Builder getBuilder() { return new Builder(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getMessageId() { return messageId; } public void setMessageId(String messageId) { this.messageId = messageId; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getSystem() { return system; } public void setSystem(String system) { this.system = system; } @Override public String toString() { return ToString.create(this); } /** * Builder pattern makes the object easier to construct in one line. */ public static class Builder { private String id; private String messageId; private String version; private String system; private Builder() {} public Builder id(String id) { this.id = id; return this; } public Builder messageId(String messageId) { this.messageId = messageId; return this; } public Builder version(String version) { this.version = version; return this; } public Builder system(String system) { this.system = system; return this; } public Registration build() { Registration entry = new Registration(this); // *** Would like to trigger spring validation here *** Set violations = validate(entry); if (violations.isEmpty()) return entry; else throw new RuntimeException(violations.toString()); } private Set validate(Registration entry) { Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<Registration>> constraintViolations = validator.validate(entry); return constraintViolations; } } }
验证在这里可以正常工作:
@RequestMapping(method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) Registration create(@RequestBody @Valid Registration registration)
解:
删除了Registraion.Builder.validate()。将Registraion.Builder.build()更新为:
public Registration build() { Registration entry = new Registration(this); return (Registration) ValidatorUtil.validate(entry); }
ValidationUtil.java
package projcore.util; import com.ericsson.admcore.error.InvalidDataException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.Errors; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; import javax.validation.Validation; import javax.validation.Validator; import java.util.Set; public class ValidatorUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorUtil.class); private static final Validator javaxValidator = Validation.buildDefaultValidatorFactory().getValidator(); private static final SpringValidatorAdapter validator = new SpringValidatorAdapter(javaxValidator); public static Object validate(Object entry) { Errors errors = new BeanPropertyBindingResult(entry, entry.getClass().getName()); validator.validate(entry, errors); if (errors == null || errors.getAllErrors().isEmpty()) return entry; else { LOGGER.error(errors.toString()); throw new InvalidDataException(errors.getAllErrors().toString(), errors); } } }
InvalidDataException.java
package projcore.error; import org.springframework.validation.Errors; /** * This exception is thrown when the dao has invalid data. */ public class InvalidDataException extends RuntimeException { private Errors errors; public InvalidDataException(String msg, Errors errors) { super(msg); setErrors(errors); } public Errors getErrors() { return errors; } public void setErrors(Errors errors) { this.errors = errors; } }
Spring提供了对JSR-303 Bean验证API的全面支持。这包括对将JSR-303实现作为Spring bean引导的便捷支持。这允许将javax.validation.Validator注入到你的应用程序中需要验证的任何地方。
使用LocalValidatorFactoryBean将默认的JSR-303验证程序配置为Spring Bean:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
上面的基本配置将触发JSR-303使用其默认引导机制进行初始化。诸如Hibernate Validator之类的JSR-303提供程序应该存在于类路径中,并且将被自动检测到。
5.7.2.1注入验证器
LocalValidatorFactoryBean implements both javax.validation.Validator and org.springframework.validation.Validator.你可以将对这两个接口之一的引用注入需要调用验证逻辑的bean中。
LocalValidatorFactoryBean implements both javax.validation.Validator and org.springframework.validation.Validator.
javax.validation.Validator如果你希望直接使用JSR-303 API,请插入参考:
javax.validation.Validator
// JSR-303 Validator import javax.validation.Validator; @Service public class MyService { @Autowired private Validator validator; }
注入引用,以了解org.springframework.validation.Validator你的bean是否需要Spring Validation API:
org.springframework.validation.Validator
// Spring Validator import org.springframework.validation.Validator; @Service public class MyService { @Autowired private Validator validator; }