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
      
    • yml 格式

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

    • 所有配置文件中能配置的属性都是在 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. 直接使用 \n 换行

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

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

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

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

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

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

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

      • ---
        string: |
          I am a coder.
        ---
        string: |+
          I am a coder.
        --- 
        string: |-
          I am a coder.
        
显示不换行
  • 配置按段落,显示在一行

    1. 直接换行写

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

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

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

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

      • ---
        string: >
          I am a coder.
        ---
        string: >+
          I am a coder.
        ---
        string: >-
          I am a coder.
        
示例
# 分为两种不同环境
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.

  • 顶层由七个键值组成
    • 键值 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. 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:第一位置
      	-	第二位置
      

多环境配置

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

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

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

    • spring.profiles.active=dev
      
  • 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	# 生产环境
    

自定义K-V

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

    • 在赋值引用时可以引用框架的 key 或 自定义key
    demo:
      name: 张三${random.uuid}
      age: 19
      map:
        demo1: 18
        demo2: 20
      hobby:
        --- rap
    
@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;
    
占位符

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

随机数
${random.value}
${random.int}
${random.long}
${random.int(10)}
${random.int[1024,65536]}
默认值
  • 占位符获取之前配置的值
  • 如果没有可以用 : 指定默认值
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

@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]					# 数组,行内写法

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

@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;
}
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();
          }
      
      }
      
  • 异常的统一处理

    • 参数校验不通过时,会抛出 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);
          }
      }
      
  • 分组解决校验

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

      • 例: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();
              }
          }
          
    • 创建一个 Groups

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

      • @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;
        
        }
        
    • Controller 中原来的 @Valid 不能指定分组 ,需要替换成 @Validated

      • @RestController
        @RequestMapping("/user")
        public class UserController {
        
            @PostMapping("")
            public Result save (@Validated(Groups.Add.class) User user)  {
                return Result.ok();
            }
        }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值