background:
-
Our interface is a List object, and the data in the object basically has some annotations for basic data verification. How can we verify these basic rules?
-
When we import excel files for data entry, the data entry also has basic verification rules. At this time, how can we write less code and let the Validation framework help us complete these basic verifications?
With this question in mind, I shouted: Cuihua, serve sauerkraut.
text
First define the basic class of our Validation. The basic class has only one field: errMsg, which is used to store our prompt information when our verification fails:
@Data
public class ValidationBaseDTO {
private String errMsg;
}
Then define our test object class and make a simple DTO that integrates our verification basic class
@Data
public class ValidationTestDTO extends ValidationBaseDTO {
@NotEmpty(message = "用户名不允许为空!")
private String userName;
@NotEmpty(message = "用户code不允许为空")
private String userCode;
private int age;
}
Then write our verification tool class:
public class ValidationUtils{
public static <E, T extends ValidationBaseDTO> List<T> validate(Validator validator, E e) {
return validate(validator, e, Default.class);
}
public static <E, T extends ValidationBaseDTO> List<T> validate(Validator validator, E e, Class<?> groupClass) {
Set<ConstraintViolation<E>> set = validator.validate(e, groupClass);
if (CollectionUtils.isEmpty(set)) {
return null;
}
Map<String, List<ConstraintViolation<E>>> resultGroup = set.stream().collect(Collectors.groupingBy(item -> item.getPropertyPath().toString().substring(0, item.getPropertyPath().toString().indexOf("."))));
return resultGroup.entrySet().stream().map(item -> {
T targetObject = (T)item.getValue().get(0).getLeafBean();
String errMsg = String.join("|", item.getValue().stream().map(ConstraintViolation<E>::getMessage).collect(Collectors.toList()));
targetObject.setErrMsg(errMsg);
return targetObject;
}).collect(Collectors.toList());
}
}
Now that we have the verification tool class, we still need to create a Controller for testing.
@Slf4j
@RestController
@RequestMapping(value = "validation")
@AllArgsConstructor
public class ValidationTestController {
private final Validator validator;
@RequestMapping(value = "validationTest")
public CommonResult<List<ValidationTestDTO>> validationTest() {
// 例如我们通过Excel导入的数据有两条,属性全为空
ValidationTestDTO validationTestDTO1 = new ValidationTestDTO();
ValidationTestDTO validationTestDTO2 = new ValidationTestDTO();
List<ValidationTestDTO> validationTestDTOList = new ArrayList<>();
validationTestDTOList.add(validationTestDTO1);
validationTestDTOList.add(validationTestDTO2);
// 校验结果如果为空,则说明全部通过,如果不为空,则说明有的校验没有通过
List<ValidationTestDTO> resultList = ValidationUtils.validate(validator, new ValidatedList<>(validationTestDTOList));
return ResultUtil.success(resultList);
}
}
What I have to mention here is that Validator is instantiated in the Spring framework and is managed by the Spring framework. We can just inject it directly.
I almost forgot, if we need to verify the List, we also need to customize a ValidationList class, as follows:
public class ValidatedList<E> implements List<E>, Serializable {
public ValidatedList(List<E> eList){
this.list = eList;
}
@Valid
private List<E> list = new LinkedList<>();
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}
If this class is not defined and the List of our request parameters is passed directly, it will be invalid;
Start it and see the effect:
Add a comment on the image, no more than 140 words (optional)