JSR-303支持嵌套校验

pull/1/head
tanghc 5 years ago
parent eef82419c8
commit f787bdfab7
  1. 39
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ServiceParamValidator.java
  2. 45
      sop-common/sop-service-common/src/test/java/com/gitee/sop/servercommon/ValidatorTest.java

@ -6,10 +6,14 @@ import com.gitee.sop.servercommon.message.ServiceErrorEnum;
import com.gitee.sop.servercommon.message.ServiceErrorFactory;
import com.gitee.sop.servercommon.param.validation.ValidationGroupSequence;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
@ -23,6 +27,8 @@ public class ServiceParamValidator implements ParamValidator {
private static final String COMMA = ",";
private static Object[] EMPTY_OBJ_ARRAY = {};
private static final List<String> SYSTEM_PACKAGE_LIST = Arrays.asList("java.lang", "java.math");
private static javax.validation.Validator validator;
static {
@ -35,6 +41,11 @@ public class ServiceParamValidator implements ParamValidator {
if (obj == null) {
return;
}
// 先校验属性对象
List<Object> fields = listObjectField(obj);
if (!fields.isEmpty()) {
fields.forEach(this::validateBizParam);
}
Set<ConstraintViolation<Object>> set = validator.validate(obj, ValidationGroupSequence.class);
if (!CollectionUtils.isEmpty(set)) {
ConstraintViolation<Object> oneError = set.iterator().next();
@ -43,6 +54,34 @@ public class ServiceParamValidator implements ParamValidator {
}
}
private List<Object> listObjectField(Object object) {
List<Object> ret = new ArrayList<>();
ReflectionUtils.doWithFields(object.getClass(), field -> {
if (isCustomPackage(field.getType())) {
ReflectionUtils.makeAccessible(field);
ret.add(field.get(object));
}
});
return ret;
}
/**
* 字段类型所在package是否是自定义包
* @param fieldType 指定的类型
* @return true是自定义的
*/
private boolean isCustomPackage(Class<?> fieldType) {
if (fieldType.isPrimitive()) {
return false;
}
Package aPackage = fieldType.getPackage();
if (aPackage == null) {
return false;
}
String packageName = aPackage.getName();
return !SYSTEM_PACKAGE_LIST.contains(packageName);
}
private RuntimeException getValidateBizParamException(String errorMsg) {
String subCode = ServiceErrorEnum.ISV_PARAM_ERROR.getErrorMeta().getSubCode();
String[] msgToken = errorMsg.split(EQ);

@ -11,7 +11,9 @@ import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
/**
* @author tanghc
@ -24,10 +26,17 @@ public class ValidatorTest extends TestCase {
* 测试JSR-303注解校验顺序校验顺序: Group1~GroupN
*/
public void testValidate() {
serviceParamValidator.validateBizParam(new User("1", 1));
serviceParamValidator.validateBizParam(new User("Jim", 30));
}
public void testField() {
Manager manager = new Manager("Jim", 22);
Store store = new Store("仓库A", manager);
Goods goods = new Goods("Apple", new BigDecimal(50000), store);
serviceParamValidator.validateBizParam(goods);
}
@Data
@AllArgsConstructor
private static class User {
@ -36,7 +45,7 @@ public class ValidatorTest extends TestCase {
@NotBlank(message = "NotBlank", groups = Group1.class)
// 优先校验Group2
// 可交换下面Group2,Group3,看下校验顺序
@Length(min = 2, max = 20, message = "length must 10~20", groups = Group2.class)
@Length(min = 2, max = 20, message = "length must 2~20", groups = Group2.class)
@Pattern(regexp = "[a-zA-Z]*", message = "name must letters", groups = Group3.class)
private String name;
@ -45,4 +54,36 @@ public class ValidatorTest extends TestCase {
}
@Data
@AllArgsConstructor
static class Goods {
@NotBlank(message = "商品名称不能为空")
private String goodsName;
@Min(value = 1, message = "商品价格最小值为1")
private BigDecimal price;
@NotNull(message = "仓库不能为空")
private Store store;
}
@Data
@AllArgsConstructor
static class Store {
@NotBlank(message = "库存名称不能为空")
private String storeName;
@NotNull(message = "管理员不能为空")
private Manager manager;
}
@Data
@AllArgsConstructor
static class Manager {
@NotBlank(message = "管理员姓名不能为空")
private String name;
private int age;
}
}

Loading…
Cancel
Save