YAML做配置一门语言:
以前的配置文件;大多都使用的是 xxxx.xml文件还有properties;
YAML:以数据为中心,比json、xml等更适合做配置文件;
YAML:配置例子
server:
port: 8081
XML:
<server>
<port>8081</port>
</server>
properties:
server.port =8081
-
- YML语法
- 基本语法
- YML语法
k:(空格)v:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
server:
port: 8081
path: /hello
属性和值也是大小写敏感;
-
-
- 值得写法
-
1)字面量:普通的值(数字,字符串,布尔)
k: v:字面直接来写;
字符串默认不用加上单引号或者双引号;
"":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi":输出;zhangsan 换行 lisi
'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
2)k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
3)数组(List、Set):
用- 值表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
-
- 配置文件值得注入
- 准备
- 配置文件值得注入
配置文件
person: lastName: hello age: 18 boss: false birth: 2017/12/12 maps: {k1: v1,k2: 12} lists: - lisi - zhaoliu dog: name: 小狗 age: 12 |
Javabean
/** * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; * prefix = "person":配置文件中哪个下面的所有属性进行一一映射 * * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; * */ @Component @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<Object> lists; private Dog dog; |
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
-
-
- 注入
-
- @ConfigurationProperties&@Value
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
@Component @ConfigurationProperties(prefix = "person") @Validated public class Person {
/** * <bean class="Person"> * <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property> * <bean/> */
//lastName必须是邮箱格式 //@Value("${person.last-name}") private String lastName; //@Value("#{11*2}") private Integer age; //@Value("true") private Boolean boss; |
- @PropertySource
@PropertySource指定配置文件
只支持properties文件
-
- Profile多环境支持
- 为什么要做多环境配置
- Profile多环境支持
一套代码要在多种环境运行(开发,测试,上线),所以我们的配置文件要支持多种环境
-
-
- 多profile文件
-
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
默认使用application.properties的配置;
-
-
- Yml支持多文档块模式
-
Application.yml
server: port: 8081 spring: profiles: active: prod
--- server: port: 8083 spring: profiles: dev
---
server: port: 8084 spring: profiles: prod #指定属于哪个环境 |
-
-
- 激活特定环境
-
1、在配置文件中指定 spring.profiles.active=dev
2、命令行: 部署环境
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod;
可以直接在测试的时候,配置传入命令行参数
3、虚拟机参数; 开发环境
-Dspring.profiles.active=dev
-
- 自动配置原理
配置文件到底能写什么?怎么写?自动配置原理;
官方文档查看
-
-
- 自动配置原理
-
- SpringBoot启动的时候加载主配置类,开启了自动配置功能 ==@EnableAutoConfiguration==
- @EnableAutoConfiguration 作用:
- 利用EnableAutoConfigurationImportSelector给容器中导入一些组件?
- 可以查看selectImports()方法的内容;
- List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置
==将 类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;==
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
每一个自动配置类进行自动配置功能;
- 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;
@Configuration //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件 @EnableConfigurationProperties(HttpEncodingProperties.class) //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中
@ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnClass(CharacterEncodingFilter.class) //判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的 //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的; public class HttpEncodingAutoConfiguration {
//他已经和SpringBoot的配置文件映射了 private final HttpEncodingProperties properties;
//只有一个有参构造器的情况下,参数的值就会从容器中拿 public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) { this.properties = properties; }
@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取 @ConditionalOnMissingBean(CharacterEncodingFilter.class) //判断容器没有这个组件? public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; } |
根据当前不同的条件判断,决定这个配置类是否生效?
一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
- 、所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功能对应的这个属性类
-
-
- 自动配置总结
-
精髓:
- 、SpringBoot启动会加载大量的自动配置类
2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
xxxxAutoConfigurartion:自动配置类;
给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
使用SpringBoot;
1)、创建SpringBoot应用,选中我们需要的模块;
2)、SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
3)、自己编写业务代码;
-
- 总结
- 整合测试-springboottest
- 引入
后续的学习过程中,每次都要写controller来访问测试比较麻烦,其他我们可以通过springboot的测试直接测试。就和原来不用启动tomcat一样测试
-
- 导入spring-boot-starter-test
在原有基础上面导入spring-boot-starter-test
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
-
- 创建一个SpringBoot应用,并在下面创建一个Bean
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
书写bean略过
-
- 写SpringBoot测试从Springboot中获取bean就ok
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class) //这事一个Spring测试,要告诉它在哪儿加载Spring配置文件,其实告诉它应用类型就ok
public class SpringbootTest {
@Autowired
private TestService testService;
@Test
public void test() throws Exception {
System.out.println(testService);
testService.test();
}
}
2.5小结
- Spring boot日志支持
- 为什么需要日志框架
通过日志的方式记录系统运行的过程或错误以便定位问题。
-
- 常见日志框架
- 设计思想
- 常见日志框架
1、System.out.println("");将关键数据打印在控制台;去掉?写在一个文件?
2、框架来记录系统的一些运行时信息;日志框架 ; zhanglogging.jar;
3、高大上的几个功能?异步模式?自动归档?xxxx? zhanglogging-good.jar?
4、将以前框架卸下来?换上新的框架,重新修改之前相关的API;zhanglogging-prefect.jar;
5、JDBC---数据库驱动;
写了一个统一的接口层;日志门面(日志的一个抽象层);logging-abstract.jar;
给项目中导入具体的日志实现就行了;我们之前的日志框架都是实现的抽象层;
-
-
- 常见框架
-
-
- Slf4j使用
- 如何在系统中使用SLF4j https://www.slf4j.org
- Slf4j使用
以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;给系统里面导入slf4j的jar和 logback的实现jar
每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;
-
-
- 遗留问题
-
a(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx
统一日志记录,即使是别的框架和我一起统一使用slf4j进行输出?
如何让系统中所有的日志都统一到slf4j;
==1、将系统中其他日志框架先排除出去;==
==2、用中间包来替换原有的日志框架;==
==3、我们导入slf4j其他的实现==
当项目是使用多种日志API时,可以统一适配到SLF4J,中间使用SLF4J或者第三方提供的日志适配器适配到SLF4J,SLF4J再底层用开发者想用的一个日志框架来进行日志系统的实现,从而达到了多种日志的统一实现。其中的技术实现大体有一下两种方式:
重写上游类的实现。比如jcl-over-slf4j和log4j-over-slf4j,为了承接log4j 1,重写了log4j 1 的Logger和LogFactory类。
对接上游类的扩展方案。比如jul-to-slf4j和log4j-to-slf4j,为了承接J.U.L,实现了继承java.util.logging.Handler的SLF4JBridgeHandler。
-
- Springboot日志关系
总结:
1)、SpringBoot底层也是使用slf4j+logback的方式进行日志记录
2)、SpringBoot也把其他的日志都替换成了slf4j;
3)、中间替换包?
4)、如果我们要引入其他框架?一定要把这个框架的默认日志依赖移除掉?
Spring框架用的是commons-logging;
==SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可;==
-
- logback日志使用
- 默认配置
- logback日志使用
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
-->
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
修改配置
logging.level.cn.itsource=trace
#logging.path= # 不指定路径在当前项目下生成springboot.log日志 # 可以指定完整的路径; #logging.file=G:/springboot.log
# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件 logging.path=/spring/log
# 在控制台输出的日志的格式 logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n # 指定文件中日志输出的格式 logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n |
默认配置在哪儿找
-
-
- 指定配置
-
如果还是不够用的话,可以自定义配置。给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的
logback.xml:直接就被日志框架识别了;
logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <!-- 日志输出格式: %d表示日期时间, %thread表示线程名, %-5level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息, %n是换行符 --> <layout class="ch.qos.logback.classic.PatternLayout"> <springProfile name="dev"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern> </springProfile> <springProfile name="!dev"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern> </springProfile> </layout> </appender> |
虚拟机参数:-Dspring.profiles.active=dev |
如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误
no applicable action for [springProfile]