Spring Boot @Validated 和Javax的@Valid配合使用

news2024/11/25 5:21:07

一、@Validated 和@Valid有什么用

@Validation 和@Valid 常常配合使用对传输的参数进行数据校验的注解,并通过配置全局异常处理器进行合理化的提示,增加用户的体验

并且@Validated可以通过分组来指定什么时候触发什么样的参数校验(这里看一下就行,下面有说什么是分组)

二、为什么要使用@Validated 和@Valid的思考?

其实不用这两个注解也可以完成对传输的参数进校验,那样我们就需要一直写if语句进行判断 ,如果不为xxx,抛出异常,然后进行捕获处理  

但是当多处都用到的一样的传输参数的时候,我们每次都需要写一些重复的if进行校验,其实代码是不优雅的。因此有了这两个组件来帮我们进行传输参数的校验。

三、使用方法

3.1 引入pom

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--validator请求参数校验-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

       <!--测试方法-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
	</dependencies>

3.2 写实体类加入一写校验注解

常用的校验注解

     

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    private String name;

    @NotNull(message = "年龄不能为空")
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;

}

3.3 编写controller层进行测试 (请求参数是对象)

注意需要在请求参数的前面加上@Valid注解

统一返回类

package com.sofwin.validator.config;

import lombok.Data;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:34
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 统一返回参数
 */
@Data
public  class  BaseResult<T> {
    private int code;
    private String message;
    private T data;

    public BaseResult() {
    }

    public BaseResult(int code, T data,String message) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> BaseResult<T> build(int code, T data, String message) {
        return new BaseResult<T>(code,data,message);
    }

    public static <T> BaseResult<T> build( T data, BaseResult resultCodeEnum) {
        return new BaseResult<T>(resultCodeEnum.getCode(),data,resultCodeEnum.getMessage());
    }

    public static <T> BaseResult<T> ok(T data) {
        return new BaseResult<>(20000,data,"success");
    }

    public static <T> BaseResult<T> fail(T data) {
        return new BaseResult<>(50000,data,"error");
    }



}

controller 

package com.sofwin.validator.controller;

import com.sofwin.validator.config.BaseResult;
import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.domain.UserR;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

/**
 * @packageName: com.sofwin.validator.controller
 * @author: wentao
 * @date: 2023/9/4 21:14
 * @version: 1.0
 * @description: 请求参数校验
 */

@RestController
@RequestMapping("validator")
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
   
}

正常参数

 

非正常参数 

我们发现没有提示我们在实体中message中写的提示信息,是因为我们没有设置全局异常处理器

,它只是在控制台返回了提示信息 

2023-09-05 21:24:03.305  WARN 20924 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.sofwin.validator.config.BaseResult com.sofwin.validator.controller.ValidatorController.validPostTest(com.sofwin.validator.domain.UserR): [Field error in object 'userR' on field 'age': rejected value [1111]; codes [Range.userR.age,Range.age,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userR.age,age]; arguments []; default message [age],200,1]; default message [最小为1岁,最大为200岁]] ]

全局异常处理器

package com.sofwin.validator.config;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
import org.slf4j.Logger;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:28
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 全局异常处理器
 */

@RestControllerAdvice
@Slf4j
public class GlobExceptionHandeler {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    //valid参数校验出现异常
    @ExceptionHandler(BindException.class)
    public BaseResult bindException(BindException e) {
        logger.error("valid参数校验出现异常");
        System.out.println(e);
        return BaseResult.build(441,null,e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    //validated参数校验出现异常
    @ExceptionHandler(ConstraintViolationException.class)
    public BaseResult constraintViolationException(ConstraintViolationException e) {
        logger.error("validated参数校验出现异常");

        return BaseResult.build(441,null,e.getLocalizedMessage().split(":")[1].trim());
    }

    @ExceptionHandler(Exception.class)
    public BaseResult constraintViolationException(Exception e) {
        logger.error("Exception");
        return BaseResult.build(441,null,e.getLocalizedMessage());
    }
}

 加入全局异常处理器后非正常参数返回结果:

3.4 当参数不是一个对象

 一定要在controller上加入@Validated才生效

@RestController
@RequestMapping("validator")
@Validated
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
  

    @GetMapping("/validGet1")
    public BaseResult validGetTest( @NotBlank(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }
}

 

3.5 分组

当我们在特定情况下才进行参数校验才进行分组,例如只有当我们插入的时候我们进行校验,其他时候不进行参数的校验,这个时候就可以使用分组

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

   

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;



}

其中InsertGroup和UpdateGroup只是一个普通的接口


public interface InsertGroup {

}



public interface UpdateGroup {

}

 

controller

package com.sofwin.validator.controller;

import com.sofwin.validator.config.BaseResult;
import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.domain.UserR;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * @packageName: com.sofwin.validator.controller
 * @author: wentao
 * @date: 2023/9/4 21:14
 * @version: 1.0
 * @description: 请求参数校验
 */

@RestController
@RequestMapping("validator")
@Validated
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
    @PostMapping("/validPost2")
    public BaseResult validPostTest2(@Validated(InsertGroup.class) @RequestBody UserR user ) {
        return BaseResult.ok(user);
    }

    @GetMapping("/validGet1")
    public BaseResult validGetTest( @NotBlank(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }

    @GetMapping("/validGet2")
    public BaseResult validGetTest2(@Validated(InsertGroup.class) @NotNull(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }
}

测试

validPost2、validGet2

validPost2 

validGet2

3.6 自定义注解

当它提供的注解我们没有办法解决我们的问题的时候,我们就可以自定义注解

定义注解Status

package com.sofwin.validator.config;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:52
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 自定义校验注解
 */
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//自己写校验规则
@Constraint(validatedBy = {StatusConstraint.class})
//元注解 可以分组使用,如果不写定义相同的注解会出现错误
@Repeatable(Status.List.class)
public @interface Status {

    String[] statusType() default {};

    String message() default "状态传递有误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload()  default {};

   @Target({ElementType.FIELD,ElementType.PARAMETER})
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
    @interface List {
       Status[] value();
   }

}

校验规则

package com.sofwin.validator.config;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 22:04
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 自定义校验柜子
 */
public class StatusConstraint implements ConstraintValidator<Status,Integer> {

    List<String> statusType;

    /**
     * 一般进行初始化
     * @param constraintAnnotation
     */
    @Override
    public void initialize(Status constraintAnnotation) {
        String[] strings = constraintAnnotation.statusType();
        statusType = Arrays.asList(strings);
    }

    /**
     *
     * @param value  参数的值
     * @param context
     * @return  true 通过不抛出异常  fasle不通过抛出异常
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value !=null) {
            if (!statusType.contains(String.valueOf(value))) {
                return  false;
            }
            return  true;
        }
        return false;
    }
}

测试

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Status(statusType = {"1","2"})
    private Integer status;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;



}

controller 

  @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }

正常传参

非正常传参

 3.7 当出现类中出现嵌套的情况

当出现嵌套的情况只需要在类的属性中在加一个注解@Valid

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Status(statusType = {"1","2"})
    private Integer status;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;


    //嵌套使用valid才能生效
    @Valid
    private List<SonUser> sonUserList;
}
package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class SonUser {

    @NotBlank(message = "sonName不能为空")
    private String sonName;

}

controller

  @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }

四、 总结 

@Valid:没有分组的功能。

@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上

@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/977589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。

基于FPGA的FIR数字滤波器设计&#xff08;quartus和vivado程序都有&#xff09;。 附&#xff1a; 1.配套quartus从MATLAB系数生成直到仿真成功说明文档。 2.配套仿真出波形&#xff08;图1&#xff09;的视频。

ShareCRM罗一立:立足香港联通国际,出海正当时

IDC数据显示&#xff0c;2022年中国企业级应用SaaS市场规模达41.6亿美元&#xff1b;而根据另一组数据&#xff0c;同一年全球SaaS市场规模已突破千亿美元。 一边是国内趋于白热化的竞争环境&#xff0c;一边是拥有广阔市场空间的海外“流奶与蜜之地”。近两年&#xff0c;出海…

手写Mybatis:第14章-解析和使用ResultMap映射参数配置

文章目录 一、目标&#xff1a;ResultMap映射参数二、设计&#xff1a;ResultMap映射参数三、实现&#xff1a;ResultMap映射参数3.1 工程结构3.2 ResultMap映射参数类图3.3 添加类型处理器3.3.1 日期类型处理器3.3.2 类型处理器注册机 3.4 存放映射对象3.4.1 结果标志3.4.2 结…

数据结构笔记:PR四叉树

1 基本介绍 在PR四叉树中&#xff0c;每个节点代表一个矩形区域&#xff0c;并且每个节点要么没有子节点&#xff0c;要么有四个子节点&#xff0c;分别代表该矩形区域的四个象限 2 数据结构 PR四叉树的每个节点通常包含以下几个元素&#xff1a; 区域&#xff08;矩形&…

go语言基本操作--四

面向对象编程 对于面向对象编程的支持go语言设计得非常简洁而优雅。因为&#xff0c;Go语言并没有沿袭面向对象编程中诸多概念&#xff0c;比如继承(不支持继承&#xff0c;尽管匿名字段的内存布局和行为类似继承&#xff0c;但它并不是继承)、虚函数、构造函数和析构函数、隐…

16字节协议的串口通信

1.协议要求 协议为帧传输&#xff0c;一共16字节。主要是2字节的固定帧头 EB 90&#xff0c;2字节的帧计数(用来计数发出的帧),10字节的数据和2字节的校验位 帧头&#xff1a;2字节&#xff0c;固定值 8’HEB、8’H90 帧计数&#xff1a;2字节&#xff0c;用来说明发出去帧是…

esp32s3实现openmv

演示参考下方视频 源码链接在视频末尾获取点击查看视频 摄像头引脚配置 烧录配置

【Linux】进程基础概念【下篇】

目录 1. 基本概念 2. 常见环境变量 常见环境变量指令 &#xff08;1. PATH &#xff08;2. HOME &#xff08;3. SHELL 3.环境变量的组织形式 &#xff08;1&#xff09;通过代码如何获取环境变量 &#xff08;2&#xff09;普通变量与环境变量的区别 &#xff08;3&…

Vue+NodeJS实现邮件发送

一.邮箱配置 这里以QQ邮箱为例,网易邮箱类似. 设置->账号 二.后端服务搭建 index.js const express require(express) const router require(./router); const app express()// 使用路由文件 app.use(/,router);app.listen(3000, () > {console.log(server…

大学大创项目:手机室内AR导航APP项目思路

文章目录 一、最初的项目思路二、建图和定位分离的项目思路1、建图2、定位 个人见解&#xff0c;如有错误&#xff0c;请多包涵 一、最初的项目思路 在大创项目的开始&#xff0c;将手机确定为应用设备&#xff0c;传感器确定为相机。 由于知识储备的原因&#xff0c;在头一次…

Jenkins实现基础CI操作

操作截图 代码push进gitlab Jenkins拉取gitlab代码 在容器内Jenkins拉取的代码

app备案ios的公钥和md5的获取方法

最近app需要备案才能上架了 但是app备案的时候&#xff0c;特别是ios备案的时候需要提供app的公钥和md5比较头大&#xff0c;无论是android系统还是ios系统&#xff0c;都需要提供证书的公钥和md5。 获取这个公钥和md5真的好麻烦&#xff0c;好像各种工具都没有提供获取这些信…

java数据结构1------深入学习ArrayList

目录 一、概念 二、源码分析 1、属性 2、构造器 ①空构造 ②指定初始容量&#xff08;initialCapacity&#xff09;构造器 ②参数为Collection的构造器 3、常用方法 ①public boolean add(E e) ②public void add(int index, E element) ③其他方法 三、总结 一、概念…

【ARM AMBA5 CHI 入门 12 -- CHI 总线学习 】

文章目录 介绍CHI 特点Layers of the CHI architectureTopology Node TypeTransaction 分类Transaction 路由SAM 介绍Node ID 节点间数据怎么传输的呢&#xff1f; 介绍 CHI 的全称是 Coherent Hub Interface。所以从名字就能看出&#xff0c;CHI要解决什么问题了。按照惯例&a…

思维导图怎么变成ppt?4个思维导图一键生成ppt的方法

做好的思维导图如何变成一份ppt&#xff1f;本文罗列了4个可行方法&#xff0c;一起来看看吧。 一 直接复制粘贴 这是最简单的方法&#xff0c;虽然这样可能会花费一些时间&#xff0c;但可以确保内容排版和布局与你想要的一致。当然&#xff0c;我们大可使用更高效的方法。…

NLP(2)--Transformer

目录 一、Transformer概述 二、输入和输出 三、Encoder 四、Decoder 五、正则化处理 六、对于结构的改进&#xff1f; 七、AT vs NAT 八、Cross-attention 一、Transformer概述 Transformer模型发表于2017年Google团队的Attention is All you need这篇论文&#xff0c;…

七、SSM 框架整合

目前已经学习了 MyBatis 框架&#xff0c;Spring 框架&#xff0c;以及Spring MVC 框架。现阶段学习将这三个框架整合到一起&#xff0c;实现简单的前后端交互的曾删改差功能页面。 Mybatis 框架主要负责数据库的操作问题&#xff0c;以及数据回显。该框架将 SQL 与 Jav…

Browserslist 信息和配置使用整理

我们可以在各种前端工程看到 Browserslist 的配置身影&#xff0c;看似简单但实际上可能会有暗坑导致线上兼容问题&#xff0c;借此文来整理下 Browserslist 的信息。 Browserslist 是由 Autoprefixer 团队维护的一个开源项目&#xff0c;用于自动处理 CSS 和 JavaScript 文件…

opencv识别一张图片的多个红框,并截取红框的内容

需求 需要获取图片的红框的内容&#xff0c;实体的图片我就不放了 获取红框 先截取获得图片的多个轮廓 import cv2 import numpy as np # 加载图像并转换为灰度图像 image cv2.imread(image6.jpg) gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用高斯模糊以减…

基本的 Linux 命令以及 Linux 目录结构

目录 什么是Linux&#xff1f; ls - 列出文件和目录 pwd - 显示当前工作目录 cd - 切换目录 mkdir - 创建目录 touch - 创建空文件 rm - 删除文件和目录 cp - 复制文件和目录 mv - 移动和重命名文件和目录 文件系统基础 Linux 操作系统是开源且强大的操作系统&…