IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java参数校验 -> 正文阅读

[Java知识库]java参数校验

1、传统的参数校验方式

搭建项目结构

在这里插入图片描述

  • entity包下创建Deparement实体类
@Data
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class Department {
    /**
     * 主键
     */
    private Integer id;
    /**
     * 父级 ID
     */
    private Integer parentId;
    /**
     * 部门名臣
     */
    private String name;
    /**
     * 成立时间
     */
    private LocalDateTime createTime;
}
  • 传统校验方式(if - else)
 String errorPrefix = "添加失败,";
     if (department.getId() != null) {
         return errorPrefix + "实体参数异常";
     }
     if (department.getParentId() == null) {
         return errorPrefix + "父机构异常";
     }
     if (department.getParentId() < 0) {
         return errorPrefix + "父机构不存在";
     }
     if (department.getName() == null || department.getName().equals("")) {
         return errorPrefix + "名称不能为空";
     }
     if (department.getCreateTime() == null) {
         department.setCreateTime(LocalDateTime.now());
     }else {
         if (department.getCreateTime().isAfter(LocalDateTime.now())) {
            return errorPrefix + "创建时间不能大于当前时间";
        }
     }

       id           必须是 null (因为id是主键)
       parentId    不能为 null,必须大于 0
       name         不能为空,长度必须大于 0
       createTime   肯定不是未来的时间

2、开始使用validator

  • 引入validator的依赖,非web场景(这里开发场景使用web开发场景,所以我们不单独引入该依赖)。
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
        <version>2.1.9.RELEASE</version>
      </dependency>
  • 引入springboot的web开发场景,如下依赖:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  • 引入该依赖之后,该依赖就会引入上面validator的依赖。
    在这里插入图片描述

  • 更改上面的实体类Department
    在这里插入图片描述

  • 新建Vo包,在Vo包下创建ResultVo ,用于向前端返回统一的响应对象。

@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class ResultVO {
    /**
     * 后端是否处理成功
     */
    private boolean success;
    /**
     * 错误码
     */
    private String code;
    /**
     * 错误消息
     */
    private String msg;
    /**
     * 给前端的返回值
     */
    private Object data;

    public static ResultVO success() {
        ResultVO resultVO = new ResultVO();
        resultVO.setSuccess(true);
        return resultVO;
    }

    public static ResultVO success(Object data) {
        ResultVO resultVO = new ResultVO();
        resultVO.setSuccess(true);
        resultVO.setData(data);
        return resultVO;
    }

    public static ResultVO fail(ErrorCode errorCode) {
        ResultVO resultVO = new ResultVO();
        resultVO.setSuccess(false);
        resultVO.setCode(errorCode.getCode());
        resultVO.setMsg(errorCode.getMsg());
        return resultVO;
    }

    public static ResultVO fail(ErrorCode errorCode, Object data) {
        ResultVO resultVO = new ResultVO();
        resultVO.setSuccess(false);
        resultVO.setCode(errorCode.getCode());
        resultVO.setMsg(errorCode.getMsg());
        resultVO.setData(data);
        return resultVO;
    }
}
  • 创建一个enum包,该包下创建ErrorCode的枚举类,用来声明一些错误状态码,和错误信息。
    在这里插入图片描述
  • 新建controller包,在该包中创建DepartmentController类,该类声明如下测试方法。
    在这里插入图片描述
  • 目前的项目结构:
    在这里插入图片描述
  • 请求 DeparementController中的add方法。注意下面标红信息。
  1. add方法参数加了@Valid
  • postman测试,可以看到校验结果。查看到校验不通过的结果太难看了。下面进行异常处理。
    在这里插入图片描述
  • 新建exception包,在下面建一个CtrlAdvice的类,声明如下:
    在这里插入图片描述
  • 在上面的debug断点处,我们可以查看到异常类型为``
    在这里插入图片描述
  • 修改上面的异常,只获取重要的信息
    在这里插入图片描述
  • 这样看就清爽多了。
    在这里插入图片描述
  • 下面圈住的使用@Validated也是可以的。
    在这里插入图片描述

3、级联验证(一对一、一对多)

一对一

通俗来讲,就是一个对象里面有另一个对象。‘
在上面的entity包中新建实体类Employee,声明如下:

在这里插入图片描述

  • 级联验证就是,如果在一个实体类中有另一个实体类属性,而另一个实体类上也加了注解验证(Department实体类中,加了注解验证),那么,另一个实体类的属性上面的注解能否生效。
  • 新建一个EmployeeController,声明addList方法如下:
    在这里插入图片描述
  • 使用postman访问
    在这里插入图片描述
  • 解决上面Department的属性没有进行校验的问题。在Employee中的Department类型的属性上加@Valid注解。
    在这里插入图片描述
  • 使用postman再次访问,发现department上面的也可以被校验了。

在这里插入图片描述

一对多

通俗来讲,一对多就是一个实体类中,有一个另一个实体类的集合。如下面:
在这里插入图片描述

  • 使用postman进行访问,发现校验成功。
    在这里插入图片描述
    总结
    对于级联验证,只要在要验证的实体类属性上面添加@Valid注解就行。(对于一对多的有两种校验,一种是加在属性上,另一种加在List<@Valid Department>

4. 在service中做参数验证

情况一:不实现service接口

项目中,有可能参数校验不在Controller层中,而是在Service层进行参数校验。

  • 创建service层,并创建一个DepartmentService的实体类(这个实体类不实现接口,按照规范是:DepartmentServiceImplDepartmentService接口,这里不这样做,直接DepartmentService声明为class,而不是interface),声明如下:
    在这里插入图片描述
  • 更改DepartmentController如下:
    在这里插入图片描述
  • 使用postman工具,访问上面的接口:
    在这里插入图片描述
  • 发现保错了,在idea控制台查看,报错误信息javax.validation.ConstraintViolationException
    在这里插入图片描述
  • 在上面的exception包中的CtrlAdvice类中,声明一个异常处理,来捕获该异常(controller调用service,service层的异常抛给controller,添加的异常处理类,可以处理controller中的异常信息):
    在这里插入图片描述
  • 所以,下面写一个捕获该异常的方法,并且将上面的信息提炼出来,作为响应信息。

在这里插入图片描述

// Service层的校验抛出ConstraintViolationException
    @ExceptionHandler
    public ResultVO exceptionHandler(ConstraintViolationException ce){
        Map<String,String> collect =new HashMap<>();
        ce.getConstraintViolations().forEach(constraintViolation -> {
            PathImpl propertyPath = (PathImpl) constraintViolation.getPropertyPath();
            NodeImpl leafNode = propertyPath.getLeafNode();
            String name = leafNode.getName();
            String value = constraintViolation.getMessageTemplate();
            collect.put(name,value);
        });
        return ResultVO.fail(ErrorCode.PARAM_ERROR,collect);
    }
  • postman测试,查看响应结果
    在这里插入图片描述

情况二:实现service接口

  • 创建在service包下,创建IEmployee接口,在serviceimpl中创建EmployService实现类,该类实现IEmployee接口。此时项目结构如下:
    在这里插入图片描述
  • IEmployeeService方法声明如下:
    在这里插入图片描述
  • EmployeeService声明如下:
    在这里插入图片描述
  • EmployeeController声明如下,访问下面的方法
    在这里插入图片描述
  • postman请求结果
    在这里插入图片描述

总结: 对于在service层的校验,如果不实现接口的话,在类上加
@Validated注解,并且在验证的对象参数前加@Valid注解。对于有接口,有实现类的情况,@valid一定加在接口中抽象方法的形参前面,@Validated可以加在实现类上,也可以加在接口上,不能不加,我习惯加在实现类上。

5、方法上参数的验证(使用参数接收表单数据)

使用多个参数一一接收表单数据

  • EmployeeController实体类做出如下的更改,声明如下:
    在这里插入图片描述
  • name=刘,·age=250·,使用postman测试,查看异常信息。使用debug启动。
  • postman发送的参数如下:
    在这里插入图片描述
  • 发现上述异常信息,很工整,肯定是被哪个异常捕获了,下面以debug启动,在下面位置打上断点:
    在这里插入图片描述
  • debug进入了上面的异常方法中,也就是校验service层使用对象作为参数时,不满足条件所抛出的异常。
  • 上面的代码的可复制版:
/* 该方法可以捕捉校验不通过异常的地方一:
             Service层的校验抛出ConstraintViolationException(校验service层的方法中使用对象作为参数)示例:
             @PostMapping
             public ResultVO add(@Valid @RequestBody Employee){}  @RequestBody 不是必须的 前台可以直接是
                表单数据,到后台用对象接收时,也会被验证。
       该方法可以捕捉校验不通过异常的地方二:
            在Controller层直接写单的的参数,如果校验不通过,也会走该异常处理:示例
                @PutMapping
                public ResultVO add(@Length(min = 2,message = "名字不能少于两个字符") String name ,
                      @Max(value = 200,message = "年龄不能超过200") Integer age)
     */
    /* 该方法可以捕捉校验不通过异常的地方一:
             Service层的校验抛出ConstraintViolationException(校验service层的方法中使用对象作为参数)示例:
             @PostMapping
             public ResultVO add(@Valid @RequestBody Employee){}  @RequestBody 是必须的 前台如果是
                表单数据,到后台用对象接收时,不会被验证。
       该方法可以捕捉校验不通过异常的地方二:
            在Controller层直接写单的的参数,如果校验不通过,也会走该异常处理:示例
                @PutMapping
                public ResultVO add(@Length(min = 2,message = "名字不能少于两个字符") String name ,
                      @Max(value = 200,message = "年龄不能超过200") Integer age)
     */
    @ExceptionHandler
    public ResultVO exceptionHandler(ConstraintViolationException ce){
        Map<String,String> collect =new HashMap<>();
        ce.getConstraintViolations().forEach(constraintViolation -> {
            PathImpl propertyPath = (PathImpl) constraintViolation.getPropertyPath();
            NodeImpl leafNode = propertyPath.getLeafNode();
            String name = leafNode.getName();
            String value = constraintViolation.getMessageTemplate();
            collect.put(name,value);
        });
        return ResultVO.fail(ErrorCode.PARAM_ERROR,collect);
    }

使用对象接收多个表单数据

  • DepartmentController更改如下,下面的Department实体类还是上面的,上面加了注解校验:(可以看到,当参数是一个对象时,@valid或者@validated可以在该对象参数前面)
    在这里插入图片描述
    在这里插入图片描述

  • 不加任何异常处理方法,直接使用postman测试,查看控制台信息
    在这里插入图片描述

  • 发现是BindException异常,下面我们还在CtrlAdvice类中定义处理该异常的方法:
    在这里插入图片描述

  • 根据上面的信息,写出我们想要的结果的处理方法。
    在这里插入图片描述

  • 完成,在该方法上debug调试,看看能否得到想要的结果:postman测试结果如下:
    在这里插入图片描述

  • 异常处理方法,可copy版本:

 // 处理controller方法中,用对象接收表单数据,不满足校验注解,所抛出的异常信息
    @ExceptionHandler
    public ResultVO exceptionHandler(BindException b){
        List<ObjectError> allErrors = b.getBindingResult().getAllErrors();
        Map<String,String> collect = new HashMap<>();
        allErrors.forEach(error->{
            FieldError fieldError =(FieldError)error;
            collect.put(fieldError.getField(),fieldError.getDefaultMessage());
        });
        return ResultVO.fail(ErrorCode.PARAM_ERROR,collect);
    }

6、分组校验

就是校验你想校验的那个或者那些属性。

  • 修改上面的Employee实体类,声明如下:
    在这里插入图片描述

  • EmployeeController声明如下:
    在这里插入图片描述

  • 使用postman访问controller方法,响应信息如下:
    在这里插入图片描述

  • 更改EmployeeController中的方法,将@Validated中的group做出更改如下:
    在这里插入图片描述

  • postman结果:
    在这里插入图片描述

  • 查看该校验被哪个异常方法所捕获。
    在这里插入图片描述

在这里插入图片描述

  • 通过以上测试可以发现,如果进行了分组的话,只会对已经分组的属性进行校验(上面的name属性,id属性,那么如何校验没有分组的属性呢,如上面的age属性。结论,如果类中的属性,没有被分到组的话,则这些属性都属于是默认组)
  • 更改Employee实体类,如下:(未完。。。抽时间接着测试)
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-26 08:43:52  更:2021-11-26 08:44:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/20 10:22:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码