• Spring Boot 之配置文件


    application.properties

    • SpringBoot 的核心配置文件

      • 配置文件名:application.properties | yml

      • 不能改变

    • 扩展名

      • properties;数据格式:k=v
      • yaml、yml;数据格式:k: v
        • application.propertiesapplication.yml
      • 当两种格式配置文件同时存在
        • properties 优先级最高
        • 在父工程中配置文件加载顺序
          • yml → yaml → properties
          • 后加载的配置文件会将先加载的配置覆盖掉
    • 定义 SpringBoot 的相关设置

      • properties 格式

        # 设置端口号
        server.port=80
        # 设置访问应用的上下文路径;访问路径在 /root下
        server.servlet.context-path=/root
        
        • 1
        • 2
        • 3
        • 4
      • yml 格式

        • 一种能直观被计算机识别的数据序列化格式
        # 下级换行空格,赋值冒号空格
        server:
         port: 80
         servlet:
          context-path: /root
        # 行内写法
        server: { port: 80, servlet: {context-path: /js} }
        # 数组
        array:
          - cat
          - dog
        # 行内数组
        array: [cat, dog]
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
    • 配置文件中所有能配置的项都和配置类中属性相关

      • 所有配置文件中能配置的属性都是在 xxxxProperties 类中封装
        • 配置文件的配置可以参照某个功能对应的属性类
      • xxxxAutoConfigurartion:自动配置类,给容器中添加组件
        • 配置类都有默认值
      • xxxxProperties:封装配置文件中相关属性
        • 在配置文件中配置自定义配置
        • 通过配置文件的自动加载赋值到配置类中的属性使生效
      • 配置文件中设置 debug=true 可查看生效的配置
    yaml
    语法格式
    • 语法

      • 大小写敏感

      • 使用缩进表示层级关系

      • 缩进时不允许使用 Tab 键,只允许使用空格

      • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

      • # :注释,从这个字符一直到行尾,都会被解析器忽略

    • k: v:字面量直接写

      • 字符串默认不用加上 ''""

      • "":双引号不会转义字符串里面的特殊字符

        • 特殊字符会作为本身想表示的意思
      • '':单引号会转义特殊字符

        • 特殊字符最终只是一个普通的字符串数据
    • 支持的数据结构有三种

      • 对象:键值对的集合,又称为映射 / 哈希 / 字典

      • 数组:一组按次序排列的值,又称为序列/ 清单 / 列表

      • 纯量:单个的、不可再分的值

    区块
    • yml 支持不同开发环境写在同一个文件

      • 每个块用 ---- 隔开等价于多个配置文件
    • 缩进/区块 以及内置(inline)两种格式,表示清单(数组)和散列表

      --- # 缩进数组
      - Casablanca
      - North by Northwest
      - Notorious
      
      --- # 内置数组
      [milk, pumpkin pie, eggs, juice]
      
      --- # 散列表
      person:
         name: John Smith
         age: 33
         
      --- # 內置
      person: {name: John Smith, age: 33}
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    多行文字
    段落换行
    • 配置和显示都按句子换行

      1. 直接使用 \n 换行

        • \n 在显示的时候换行,配置行末的 \ 让字符串换行继续写

          • 必须有,否则第二行行首会多一个空格
        • 必须使用双引号定义字符串,不能用单引号

          • 单引号不支持 \n 换行
          string: "I am a coder.\n\
                   My blog is didispace.com."
                   
          # 输出效果
          # I am a coder.
          # My blog is didispace.com
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
      2. |

        • |:文中自动换行,文末新增一空行

        • |+:文中自动换行,文末新增两空行

        • |-:文中自动换行,文末不新增行

        • 换行字符会被转换成空白字符,而引领空白字符则会被自动消去

        • ---
          string: |
            I am a coder.
          ---
          string: |+
            I am a coder.
          --- 
          string: |-
            I am a coder.
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
    显示不换行
    • 配置按段落,显示在一行

      1. 直接换行写

        • # 单双引号都可
          string: 'I am a coder.
                   My blog is didispace.com.'
          
          • 1
          • 2
          • 3
      2. >

        • >:文中不自动换行,文末新增一空行

        • >+:文中不自动换行,文末新增两空行

        • >-:文中不自动换行,文末不新增行

        • ---
          string: >
            I am a coder.
          ---
          string: >+
            I am a coder.
          ---
          string: >-
            I am a coder.
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
    示例
    # 分为两种不同环境
    server:
      port: 8081
    spring:
      profiles:
        active: prod 		# 激活对应的环境配置
    ---
    server:
      port: 8083
    spring:
      profiles: dev 		# 指定属于哪个环境
     
    --- # 数据结构可以用类似大纲的缩进方式呈现
    receipt:     Oz-Ware Purchase Invoice
    date:        2012-08-06
    customer:
        given:   Dorothy
        family:  Gale   
        
    items:
        - part_no:   A4786
          descrip:   Water Bucket (Filled)
          price:     1.47
          quantity:  4 
          
        - part_no:   E1628
          descrip:   High Heeled "Ruby" Slippers
          size:      8
          price:     133.7
          quantity:  1 
          
    bill-to:  &id001				# 锚点
        street: | 
                123 Tornado Alley
                Suite 16
        city:   East Centerville
        state:  KS
        	
    ship-to:  *id001   				# 引用
    
    specialDelivery:  >
        Follow the Yellow Brick
        Road to the Emerald City.
        Pay no attention to the
        man behind the curtain.
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 顶层由七个键值组成
      • 键值 items 两个元素构成的数组(或称清单)
        • 清单中的两个元素同时包含四个键值的散列表
    • 文件中重复的部分处理
      • 使用锚点( & )和引用( * )标签
      • bill-to 散列表的内容复制到 ship-to 散列表
    • 可以在文件中加入选择性的空行,以增加可读性
    • 在一个文件中可同时包含多个文件
      • 使用 --- 分隔
    • 选择性的符号 ... 可以用来表示文件结
      • 在利用流的通信中非常有用
      • 可以在不关闭流的情况下,发送结束信号

    配置文件位置

    • 高优先级的配置文件会覆盖低优先级的配置文件

    • SpringBoot 会从四个位置全部加载主配置文件

      1. 使用命令行参数在启动项目的时候来指定配置文件的新位置
        • 指定配置文件和默认加载的配置文件共同起作用形成互补配置
      2. 通过 spring.config.location 改变默认的配置文件位置
      java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
      
      • 1
    • 按优先级顺序排序:

      1. file:./config
        • 默认当项目的根路径下的 config 目录中
      2. file:./
        • 当前项目根目录下直接创建
      3. classpath:/config/
        • resource 目录下的 cofig 目录中
      4. classpath:/:默认生成配置文件位置
        • resource 目录下直接创建
        • 或同级的 src/main/java 目录下
    • 目录结构

      • 项目名
        	-	src
        		-	main
        			-	java
        				- 	第四位置
        			-	resource
        				-	static
        				-	templates
        				-	config
        					-	第三位置
        				-	第四位置
        		-	test
        	-	target
        	-	pom.xml
        	-	config
        		-  application.properties:第一位置
        	-	第二位置
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17

    多环境配置

    • 项目开发中经历多个阶段:开发、测试、上线 等

      • 各阶段所处的环境配置有所不同,例如:端口、上下文根、数据库等
    • 为了方便在不同环境间切换 SpringBoot 提供了多环境配置

      • 为每一个环境创建一个配置文件
        • 必须为每一个环境单独创建配置文件
      • 文件命名必须是:application-环境标识.properties | yml
        • 例如:application-dev.properties 开发环境
    • 在主配置文件指定使用的配置文件

      • spring.profiles.active=dev
        
        • 1
    • yml 格式配置支持多文档模块

      • 使用 --- 将同一个文档中分隔为多个文档
        • 只需要创建一个配置文件即可配置不同环境
      • 不同开发环境写在同一个文件
        • 新增 Profile
        • 2.4 版本重命名 spring.profilesspring.config.activate.on-profile
      --- # 主配置文件
      server:
        port: 82
      spring:
        profiles:
          active: dev  		# 指定使用开发环境配置文件
      
      --- # 开发环境配置文件
      server:
        port: 83
      spring:
        config:
          activate:
            on-profile: dev  	# 开发环境,不同环境配置文件标识
            
      --- # 生产环境配置文件
      server:
        port: 84
      spring:
        config:
          activate:
            on-profile: pro	# 生产环境
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

    自定义K-V

    • 配置文件中可以自定义 key

      • 在赋值引用时可以引用框架的 key 或 自定义key
      demo:
        name: 张三${random.uuid}
        age: 19
        map:
          demo1: 18
          demo2: 20
        hobby:
          --- rap
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    @Value
    • @Value(${key})

      • key 来自配置文件
      • 当指定使用了其他配置文件时
        • 获取 key 优先从指定的配置文件搜索
        • 若该文件没有定义此 key 到主配置文件搜索
        • 若仍没有则会报错
      # 主配置文件
      spring:
        profiles:
          active: dev  		# 指定使用开发环境配置文件,dev是自定义名
      server:
        servlet:
          context-path: /demo
        port: 8081
      name: 张三   			   # 开发环境配置文件不存在这两个key,故使用这两个 key 赋值
      age: 18
      address: 北京
      
      ---
      # 开发环境配置文件
      server:
        port: 8001  			 # 使用这个端口号赋值
        servlet:
          context-path: /test
      address: 上海				# 使用这个地址赋值
      
      ---
      # 以下属于Java类中注解引用配置文件赋值
      @Value("${name}")  			# 张三
      private String name;
      @Value("${age}")   			# 18
      private Integer age;
      @Value("${address}")  		# 上海
      private String address;
      @Value("${server.port}")  	# 8001
      private Integer port;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    占位符

    Spring Boot 配置文件支持占位符:${}

    随机数
    ${random.value}
    ${random.int}
    ${random.long}
    ${random.int(10)}
    ${random.int[1024,65536]}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    默认值
    • 占位符获取之前配置的值
    • 如果没有可以用 : 指定默认值
    person.last-name=张三${random.uuid}
    person.age=${random.int}
    person.birth=2017/12/15
    person.boss=false
    person.maps.k1=v1
    person.maps.k2=14
    person.lists=a,b,c
    # 使用默认值
    person.dog.name=${person.hello:hello}_dog  
    person.dog.age=15
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    @ConfigurationProperties

    作用
    • 将整个文件映射成一个对象
      • 用于自定义配置较多的情况
      • 同时将整个类中属性赋值
        • 根据属性名和 key 一致进行赋值
        • set 注入,类中必须存在 set 方法
    • 会提示添加依赖项
      • 添加后可以显示自定义 key 的引用信息
    • 属性:prefixvalue:指定配置文件中 key 的前缀
      • 这两个属性作用一样
    • 对比 @Value
      • 可以批量注入对象属性,@value 需要一个一个赋值
      • 支持松散绑定,@Value 支持
        • 配置文件中属性名和类属性名可不完全一致
        • Java 中对于驼峰命名法,可用原名或使用 - 代替驼峰
          • 如:lastName 属性,yml 中使用 lastName 或 last-name 都可正确映射
      • 不支持SpEL,@Value 不支持
        • SpEL 使用 #{...} 作为定界符 ,
          • 所有在大括号中的字符都将被认为是 SpEL
        • 通过 SpEL
          • 通过 bean 的 id 对 bean 进行引用
          • 调用方式以及引用对象中的属性
          • 计算表达式的值
          • 正则表达式的匹配
      • 支持 JSR303 数据校验,@Value 不支持
      • 支持复杂类型封装,@Value 不支持
    示例

    yaml 配置文件定义类属性值

    # 配置文件中定义 Person 类属性 使用 person 作为前缀
    person:								# 对象
      boss: false
      maps:  							# Map 集合
        k1: v1  
        k2: 14
      lists:							# List 集合
        - name: d1
      	  age: ${demo.map.demo1:20}22	# demo1值存在时赋值,否则赋值20;追加默认值22
        - name: d2
          age: 3
        - {name: d3,age: 4}   			# 行内写法
      birth: 2017/12/15       			# Date
      dog:				    			# 对象属性
        name: p_dog
        age: 15
      age: 13
      last-name: 张三${random.uuid}	   # 使用随机uuid,松散绑定属性
      arr: [s1,s2,s3]					# 数组,行内写法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    实体类中引用配置文件中的定义

    @Component  
    @Data       						//自动生成set、get、toString()、equals()、hashCode() 等 方法
    @NoArgsConstructor   				//声明生成无参构造
    @AllArgsConstructor  				//声明生成有参构造
    @ConfigurationProperties(prefix = "person")
    public class Person {
        private String lastName;
        private Integer age;
        private Boolean boss;
        private Date birth;
        private Map<String,Object> maps;
        private List<Dog> lists;
        private Dog dog;
        private String[] arr;@Component 
    @Data       
    @NoArgsConstructor   
    @AllArgsConstructor  
    @ConfigurationProperties(prefix = "demo")
    public class Dog {
        private String name;
        private Integer age;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    JSP303
    • JSR:Java Specification Requests,Java 规范提案
      • 指向JCP(Java Community Process) 提出新增一个标准化技术规范的正式请求
      • 任何人都可以提交 JSR,以向 Java 平台增添新的 API 和服务
      • JSR 已成为 Java 界的一个重要标准
    • JSR-303 是JAVA EE 6 中的一项子规范
      • 叫做 Bean Validation
    @Validated
    • 进行数据格式校验
    • 空检查
      • @Null:被注释的元素必须为 null
      • @NotNull:被注释的元素必须不为 null
        • 无法查验 "" 字符串
      • @NotBlank:被注释字符串必须不为 null 且被 trim() 后长度大于 0
        • 只针对字符串且会去掉前后空格
      • @NotEmpty:被注释的字符串的必须非空
    • Booelan 检查
      • @AssertTrue:被注释的元素必须为 true
      • @AssertFalse:被注释的元素必须为 false
    • 长度检查
      • @Size(max, min) :被注释的元素的长度必须在指定的范围内
        • Array、Collection、Map、String 类型元素
      • @Length(min=, max=):被注释的字符串的长度必须在指定的范围内
    • 日期检查
      • @Past:被注释的元素必须是一个过去的日期
      • @Future:被注释的元素必须是一个将来的日期
    • 正则验证
      • @Pattern:被注释的元素必须符合指定的正则表达式
        • regexp:正则表达式
        • flags:指定 Pattern.Flag 的数组,表示正则表达式的相关选项
    • 数值检查
      • 建议使用在 StirngInteger 类型
        • 不建议使用在 int 类型
          • 表单值为 "" 时无法转换为int
          • Stirng 可为 ""Integer 可为 null
      • @Min(value):被注释的元素必须是值大于等于指定的最小值的数字
      • @Max(value):被注释的元素必须是值小于等于指定的最大值的数字
      • @DecimalMin(value):被注释的元素必须是值大于等于指定的最小值的数字
        • 包含精度
      • @DecimalMax(value):被注释的元素必须是值小于等于指定的最大值的数字
        • 包含精度
      • @Digits:被注释的元素必须是一个数字,其值必须在可接受的范围内
        • interger:指定整数精度
        • fraction:指定小数精度
      • @Range(min=, max=) :被指定的元素必须在合适的范围内
        • @Range(min=10000, max=50000, "message=range.bean.wage")
      • @Valid:递归的对关联对象进行校验
        • 如果关联对象是集合或者组
          • 对其中的元素进行递归校验
        • 如果是一个map
          • 对其中的值部分进行校验
    • 特殊格式
      • @CreditCardNumber:信用卡验证
      • @Email:被注释的元素必须是电子邮箱地址
        • null,不进行验证,算通过验证
      • @ScriptAssert(lang= ,script=, alias=) :JS 验证
      • @URL(protocol=,host=, port=,regexp=, flags=)
        • 被注解元素必须是 url
    使用
    • 需要校验的参数 Bean 前添加 @Valid 开启校验功能

      • 校验的 Bean 后添加一个 BindingResult

      • BindingResult 封装了前面 Bean 的校验结果

      • @RestController
        @RequestMapping("/user")
        public class UserController {
        
            @PostMapping("")
            public Result save (@Valid User user , BindingResult bindingResult)  {
                if (bindingResult.hasErrors()) {
                    Map<String , String> map = new HashMap<>();
                    bindingResult.getFieldErrors().forEach( (item) -> {
                        String message = item.getDefaultMessage();
                        String field = item.getField();
                        map.put( field , message );
                    } );
                    return Result.build( 400 , "非法参数 !" , map);
                }
                return Result.ok();
            }
        
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
    • 异常的统一处理

      • 参数校验不通过时,会抛出 BingBindException 异常

      • 可以进行统一异常处理中,不用在每个需要参数校验的地方都用 BindingResult 获取校验结果

      • @Slf4j
        @RestControllerAdvice(basePackages = "com.itwolfed.controller")
        public class GlobalExceptionControllerAdvice {
        
            @ExceptionHandler(value= {MethodArgumentNotValidException.class , BindException.class})
            public Result handleVaildException(Exception e){
                BindingResult bindingResult = null;
                if (e instanceof MethodArgumentNotValidException) {
                    bindingResult = ((MethodArgumentNotValidException)e).getBindingResult();
                } else if (e instanceof BindException) {
                    bindingResult = ((BindException)e).getBindingResult();
                }
                Map<String,String> errorMap = new HashMap<>(16);
                bindingResult.getFieldErrors().forEach((fieldError)->
                        errorMap.put(fieldError.getField(),fieldError.getDefaultMessage())
                );
                return Result.build(400 , "非法参数 !" , errorMap);
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
    • 分组解决校验

      • 新增和修改对于实体的校验规则是不同的

        • 例:id 自增,新增时 id 要为空,修改则必须不为空
          • 新增和修改若用的恰好是同一种实体就需要用到分组校验
      • 校验注解都有一个 groups 属性,可将校验注解分组

        • groupsClass 类型的数组,@NotNull 源码

          • @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
            @Retention(RUNTIME)
            @Repeatable(List.class)
            @Documented
            @Constraint(validatedBy = { })
            public @interface NotNull {
            
                String message() default "{javax.validation.constraints.NotNull.message}";
                
                Class<?>[] groups() default { };
                
                Class<? extends Payload>[] payload() default { };
                
                @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
                @Retention(RUNTIME)
                @Documented
                @interface List {
                    NotNull[] value();
                }
            }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
      • 创建一个 Groups

        • public class Groups {
              public interface Add{}
              public interface  Update{}
          }
          
          • 1
          • 2
          • 3
          • 4
      • 给参数对象的校验注解添加分组

        • @Data
          public class User {
          
              @Null(message = "新增不需要指定id" , groups = Groups.Add.class)
              @NotNull(message = "修改需要指定id" , groups = Groups.Update.class)
              private Integer id;
              @NotBlank(message = "用户名不能为空")
              @NotNull
              private String username;
              @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$", message = "密码必须为8~16个字母和数字组合")
              private String password;
              @Email
              private String email;
              private Integer gender;
          
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
      • Controller 中原来的 @Valid 不能指定分组 ,需要替换成 @Validated

        • @RestController
          @RequestMapping("/user")
          public class UserController {
          
              @PostMapping("")
              public Result save (@Validated(Groups.Add.class) User user)  {
                  return Result.ok();
              }
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
  • 相关阅读:
    2023 年 数维杯(A题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析
    3D开发工具HOOPS:助力Navisworks数据处理与3D模型可视化!
    【元宇宙】5个视角,重新看待区块链和元宇宙
    WPF优秀组件推荐之FreeSpire
    PX4模块设计之十一:Built-In框架
    神经网络极简入门
    驱动开发:内核特征码搜索函数封装
    苹果专用解压缩推荐 BetterZip 5 中文for mac
    爬虫 day 03 数据接口和selenuim基础
    小黑昨晚又内耗了起床来个leetcode:109. 有序链表转换二叉搜索树
  • 原文地址:https://blog.csdn.net/qq_66991094/article/details/127593705