使用@Validated校验List集合中数据失效

文章讲述了在使用SpringMVC的@Validated注解校验List集合时遇到的问题,即单个注解无法作用于整个集合。作者提供了三种解决方案,包括逐个校验、在Controller类上全局注解和自定义ValidableList进行校验,最后推荐使用自定义ValidableList以提高异常清晰度。
摘要由CSDN通过智能技术生成

使用@Validated校验List集合中数据失效

使用场景:

1,再做批量修改,或者单独修改数据时候,我们要对前端传递的值做一些校验,比如如下图
在这里插入图片描述

前端传递的实际值或者ip地址为空或者xxx字段为空,导致了之前正确的数据,变成了 非法数据,给后期运维添加工作量。。。效果不好

于是代码就写成如下:

    @PostMapping("/batchUpdateIndicatorDeviceCategorys")
    @ApiOperation("根据参数dto-批量修改告警设备或异常设备的数据值")
    public ResponseVo batchUpdateIndicatorDeviceCategorys(@RequestBody @Validated List<IndicatorDeviceScheduleDto> scheduleDtoList){
        return indicatorDeviceCategoryDetailsService.batchUpdateIndicatorDeviceCategorys(scheduleDtoList);
    }

在测试时候,发现明明在参数校验时候做了判断,但是集合里面比如id,或者currentUserNumber没有传递值,在调试时候还是提示更新成功,数据库里面比如之前修改人工号是有数据的,变成了null,这你要是上线了,运维不得炸。。。。。


@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IndicatorDeviceScheduleDto {

    /**
     * id
     */
    @TableId
    @NotNull(message = "id不能为空")
    private Long id;

    /**
     * 当前登录人工号或者唯一标识
     */
    @NotNull(message = "当前登录人工号或者唯一标识不能为空")
    private String currentUserNumber;

    /**
     * 实际指标值 保留2位小数
     */
    @NotNull(message = "实际指标值,不能为空请重新输入")
    private Double actualValue;

}

原因分析:

1,个人理解 可能有误:@Validated只能对单个起到作用,对list集合起不到,list是java.util包下面的,你这里加个注解肯定不行的了,java.utils包不能自己对参数进行校验,没有这么智能。

解决方案:

方案一:

传统方式,对list集合进行遍历,然后对每个值进行校验,如果有异常 抛出异常,这个方法可行但是代码量臃肿。

方案二:

在controller类上面添加注解 @Validated ,在controller 传参列表里面添加 @Valid

    @Api(tags = "xxxx 管理")
    @Validated
    @RestController
    @RequestMapping("aaa/indicatorDeviceCategoryDetailsController")
    public class IndicatorDeviceCategoryDetailsController {
    
    @PostMapping("/batchUpdateIndicatorDeviceCategorys")
    @ApiOperation("根据参数dto-批量修改告警设备或异常设备的数据值")
    public ResponseVo batchUpdateIndicatorDeviceCategorys( @RequestBody @Valid List<IndicatorDeviceScheduleDto> scheduleDtoList){
        return indicatorDeviceCategoryDetailsService.batchUpdateIndicatorDeviceCategoryDetails(scheduleDtoList);
  }

}

再次调试,scheduleDtoList集合里面的Dto的currentUserNumber设置为空,抛异常了,异常是xxx异常,但是异常过于繁多,消息提示不够友好,可以满足校验参数情况,错误信息详情如下
在这里插入图片描述

方案三:

我们可以写一个集合实现list,代码如下,在controller类上面不用加@Validated注解,在controller使用自定义ValidableList集合,对list进行封装,就可以对scheduleDtoList做参数校验处理。

个人推荐方案三: 优点,异常清晰明了
代码如下:

    @Api(tags = "xxxx 管理")
    @RestController
    @RequestMapping("aaa/indicatorDeviceCategoryDetailsController")
    public class IndicatorDeviceCategoryDetailsController {
    
    @PostMapping("/batchUpdateIndicatorDeviceCategorys")
    @ApiOperation("根据参数dto-批量修改告警设备或异常设备的数据值")
     public ResponseVo batchUpdateIndicatorDeviceCategoryDetails(@RequestBody @Validated ValidableList<IndicatorDeviceScheduleDto> scheduleDtoList){
        return indicatorDeviceCategoryDetailsService.batchUpdateIndicatorDeviceCategoryDetails(scheduleDtoList);
  }
}

import lombok.Data;
import org.jetbrains.annotations.NotNull;

import javax.validation.Valid;
import java.util.*;
import java.util.function.UnaryOperator;

/**
 * @author psd 用于校验指定的List集合里面的数据
 */
@Data
public class ValidableList<E> implements List<E> {

    @Valid
    private List<E> list = new ArrayList<>();

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

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

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }

    @NotNull
    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }

    @NotNull
    @Override
    public Object[] toArray() {
        return list.toArray();
    }

    @NotNull
    @Override
    public <T> T[] toArray(@NotNull 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(@NotNull Collection<?> c) {
        return list.containsAll(c);
    }

    @Override
    public boolean addAll(@NotNull Collection<? extends E> c) {
        return list.addAll(c);
    }

    @Override
    public boolean addAll(int index, @NotNull Collection<? extends E> c) {
        return list.addAll(index, c);
    }

    @Override
    public boolean removeAll(@NotNull Collection<?> c) {
        return list.removeAll(c);
    }

    @Override
    public boolean retainAll(@NotNull Collection<?> c) {
        return list.retainAll(c);
    }

    @Override
    public void replaceAll(UnaryOperator<E> operator) {
        List.super.replaceAll(operator);
    }

    @Override
    public void sort(Comparator<? super E> c) {
        List.super.sort(c);
    }

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

    @NotNull
    @Override
    public ListIterator<E> listIterator() {
        return list.listIterator();
    }

    @NotNull
    @Override
    public ListIterator<E> listIterator(int index) {
        return list.listIterator(index);
    }

    @NotNull
    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }

    @Override
    public Spliterator<E> spliterator() {
        return List.super.spliterator();
    }
}


**错误信息详情如下: **简单明了
在这里插入图片描述

温馨提示,无论使用方案二或者方案三,都要写下面统一异常处理,要不然拦截不了异常

import com.dx.major.common.bean.ResponseVo;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import lombok.extern.slf4j.Slf4j;

/**
 * @author psc 统一参数校验异常处理类
 */
@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {

    /**
     * 处理@Validated 参数校验异常
     * 
     * @param exception
     *            异常类型
     * @return 异常信息
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseVo exceptionHandler(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        StringBuilder builder = new StringBuilder();
        if (result.hasErrors()) {
            result.getAllErrors().forEach(p -> {
                FieldError fieldError = (FieldError) p;
                log.warn("Bad Request Parameters: dto entity [{}],field [{}],message [{}]", fieldError.getObjectName(), fieldError.getField(),
                        fieldError.getDefaultMessage());
                builder.append(fieldError.getDefaultMessage());
            });
        }
        return ResponseVo.paramError(builder.toString());
    }
}

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值