使用自定义注释进行弹簧形式验证

时间:2016-06-28 07:32:57

标签: spring validation annotations

我在spring4.2.3和基于hibernate5.1.0的项目中使用自定义注释进行表单验证。

1)我的注释界面如下所示

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.rapidtech.rapidtechorganic.custom.logic.UnitConstraintValidator;
@Documented
@Constraint(validatedBy = UnitConstraintValidator.class)
@Target( {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IsUnit {

String message() default "Please Enter a valid UNIT e.g. kg,litre,ton";

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

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

}

2)我的逻辑类UnitConstraintValidator看起来像这样

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;

public class UnitConstraintValidator implements ConstraintValidator<IsUnit, String> {

@Override
public void initialize(IsUnit unit) {
    // TODO Auto-generated method stub

}

@Override
public boolean isValid(String unit, ConstraintValidatorContext cxt) {

    if(unit.equals(null) || unit == null){
        return false;
    }

    if(unit.matches("kg|KG|Kg|Litre|litre|lt|ton|Ton")){

        return true;

    }

    return false;
}

}

3)我正在使用自定义注释的Model类

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
public class Lot implements java.io.Serializable{

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long lotId;

@Size(min=5,max=30)
private String lotNumber;

@IsUnit
private String lotName;

@OneToOne(cascade = {CascadeType.ALL})
private ProductAvailable productAvailable;

public long getLotId() {
    return lotId;
}
public void setLotId(long lotId) {
    this.lotId = lotId;
}
public String getLotNumber() {
    return lotNumber;
}
public void setLotNumber(String lotNumber) {
    this.lotNumber = lotNumber;
}
public String getLotName() {
    return lotName;
}
public void setLotName(String lotName) {
    this.lotName = lotName;
}
public ProductAvailable getProductAvailable() {
    return productAvailable;
}
public void setProductAvailable(ProductAvailable productAvailable) {
    this.productAvailable = productAvailable;
}



}

4)我正在使用自定义注释的ProductAvailable模型类

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.validation.constraints.Size;
import com.rapidtech.rapidtechorganic.custom.annotation.IsUnit;

@Entity
public class ProductAvailable implements java.io.Serializable {
/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long productAvailableId;

@Size(min=2,max=30,message="ahha ahha ahha")
private String productAvailableName;

@IsUnit
private String productAvailableUnit;
private double productAvailableUnitTransportationCharge;
private double productAvailableUnitLabourCharge;
private double productAvailableUnitOtherCharge;
private long productAvailableQuantity;
private double productAvailableUnitPrice;

@OneToOne
private Lot lot;


public long getProductAvailableId() {
    return productAvailableId;
}
public void setProductAvailableId(long productAvailableId) {
    this.productAvailableId = productAvailableId;
}
public String getProductAvailableName() {
    return productAvailableName;
}
public void setProductAvailableName(String productAvailableName) {
    this.productAvailableName = productAvailableName;
}
public long getProductAvailableQuantity() {
    return productAvailableQuantity;
}
public void setProductAvailableQuantity(long productAvailableQuantity) {
    this.productAvailableQuantity = productAvailableQuantity;
}
public double getProductAvailableUnitPrice() {
    return productAvailableUnitPrice;
}
public void setProductAvailableUnitPrice(double productAvailableUnitPrice) {
    this.productAvailableUnitPrice = productAvailableUnitPrice;
}

public String getProductAvailableUnit() {
    return productAvailableUnit;
}
public void setProductAvailableUnit(String productAvailableUnit) {
    this.productAvailableUnit = productAvailableUnit;
}
public double getProductAvailableUnitTransportationCharge() {
    return productAvailableUnitTransportationCharge;
}
public void setProductAvailableUnitTransportationCharge(double productAvailableUnitTransportationCharge) {
    this.productAvailableUnitTransportationCharge = productAvailableUnitTransportationCharge;
}
public double getProductAvailableUnitLabourCharge() {
    return productAvailableUnitLabourCharge;
}
public void setProductAvailableUnitLabourCharge(double productAvailableUnitLabourCharge) {
    this.productAvailableUnitLabourCharge = productAvailableUnitLabourCharge;
}
public double getProductAvailableUnitOtherCharge() {
    return productAvailableUnitOtherCharge;
}
public void setProductAvailableUnitOtherCharge(double productAvailableUnitOtherCharge) {
    this.productAvailableUnitOtherCharge = productAvailableUnitOtherCharge;
}
public Lot getLot() {
    return lot;
}
public void setLot(Lot lot) {
    this.lot = lot;
}




}

我正在使用hibernate-validator4.1.0.Final和JSR 303进行验证。

正如您所看到的,我有两个模型类Lot和ProductAvailable,它们映射了OneToMany,这意味着一个Lot可以有许多ProductAvailable。

我的问题是:我的自定义注释 IsUnit Lot 类中正常工作,但在类 ProductAvailable 的情况下抛出异常。

例外是:

javax.validation.ConstraintViolationException: Validation failed for classes [com.rapidtech.rapidtechorganic.model.ProductAvailable] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Please Enter a valid UNIT e.g. kg,litre,ton', propertyPath=productAvailableUnit, rootBeanClass=class com.rapidtech.rapidtechorganic.model.ProductAvailable, messageTemplate='Please Enter a valid UNIT e.g. kg,litre,ton'}
]
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)
org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205)
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
com.rapidtech.rapidtechorganic.dao.AbstractDao.save(AbstractDao.java:30)
com.rapidtech.rapidtechorganic.dao.lot.LotDaoImpl.save(LotDaoImpl.java:22)
com.rapidtech.rapidtechorganic.service.LotServiceImpl.save(LotServiceImpl.java:25)
com.rapidtech.rapidtechorganic.controller.LotController.saveLotController(LotController.java:59)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

我的Controller类看起来像这样:

@RequestMapping(value = "/saveLot", method = RequestMethod.POST)
public ModelAndView saveLotController(@Valid @ModelAttribute(value="lot") Lot lot, BindingResult result) {
    ModelAndView model;

    if(result.hasErrors()){
        model =   new ModelAndView("saveLotForm");
    }
    else {
    Services lotService = (LotServiceImpl) appContext.getBean("lotServiceImpl");
    lot.getProductAvailable().setLot(lot);
    lotService.save(lot);
    model = new ModelAndView("Success");
    model.addObject("successMessage","Lot "+lot.getLotName()+" Saved Successfully!");
    }
    return model;
}

任何帮助都会得到应用,并提前致谢。

1 个答案:

答案 0 :(得分:0)

在做了一些研究后,我找到了解决方案。所有我需要将 @Valid 注释放在产品可用

productAvailable 成员变量上

然后它会检查我的 ProductAvailable 类的验证。

How to Validate different model class into one form using Spring MVC JSR-303 Validator