数据校验@Validated(解决javax.validation.ConstraintViolationException问题)

前言

大多数项目中都需要后台对传过来的对象进行校验,比如手机号的位数,特殊字段不能为空等等。之前我们可能都是使用if…else…,今天我们了解一下validated

正文

单个对象

想要使用validated需要引入Jar包,有两个方式,选择一种即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.5.Final</version>
</dependency>

对于单个对象我们可以直接使用注解,在方法中使用案例:

  /**
     * 修改方法
     * @param students 学生类(需要校验的对象)
     * @param result 检验返回的结果信息
     * @return
     */
    @PutMapping()
    public String updateStudent(@RequestBody @Validated Student students, BindingResult result){
        /**
         * 查看校验结果,统计保存信息
         */
        Set<String> errors = new HashSet<>();
        // 如果 BindingResult 的 hasErrors 方法返回true,则表示有错误信息
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            // 遍历错误信息,返回给前端
            for (ObjectError error : allErrors) {
                errors.add(error.getDefaultMessage());
            }
        }
        if(errors.size() == 0){
            try {
                studentService.updateByPrimaryKeySelective(students);
                return "更新成功";
            } catch (Exception e) {
                e.printStackTrace();
                return "更新失败";
            }
        }else {
            return errors.toString();
        }
    }

实体中写上校验规则,基本的校验规则都有,大家可以自行Google一下,这里就不介绍了

    @NotEmpty(message = "ID不能为空")
    private Integer id;

    @Size(min = 5,max = 10,message = "名称需要在5到10个字符之间")
    private String name;

然后通过postman验证数据,可以跑出来我们想要的结果:
在这里插入图片描述

一组对象

我直接在接收参数把Student装到了List中,结果发现没有校验直接过了,看来这个方式不对。

public String updateStudent(@RequestBody @Validated List<Student> students, BindingResult result)

然后Google了一下,有文章说在Controller添加@Validated,在方法上添加@Valid,然后我运行发现报错,但是报错的内容里有我想要的信息,我就想到定义一个全局抛错类,抓住javax.validation.ConstraintViolationException 错误,把错误解析,拿出想要的信息,结果发现这个报错抓不住,这个方式也没走通。

@Validated
@CrossOrigin
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    /**
     * 修改方法
     * @param students 学生类(需要校验的对象)
     * @param result 检验返回的结果信息
     * @return
     */
    @PutMapping()
    public String updateStudent(@RequestBody @Valid List<Student> students, BindingResult result){
        /**
         * 查看校验结果,统计保存信息
         */
        Set<String> errors = new HashSet<>();
        // 如果 BindingResult 的 hasErrors 方法返回true,则表示有错误信息
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            // 遍历错误信息,返回给前端
            for (ObjectError error : allErrors) {
                errors.add(error.getDefaultMessage());
            }
        }
        if(errors.size() == 0){
            try {
                studentService.updateByPrimaryKeySelective(students.get(0));
                return "更新成功";
            } catch (Exception e) {
                e.printStackTrace();
                return "更新失败";
            }
        }else {
            return errors.toString();
        }
    }
}

在这里插入图片描述
再一次进行Google,查看了一下@Validated和@Valid的区别,发现@Validated用在方法入参上无法单独提供嵌套验证功能,但是单个对象是可以的,那我可以把List继承一下,写成一个对象。然后再调用的时候,还是和单个对象一样。这次得到了想要的结果,由于报错信息可能重复的太多,所以用Set接收的错误信息。

public class ValidList<E> implements List<E> {

    @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);
    }

    public List<E> getList() {
        return list;
    }

    public void setList(List<E> list) {
        this.list = list;
    }

}
@CrossOrigin
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService studentService;

    /**
     * 修改方法
     * @param students 学生类(需要校验的对象)
     * @param result 检验返回的结果信息
     * @return
     */
    @PutMapping()
    public String updateStudent(@RequestBody @Validated ValidList<Student> students, BindingResult result){
        /**
         * 查看校验结果,统计保存信息
         */
        Set<String> errors = new HashSet<>();
        // 如果 BindingResult 的 hasErrors 方法返回true,则表示有错误信息
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            // 遍历错误信息,返回给前端
            for (ObjectError error : allErrors) {
                errors.add(error.getDefaultMessage());
            }
        }
        if(errors.size() == 0){
            try {
                studentService.updateByPrimaryKeySelective(students.get(0));
                return "更新成功";
            } catch (Exception e) {
                e.printStackTrace();
                return "更新失败";
            }
        }else {
            return errors.toString();
        }
    }
}

在这里插入图片描述

结束

感觉写代码就是一步一步的尝试,错了就换一种是方式。
抓住自己有兴趣的东西,由浅入深,循序渐进地学。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值