目录

  • Spring Boot 支持两种配置文件形式
    • .properties
    • .yml(推荐使用)
  • Spring Boot 使用一个全局的配置文件 application.properties 或 application.yml,放置在【src/main/resources】目录下
    【Java框架】SpringBoot(二)核心配置-LMLPHP

yml文件

什么是yml文件

  • yml文件格式是YAML (YAML Ain’t a Markup Language)编写的文件格式,是一个可读性高,用来表达数据序列化的格式。
  • YAML是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序解析。
  • YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者

yml文件的优点

  • 易于人们阅读
  • yml数据在编程语言之间是可移植的
  • yml易于实现和使用
  • yml是以数据为核心的,比传统的xml方式更加简洁

使用场景

脚本语言

由于实现简单,解析成本很低,YAML 特别适合在脚本语言中使用

序列化

YAML是由宿主语言数据类型直转,比较适合做序列化。

配置文件

写 YAML 要比写 XML 快得多(无需关注标签或引号),并且比 ini文档功能更强。由于兼容性问题,不同语言间的数据流转建议不要用 YAML。

yml的基本语法

  • YAML的配置方式,都采用阶梯化缩进的方式展现,其结构显得更为清晰易读
  • 语法规则
    • 大小写敏感
    • 数据值前必须有空格,作为分隔符
    • 使用缩进表示层级关系
    • 缩进时不允许使用Tab键,只允许使用空格。
    • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    • “#”表示注释

yml支持的数据类型

字面量

  • 字符串,布尔类型,数值,日期。日期格式支持yyyy/MM/dd HH:mm:ss
  • 单引号:会转义特殊字符,特殊字符最终只是一个普通的字符串数据
  • 双引号:不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name1: zhangsan
name2: 'zhangsan \n lisi'                #输出zhangsan \n lisi
name3: "zhangsan \n lisi"              #输出zhangsan 换行 lisi
age: 18
flag: true	
date: 2022/01/01	

对象(属性和值)、Map(键值对)

  • 由键值对组成,形如 key:(空格)value 的数据组成。冒号后面的空格是必须要有的,每组键值对占用一行,且缩进的程度要一致,也可以使用行内写法:{k1: v1, …kn: vn}
people:
    nickName: zhangsan
    age: 20	
people: {name:zhangsan,age: 20} #行内写法	

数组

  • 由形如 -(空格)value 的数据组成。短横线后面的空格是必须要有的,每组数据占用一行,且缩进的程度要一致,也可以使用行内写法: [1,2,…n]
pets:
    - dog
    - pig
    - cat	
pets: [dog,pig,cat]  #行内写法	

复合结构

  • 例如:数组对象、list对象、set对象
peoples:
    - nickName: zhangsan
      age: 22
    - nickName: lisi
      age: 20
    - {nickName: wangwu,age: 18}

思考:Spring Boot项目中如何读取配置信息,并注入配置信息

Spring Boot配置文件的值注入

第一种读取方式@Value

  • 使用场景:如果只需要配置文件中的一两个值,@Value 是最简单方便的方式
  • 语法规则:@Value 注解上通过 ${key} 即可获取配置文件中和key对应的value值
user:
  nickName: 周杰伦
  age: 46
@RestController
public class ValueController {
    @Value("${user.nickName}")
    private String nickName;
    @Value("${user.age}")
    private Integer age;
    @RequestMapping("/config")
    public Object getConfig(){
        return "昵称:"+nickName+",年龄:"+age;
    }
}

第二种读取方式@ConfigurationProperties

  • 使用场景:当配置信息比较复杂时,可以将配置信息封装为一个JavaBean,我们一般会使用@ConfigurationProperties来读取。
  • 语法规则:在JavaBean中添加@ConfigurationProperties注解,并配置一个prefix (前缀) 参数, 参数是配置文件中 key的名称

配置文件

star:
  starName: 周传雄
  birthday: 1969/6/7
  starSex:

配置对象类

@Data
@Component
@ConfigurationProperties(prefix = "star")
public class Star {
    private String starName;
    private String starSex;
    private String birthday;
}

controller

@RestController
public class ConfigPropertiesController {
    @Resource
    private Star star;
    @RequestMapping("/star")
    public Star getStar(){
        return star;
    }
}

第三种读取方式自动装配Environment

  • Spring使用Environment表示应用的上下文环境,Environment环境代表当前应用运行时所处的环境。
  • Environment接口作用可以让Spring根据不同的环境配置加载不同的配置信息。例如我们常用的测试环境和生产环境需要使用不同的数据源,通过配置环境信息即可达到无缝切换
user:
  nickName: 周杰伦
  age: 46
@RestController
public class EnvironmentController {
    @Resource
    private Environment environment;
    @RequestMapping("/env")
    public String getEnv() {
        String nickName = environment.getProperty("user.nickName");
        String age = environment.getProperty("user.age");
        return "昵称:"+nickName+",年龄:"+age;
    }
}

思考:Spring Boot在启动的时候会自动加载 application.xxx ,但是为了区分,有时候需要自定义一个配置文件,那么如何从自定义的配置文件中取值呢?就需要配合 @PropertySource 这个注解使用了

@PropertySource注解的用法

使用场景

  • 加载指定的属性文件(*.properties)到 Spring 的 Environment 中,可以配合 @Value 和@ConfigurationProperties 使用。

使用方式

  • @PropertySource 和 @Value组合使用,可以将自定义属性文件中的属性变量值注入到当前类的使用@Value注解的成员变量中。
  • @PropertySource 和 @ConfigurationProperties组合使用,可以将属性文件与一个JavaBean类绑定,将属性文件中的变量值注入到该Java类的成员变量中。

database.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf8&useSSL=false

【Java框架】SpringBoot(二)核心配置-LMLPHP

@PropertySource 和 @Value组合使用

@RestController
@PropertySource("classpath:database.properties")
public class PropertySourceValueController {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @RequestMapping("/jdbc")
    public String getJdbc(){
        return "驱动:" + driver + ",连接地址:" + url;
    }
}

@PropertySource 和 @ConfigurationProperties组合使用

@RestController
public class PropertySourceConfigPropertiesController {
    @Resource
    private JdbcConfig jdbcConfig;
    @RequestMapping("/jdbcConfig")
    public JdbcConfig getJdbcConfig() {
        return jdbcConfig;
    }
}

补充

【Java框架】SpringBoot(二)核心配置-LMLPHP红色标记的解决方案:添加以下依赖:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
</dependency>

Spring Boot中使用Java配置

Spring配置的发展

  1. 基于XML配置
  2. 基于注解配置
    @RestController: 一般用在表现层,作用等同于@Controller + @ResponseBody
    @Controller: 一般用在表现层
    @Service:一般用在业务层
    @Repository:一般用在持久层
    @Component:该注解用于把当前类对象存入 Spring 容器中
  3. 基于Java配置

思考:是否有了注解配置,我们就可以完全摒除原来 XML 配置的方式呢?答案是否定的。有以下几点原因:

  • 注解配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注解配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注解配置,因为注解是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。
  • 如果 Bean 不是自己编写的类(如 JdbcTemplate、SessionFactoryBean 等),注解配置将无法实施,此时 XML 配置是唯一可用的方式。
  • 注解配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注解,使用 aop/tx 命名空间的事务配置更加灵活和简单。

基于Java配置(javaConfig)

什么是javaConfig

  • Spring JavaConfig是Spring社区的产品,它提供了一种纯Java方法来配置Spring IoC容器。因此,它有助于避免使用XML配置。
  • 使用JavaConfig 的优点是:
    1. 面向对象的配置。由于配置在JavaConfig中定义为类,因此用户可以充分利用Java中面向对象的功能。一个配置类可以子类化另一个,覆盖其@Bean方法等。
    2. 减少或消除XML配置。已经证明了基于依赖注入原理的外部化配置的好处。但是,许多开发人员不希望在XML和Java之间来回切换。JavaConfig为开发人员提供了一种纯Java方法来配置Spring容器,该容器在概念上类似于XML配置。在技​​术上可以仅使用JavaConfig配置类来配置容器,但是在实践中,许多人发现将JavaConfig与XML混合匹配是理想的。
    3. 类型安全和重构友好。JavaConfig提供了一种类型安全的方法来配置Spring容器。由于Java 5.0支持泛型,现在可以按类型而不是按名称检索bean,而不需要任何强制转换或基于字符串的查找

以创建DataSource为例

1.依赖
 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.10</version>
 </dependency>
2.在src/main/resources下添加jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/smbms
jdbc.user=root
jdbc.password=123456
3.添加config包,创建配置类SpringConfiguration
package com.zjl.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/23
 * @desc:
 */
@Configuration
@PropertySource(value={"classpath:jdbc.properties"})
public class SpringConfiguration {
    @Value("${jdbc.driverClassName}")
    String driverClassName;
    @Value("${jdbc.url}")
    String url;
    @Value("${jdbc.user}")
    String user;
    @Value("${jdbc.password}")
    String password;
    @Bean(name="dataSource")
    public DataSource createDataSource() {
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }
}
4.测试
@RestController
public class DataSourceController {
    @Resource
    private DataSource dataSource;
    @RequestMapping("/dataSource")
    public DataSource getDataSource() {
        return dataSource;
    }
}

Spring Boot项目中实现多环境配置

实际的开发场景

  1. 在未来的工作中,开发真实的项目时,可能会遇到不同的环境,如:开发环境、测试环境、生产环境等。
  2. 在不同的环境下,配置有可能是不一样的,比如接口地址、数据库连接的配置信息等。如果我们每次切换环境时再去配置对应的环境配置,肯定会降低我们的开发效率。
  3. Spring Boot 对多环境整合已经有了很好的支持,能够在打包,运行间自由切换环境,所以,掌握多环境配置还是非常有必要的。
  4. Spring Boot 多环境设置机制:设置spring.profiles.active属性

多环境配置的实现

第1种:单文件实现

  • 在application.yml中指定不同环境配置,通过—进行分割
  • 在application.yml文件中,指定被加载的配置文件
    • spring.profiles.active
  • 运行时指定启动环境参数
    【Java框架】SpringBoot(二)核心配置-LMLPHP

第2种:多文件实现(推荐)

  • 创建不同环境的配置文件,命名为:application-{profile}.yml
  • 不同配置文件分别配置不同的端口
  • 在application.yml文件中,指定被加载的配置文件
    • spring.profiles.active
  • 运行时指定启动环境参数
示例
  • Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式。
  • 通常一个公司的程序可能在开发环境(dev)、测试环境(test)、生产环境(prod)中运行
  • 假设我们配置不同的配置文件
    • application.yml
    • application-dev.yml(开发环境)
    • application-test.yml(测试环境)
    • application-prod.yml(生产环境)
  • 在 application.yml 中指定,确定当前使用的是哪个环境,这边环境的值与application-dev.yml中-后面的值对应,这是SpringBoot约定好的。
    【Java框架】SpringBoot(二)核心配置-LMLPHP
    application-dev.yml
server:
  port: 7777

application-test.yml

server:
  port: 8888

application-prod.yml

server:
  port: 9999

application.yml

spring:
  profiles:
    active: dev

切换application.yml中spring.profiles.active的值,然后启动springBoot,看下启动的端口号,就知道用的是哪个环境的配置了

日志的重要性

日志是程序员在代码运行时打印出来的一些数据和记录,是快速排查问题的好帮手

  • 日志,通常不会在需求阶段作为一个功能单独提出来,也不会在产品方案中看到它的细节。但是,这丝毫不影响它在任何一个项目中的重要地位。
  • 为了保证项目的正常运行,发现问题要及时,解决问题要迅速,生产环境一旦出现问题,预警系统就会通过邮件、短信甚至电话的方式实施多维轰炸模式,确保负责人不错过每一个可能的bug。预警系统判断疑似bug源于日志。当该错误日志达到一定次数出现的时候,就会触发报警。

日志的作用

  1. 问题追踪:辅助排查和定位线上问题,优化程序运行性能。
  2. 状态监控:通过日志分析,可以监控系统的运行状态。
  3. 安全审计:审计主要体现在安全上,可以发现非授权的操作。
  4. 日志在应用程序中是非常重要的,好的日志信息能有助于我们在程序出现BUG时能快速进行定位,并能找出其中的原因。

Java中如何实现日志记录

Java 拥有功能和性能都非常强大的日志库

  1. Log4j:Log4j全称是Log for Java,它是Apache的一个开源项目
  2. JUL:java.util.logging,Sun公司开发的,是Java原生的日志框架
  3. JCL:Jakarta Commons Logging是Apache提供的一个通用日志API(日志门面)
  4. SLF4J:即简单日志门面(Simple Logging Facade for Java),它主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其它日志框架,例如log4j和logback等;
  5. Logback :Logback是由log4j创始人设计的另一个开源日志组件,性能比Log4j要好Logback是基于SLF4J的日志规范实现的框架。
  6. Log4j2 :Ceki Gülcü 觉得还是得照顾下自己的 “大儿子”——Log4j,又把 Log4j 进行了改造,就是所谓的 Log4j2,同时支持 JCL 以及 SLF4J

【Java框架】SpringBoot(二)核心配置-LMLPHP

日志库特点
  1. JCL和 SLF4J 都是日志的接口,供用户使用,而没有提供实现,Log4j,JUL,logback 等等才是日志的真正实现。
  2. Log4j,JUL,logback 是互相不兼容的,没有共同的 Interface,通过适配器模式,抽象出来一个共同的接口,然后根据具体的日志框架来实现日志。
  3. 通常情况下,日志记录是由一个抽象层+实现层的组合来搭建的。
  4. Spring Boot的日志框架:默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。

Logback简介

  • Logback是由log4j创始人设计开发的另一个开源日志组件,性能安全性个方面都比Log4j好,所以一般都推荐使用这个日志框架。
  • Spring Boot 内部所有的日志实现都通过桥接器转换成Slf4j 日志门面进行统一管理,最终交给Logback日志框架进行日志输出。
  • 官网: http://logback.qos.ch
  • 主要模块:
    • logback-core:其它两个模块的基础模块
    • logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK1.4 Logging
    • logback-access:模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能。

Spring Boot中整合Logback

1.依赖

Spring Boot提供了默认的日志配置,只要将spring-boot-starter-logging作为依赖加入到当前应用中,则“开箱即用”

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
2.设置日志级别
  • 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。
  • 在 Spring 中设置日志级别,方法是使用logging.level.<logger-name>=<level>
logging:
  level:
      org.springframework.web: debug
3.Logback的定制化配置
  • 由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是通过Spring的配置文件控制。因此需要通过系统属性和传统的Spring Boot外部配置文件
    【Java框架】SpringBoot(二)核心配置-LMLPHP
  • Spring Boot官方推荐优先使用带有xx-spring.xml的文件名作为你的日志配置(比如:logback-spring.xml),命名为logback-spring.xml的日志配置文件,Spring Boot可以为它添加一些特有的配置项。
  • 创建logback-spring.xml文件,放在src/main/resources下面即可
<?xml version="1.0" encoding="UTF-8"?>
<configuration >
    <!--contextName说明:每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,
           用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来打印日志上下文名称。-->
    <contextName>logback-spring</contextName>
    <!-- name的值是变量的名称,value的值是变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="logs"/>
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy年MM月dd日 HH:mm:ss}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--输出日志到控制台-->
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <!--ThresholdFilter:临界值过滤器,打印大于等于level标签设置的级别,小的舍弃-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <!--日志输出格式-->
        <layout>
            <!--指定日志格式-->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </layout>
    </appender>

    <!--输出日志到文件-->
    <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--LevelFilter:只打印level标签设置的日志级别-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <!--匹配到就允许-->
            <onMatch>ACCEPT</onMatch>
            <!--没有匹配到就禁止-->
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
        <!--指定文件的输出位置-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>d:/${log.path}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!--日志文档保留天数-->
            <maxHistory>30</maxHistory>
            <!--配置日志文件不能超过100M,若超过100M,日志文件会以索引0开始,命名日志文件-->
            <maxFileSize>100MB</maxFileSize>
            <!--总大小-->
            <totalSizeCap>2GB</totalSizeCap>
            <!--appender启动的时候,归档文件将会被删除。默认的值为 false-->
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>
    <root level="info">
        <appender-ref ref="consoleLog"/>
        <appender-ref ref="fileLog"/>
    </root>
    <!--有logger的配置,不指定级别,不指定appender-->
    <!--将org.springframework.web包下的所有类的日志的打印-->
    <logger name="org.springframework.web" level="debug"/>
</configuration>
4.如何记录自己代码中的日志
方式一:手动创建Logger对象
@RestController
public class LoggerController {
    Logger logger = LoggerFactory.getLogger(LoggerController.class);
    @RequestMapping("/log")
    public Object log(){
        logger.info("测试日志INFO");
        logger.error("测试日志ERROR");
        logger.debug("测试日志DEBUG");
        return "测试日志";
    }
}
方式二:使用Lombok提供的@Slf4j注解

依赖

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

使用

@RestController
@Slf4j
public class LoggerController {
    @Resource
    private DataSource dataSource;
    @RequestMapping("/log")
    public Object log(){
        log.info("测试日志,日志级别是:{},数据源对象是:","INFO",dataSource);
        log.error("测试日志ERROR");
        log.debug("测试日志DEBUG");
        return "测试日志";
    }
}

【Java框架】SpringBoot(二)核心配置-LMLPHP

04-24 08:02