Spring Boot(一)Spring Boot核心技术

目录
一、Spring Boot入门
  1 Spring Boot简介
  2 微服务
  3 入门案例
  4 Spring Boot简化部署
  5 入门案例解析
  6 使用Spring Initializer快速创建Spring Boot项目(以idea为例)
  7 springboot内嵌tomcat启动方式和非内嵌tomcat启动方式
二、Spring Boot配置
  1 简介
  2 yaml文件
  3 配置文件注入
  4 配置文件占位符
  5 Profile
  6 配置文件加载位置
  7 外部配置加载顺序
\color{red}{8 自动配置原理}
三、日志
  1 市面上的日志框架
  2 SLF4j使用
  3 SpringBoot日志关系
  4 日志使用
  5 切换日志框架

更多知识可参考:https://www.jianshu.com/p/7dbaac902074


一、Spring Boot入门

1 Spring Boot简介
  • 简化Spring应用开发的一个框架
  • 整个Spring技术栈的一个大整合
  • 将J2EE开发的一站式解决方案
2 微服务

Martin Fowler和James Lewis的《Microservices》是第一篇详细介绍微服务的文章。
Microservices全文
spring微服务官网

3 入门案例

在此之前,你需要掌握Spring框架和Maven的使用.

  • 创建maven项目,导入依赖
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  • 编写主程序,启动Spring Boot应用
/**
 * SpringBootApplication用来标注一个主程序,说明这是一个Spring Boot应用
 */
@SpringBootApplication
public class FirstSpringBootApplication {
    public static void main(String[] args) {
        //spring应用启动
        SpringApplication.run(FirstSpringBootApplication.class, args);
    }
}
  • 编写controller,service
@RestController
public class FirstController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello world";
    }
}
4 Spring Boot简化部署
  • 在pom.xml中导入插件,这个插件可以将应用打包成一个jar包
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • 打包过程
    在idea的右侧栏找到maven,找到并点击package.

    此时就会在控制台输出打包的信息

    在控制台给出的路径中找到生成的jar包,使用命令行运行命令java -jar springboot-1.0-SNAPSHOT.jar,运行成功会出现如下界面

    此时再访问http://localhost:8080/hello,结果和在idea中运行结果一致,则部署成功.
5 入门案例解析
1) pom.xml文件
  • spring-boot-starter-parent,父项目是spring-boot-dependencies,它用来管理SpringBoot项目里的依赖版本
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>

在以后的项目开发过程中,出现在spring-boot-dependencies的依赖就不需要写版本号了

  • spring-boot-starter-web,是Spring Boot场景启动器,它帮我们导入了web模块正常运行所依赖的组件.
    Spring Boot将所有的功能场景都抽取出来,做成一个starter(启动器),只需要在项目引入这些starter,相关场景的所有依赖都会导入进来
2) 主程序类

   @SpringBootApplication,标注在某个类上,说明这个类是Spring Boot的主配置类,Spring Boot就应该运行在这个类的main()方法来启动应用.我们进入这个注解可以看到

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

  @SpringBootConfiguration,Spring Boot的配置类,标注在某个类上表示这是一个Spring Boot的配置类.而@SpringBootConfiguration注解上又标注了@Configuration,@Configuration表明某个类是一个配置类,配置类和配置文件有相同的作用,是容器中的一个组件(@Component)
   @EnableAutoConfiguration,SpringBoot开启自动配置功能.在这个注解上标注了@AutoConfigurationPackage,他是自动配置包,这个注解上又标注了@Import,它是Spring的底层注解.@AutoConfigurationPackage将主配置类(@SpringBootApplication标注的类)所在包及子包里面的的所有组件扫描到Spring容器;在@EnableAutoConfiguration上还标注了@Import({AutoConfigurationImportSelector.class}),它给容器导入组件AutoConfigurationImportSelector,而AutoConfigurationImportSelector是一个导入组件的选择器,它将所有需要导入的组件以全类名的方式返回,最终会给容器倒入很多自动配置类(xxxAutoConfiguration),这些配置类会给容器导入这个场景所需要的所有组件,并配置好这些组件,它为我们免去了手动编写配置文件和注入组件的工作.Spring Boot在启动时从类路径下的
META-INF/spring-autoconfigure-metadata.properties获取指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效了.也就是说,J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-2.1.6.RELEASE.jar里`

6 使用Spring Initializer快速创建Spring Boot项目(以idea为例)
  • 新建Spring Initializer项目


  • 填写包名和项目名


  • 需要什么功能,就加入相关的组件


  • finish



    系统生成了项目目录和主程序


7 springboot内嵌tomcat启动方式和非内嵌tomcat启动方式

springboot内嵌tomcat启动方式和非内嵌tomcat启动方式可参考:
https://www.cnblogs.com/ysq2018China/p/10241201.html

二、Spring Boot配置

1 简介

1.Spring Boot使用一个全局的配置文件,配置文件名是固定的;

  • application.properties
  • application.yml

2.配置文件作用:修改Spring Boot自动配置的默认值

3.配置文件放在src/main/resources目录或者类路径/config下

2 yaml文件
1) YAML(YAML Ain't Markup Language),以数据为中心,比json、xml等更适合做配置文件
  • yaml配置示例
server:
  port: 8081
  • xml配置示例
<server>
  <port>8081</port>
</server>
2) YAML语法
* YAML基本语法

– k:(空格)v:表示一对键值对(空格必须有);
– 以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
–缩进时不允许使用Tab键,只允许使用空格。
–缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
–大小写敏感

* YAML 支持的三种数据结构

– 对象:键值对的集合
– 数组:一组按次序排列的值
– 字面量:单个的、不可再分的值

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

k: v:在下一行来写对象的属性和值的关系;注意缩进;
对象还是k: v的写法

friends:
        name: zhangsan
        age: 20

行内写法:

friends: {name: zhangsan,age: 18}
* 数组(List,Set):

用- 值表示数组中的一个元素

pets:
 - cat
 - dog
 - pig

行内写法

pets: [cat,dog,pig]
* 字面量:普通的值(数字,字符串,布尔)
  • k: v:字面直接来写;
  • 字符串默认不用加上单引号或者双引号;
  • "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
    name: "zhangsan \n lisi":输出: zhangsan 换行 lisi
  • '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
    name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
3 配置文件注入
1) yaml方式

在之前创建的spring-boot-quick项目的基础上加上如下代码

  • application.yaml配置文件
person:
  name: zhangsan
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: 12}
  lists:
    - lisi
    - zhan
  dog:
    name: 小狗
    age: 2
  • Person对象
/**
 * @author:TiaNa
 * 配置文件中配置的每一个属性的值,映射到这个组件中
 * 只有这个组件是日期中的组件,才能使用容器提供的功能
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean boss;
    private Date birthday;

    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;

    get/set方法...
}
  • pom.xml,导入配置文件处理器,以后编写配置就有提示了
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
  • 重新运行SpringBootQuickApplication,编写测试代码
/**
 * springboot 单元测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootQuickApplicationTests {

    @Autowired
    Person person;

    @Test
    public void contextLoads() {
        System.out.println(person);
    }
}
  • 运行单元测试代码后


2) properties方式

application.properties文件

# 配置person的值
person.name=李四
person.age=18
person.birthday=2018/7/17
person.boss=false
person.dog.name=10
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
3) @value获取值

上面两节,不管是yaml方式还是properties方式注入,我们都使用的是@ConfigurationProperties注解获取值,但其实@value注解也可以实现。

@Component
public class Person {
   /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * <bean/>
     */
    @Value("${person.last-name}")
    private String lastName;
    @Value("#{11*2}")
    private Integer age;
    @Value("true")
    private Boolean boss;

    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
4) @value和@ConfigurationProperties获取值比较
序号 @value @ConfigurationProperties
功能 一个一个注入 批量注入配置文件的属性
松散绑定(松散语法) 不支持 支持
SpEL(Spring表达式) 支持 不支持
JSP303数据校验 不支持 支持
复杂类型封装 不支持 支持
  • 松散绑定
    属性名匹配规则(Relaxed binding)以下方式@ConfigurationProperties都能用firstName匹配
    – person.firstName:使用标准方式
    – person.first-name:大写用-
    – person.first_name:大写用_
    – PERSON_FIRST_NAME: 推荐系统属性使用这种写法
  • 配置文件注入值数据校验(JSR303数据校验)
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
   //lastName必须是邮箱格式
    @Email
    private String lastName;

如果说,我们只是在某个业务逻辑中需要获取配置文件中的某个值,使用@value;如果说,我们专门编写了一个JavaBean来和配置文件进行映射,需要使用@ConfigurationProperties。

5) @PropertySource、@ImportSource和@Bean
  • @PropertySource:加载指定的配置文件;
/**
 * 将配置文件中配置的每一个属性的值,映射到这个组件中
 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
 *      prefix = "person":配置文件中哪个下面的所有属性进行一一映射
 *
 * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
 *  @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值;
 *
 */
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
//@Validated
public class Person {

    /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * <bean/>
     */

   //lastName必须是邮箱格式
   // @Email
    //@Value("${person.last-name}")
    private String lastName;
    //@Value("#{11*2}")
    private Integer age;
    //@Value("true")
    private Boolean boss;
  • @ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;@ImportResource标注在一个配置类上使Spring的配置文件生效,加载进来;
@ImportResource(locations = {"classpath:beans.xml"})
  • @Bean
/**
 * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
 * 在配置文件中用<bean><bean/>标签添加组件
 */
@Configuration
public class MyAppConfig {

    //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
    @Bean
    public HelloService helloService02(){
        System.out.println("配置类@Bean给容器中添加组件了...");
        return new HelloService();
    }
}

SpringBoot推荐给容器中添加组件的方式:推荐使用全注解的方式
1、配置类@Configuration(相当于Spring配置文件)
2、使用@Bean给容器中添加组件

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

我们在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml,默认使用application.properties的配置

2)yml支持多文档块方式
server:
  port: 8081
spring:
  profiles:
    active: prod

---
server:
  port: 8083
spring:
  profiles: dev


---

server:
  port: 8084
spring:
  profiles: prod  #指定属于哪个环境
3)激活指定profile(三种方式)
  • 在配置文件中指定
spring.profiles.active=dev
  • 命令行,可以直接在测试的时候,配置传入命令行参数
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
  • 虚拟机参数
​   -Dspring.profiles.active=dev
6 配置文件加载位置

springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件:

–file:./config/
–file:./
–classpath:/config/
–classpath:/

优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置
我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
7 外部配置加载顺序

Spring Boot 支持多种外部配置方式
这些方式优先级参考官方文档:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config
①命令行参数
所有的配置都可以在命令行上进行指定,多个配置用空格分开; --配置项=值

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

②来自java:comp/env的JNDI属性
③Java系统属性(System.getProperties())
④操作系统环境变量
⑤RandomValuePropertySource配置的random.属性值
==
由jar包外向jar包内进行寻找;==
==
优先加载带profile==
⑥jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
⑦jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
==
再来加载不带profile*==
⑧jar包外部的application.properties或application.yml(不带spring.profile)配置文件
⑨jar包内部的application.properties或application.yml(不带spring.profile)配置文件
⑩ @Configuration注解类上的@PropertySource
①①通过SpringApplication.setDefaultProperties指定的默认属性

8 \color{red}{自动配置原理}(以SprinBoot2.1.8源码为例)

配置文件能配置的属性参照

1)SpringBoot启动时加载主配置类,开启了自动配置功能@EnableAutoConfiguration
2)@EnableAutoConfiguration作用:利用AutoConfigurationImportSelector给容器中导入组件,可以查看selectImports方法中的内容:
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = 
this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
  • 这个方法用来获取候选的配置
  • SpringFactoriesLoader.loadFactoryNames扫描所有jar包类路径下META-INF/spring.factories,把扫描到的这些文件内容包装成Properties对象,从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把它们添加进容器中。
  • 最后将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到容器中,
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
  • 每一个这样的xxxAutoConfiguration都是容器中的组件,都加入到容器中,用它们做自动配置
3)每一个配置类进行自动配置(以HttpEncodingAutoConfiguration为例)
@Configuration      
@EnableConfigurationProperties({HttpProperties.class})    
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }
    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
      filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
      filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }

  • @Configuration表示是一个配置类,和以前编写的配置文件一样,可以给容器中加入组件;
  • @EnableConfigurationProperties 启用指定类的ConfigurationProperties功能,将配置文件对应的值和HttpProperties绑定,并将HttpProperties加入到ioc容器中;
  • @ConditionalOnWebApplication,spring底层@Conditional注解,如果满足某个条件,整个配置类里的配置才能生效; @ConditionalOnWebApplication就是判断当前应用是否是web应用,如果是则生效;
  • @ConditionalOnClass判断当前有没有CharacterEncodingFilter这个类,springmvc中解决乱码的过滤器
  • @ConditionalOnProperty判断是否存在spring.http.encoding.enabled;如果不存在,判断也是成立的。即使配置文件中不配置默认也生效。
  • HttpEncodingAutoConfiguration只有一个有参构造器的情况下,参数值就会从容器中拿;
  • @Bean给容器中添加组件,这个组件的某些值需要从properties中获取,而properties已经和SpringBoot的配置文件映射了。

根据当前条件判断配置类是否生效,一旦生效,配置类就会给容器添加给中组件,这些组件的属性是从对应的properties中获取的,这些类里的属性又是和配置文件绑定的

4) 所有配置文件中能配置的属性xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能对应的属性类
//从配置文件spring.http中获取指定的值和属性进行绑定
@ConfigurationProperties( prefix = "spring.http")  
public class HttpProperties {
    private boolean logRequestDetails;
    private final HttpProperties.Encoding encoding = new HttpProperties.Encoding();
    public HttpProperties() {
    }

5) 用好自动配置类
  • SpringBoot启动会加载大量的自动配置类
  • 看我们需要的功能是否已由SpringBoot自动配置类写好,配置类中如果已经写好了组件,我们就不用配置了。
  • 给容器中自动配置类添加组件时,会从properties获取某些属性,我们可以在配置文件中指定这些属性的值。
6) @Conditional注解(补充知识)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

自动配置类必须在一定的条件下才能生效;
那我们怎么知道哪些自动配置类生效?可以application.properties里通过debug=true属性,来让控制台打印自动配置报告。打印内容如下:

=========================
AUTO-CONFIGURATION REPORT
=========================


Positive matches:(自动配置类启用的)
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
        
    
Negative matches:(没有启动,没有匹配成功的自动配置类)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

三、日志

1 市面上的日志框架

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

日志门面 (日志的抽象层) 日志实现
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j JUL(java.util.logging) Log4j2 Logback

左边选一个门面(抽象层)、右边来选一个实现;
SpringBoot选用 SLF4j和logback

2 SLF4j使用
1)如何在系统中使用SLF4j

官网: https://www.slf4j.org
以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;
给系统里面导入slf4j的jar和 logback的实现jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
 public static void main(String[] args) {
 Logger logger = LoggerFactory.getLogger(HelloWorld.class);
 logger.info("Hello World");
 }
}

系统中使用slf4j的方法:可参考https://www.slf4j.org/manual.html


每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;

2)遗留问题

A(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx
如上,A系统使用了许多框架,且每个框架日志输出使用的方式都不同,如何统一日志记录,所有框架统一使用slf4j进行输出?
解决办法:


如何让系统中所有的日志都统一到slf4j;
1、将系统中其他日志框架先排除出去;
2、用中间包来替换原有的日志框架;
3、我们导入slf4j其他的实现

3 SpringBoot日志关系
  • SpringBoot使用它来做日志功能:
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
 </dependency>
  • 底层依赖关系:

    总结:
    ​ 1)SpringBoot底层也是使用slf4j+logback的方式进行日志记录
    ​ 2)SpringBoot也把其他的日志都替换成了slf4j;
    ==SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可;==
    比如在SpringBoot1.x版本中引入spring时就做了这样的处理
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
       </exclusions>
</dependency>
2 日志使用
1)默认配置

SpringBoot默认帮我们配置好了日志;

  • 日志级别
    //记录器
    Logger logger = LoggerFactory.getLogger(getClass());
    @Test
    public void contextLoads() {
        //System.out.println();
        //日志的级别;
        //由低到高   trace<debug<info<warn<error
        //可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
        logger.trace("这是trace日志...");
        logger.debug("这是debug日志...");
        //SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
        logger.info("这是info日志...");
        logger.warn("这是warn日志...");
        logger.error("这是error日志...");
    }
  • 日志输出格式
    日志输出格式:
        %d表示日期时间,
        %thread表示线程名,
        %-5level:级别从左显示5个字符宽度
        %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
        %msg:日志消息,
        %n是换行符
    -->
    %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
  • SpringBoot修改日志的默认配置
logging.level.com.logging=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
logging.file logging.path Example Description
(none) (none) 只在控制台输出
指定文件名 (none) my.log 输出日志到my.log文件
(none) 指定目录 /var/log 输出到指定目录的 spring.log 文件中
2)指定配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

logback.xml:直接就被日志框架识别了;

logback-spring.xml:日志框架不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
    可以指定某段配置只在某个环境下生效
</springProfile>

如:

<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>

如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误
no applicable action for [springProfile]

5 切换日志框架

可以按照slf4j的日志适配图,进行相关的切换;
slf4j+log4j的方式:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <artifactId>logback-classic</artifactId>
      <groupId>ch.qos.logback</groupId>
    </exclusion>
    <exclusion>
      <artifactId>log4j-to-slf4j</artifactId>
      <groupId>org.slf4j</groupId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
</dependency>

切换为log4j2

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,423评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,339评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,241评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,503评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,824评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,262评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,615评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,337评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,989评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,300评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,829评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,193评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,753评论 3 230
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,970评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,708评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,295评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,207评论 2 258