【SpringBoot】①入门,配置,日志

实际2020-04-20 10:37:42
此篇文章使用版本:2.2.2.RELEASE

SpringBoot 入门

简介

1
2
3
4
5
6
7
8
9
10
11
SpringBoot
1. 简化Spring应用开发的一个框架;
2. 整个Spring技术栈的一个大整合;
3. J2EE开发的一站式解决方案;

SpringCloud
2014,martin fowler
微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;
单体应用:ALL IN ONE
微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;

HelloWorld 实现&分析

功能:浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串;

  • 实现
    在这里插入图片描述
  • 分析
    ①pom文件
    在这里插入图片描述
    ②主程序类,主入口类【分析注解@SpringBootApplication & 自动化加载配置类】
    在这里插入图片描述
    在这里插入图片描述

Spring Initializer

IDE都支持使用Spring的项目创建向导快速创建一个SpringBoot项目;

选择我们需要的模块;向导会联网创建SpringBoot项目;

默认生成的SpringBoot项目;

  • 主程序已经生成好了,我们只需要我们自己的逻辑
  • resources文件夹中目录结构
    • static:保存所有的静态资源; js css images;
    • templates:保存所有的模板页面;(SpringBoot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面);可以使用模板引擎(freemarker、thymeleaf);
    • application.properties:SpringBoot应用的配置文件;可以修改一些默认设置;

SpringBoot配置

properties和yml

SpringBoot使用一个全局的配置文件,配置文件名是固定的;application.properties application.yml
配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;

1
2
3
4
5
6
7
YAML(YAML Ain't Markup Language)
​ YAML A Markup Language:是一个标记语言
​ YAML isn't Markup Language:不是一个标记语言;

标记语言:
​ 以前的配置文件;大多都使用的是xml文件;
​ YAML:**以数据为中心**,比json、xml等更适合做配置文件;
  • 语法 + 单/双引号区别 + 中文编码问题
    在这里插入图片描述

@Configuration

【对@Component的一种封装,用于替代之前的xml配置文件形式】
在这里插入图片描述

@ConfigurationProperties

注入数据的两种使用方式【@EnableConfigurationProperties注解的使用】
在这里插入图片描述
配置文件数据校验 + 配置文件代码提示(需重启主配置类)
在这里插入图片描述
可以选择设置【关闭通知面板】
在这里插入图片描述

@Value

注意:这个可以没有对应的set方法也可以注入
在这里插入图片描述

  • @Value获取值和@ConfigurationProperties获取值比较
@ConfigurationProperties @Value
功能 批量注入 单个注入
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

配置文件yml还是properties他们都能获取到值;
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

@PropertySource

在这里插入图片描述

@ImportResource

  • 使用方法
    在这里插入图片描述
  • SpringBoot推荐使用@Configuration
    在这里插入图片描述

配置文件占位符

在这里插入图片描述

三种激活方式

在这里插入图片描述

@ActiveProfiles

此注解的效果同指定虚拟机参数。
@ActiveProfiles("dev") 等同于 -Dspring.profiles.active=dev
区别在于:此注解是专门用于测试使用。不能给主配置类使用。
在这里插入图片描述

@Profile

官网说了,只能作用于@Component @Configuration @ConfigurationProperties标记的类上,或被标记类的方法中。
注意:启动主配置类时要使用三种方式激活对应的文件。测试时可使用@ActiveProfiles进行激活。
在这里插入图片描述

加载顺序

我的理解:先加载的会覆盖后加载的,这些配置文件呢,是为了覆盖默认的自动化配置。
会形成互补配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
指定以下参数 启动主配置类
-Dspring.profiles.active=dev
application-dev.properties
application.properties【spring.profiles=dev】
application-dev.yml
application.yml【spring.profiles=dev】
application.properties【没有spring.profiles属性】
application.yml【没有spring.profiles属性】
8080
不会加载application-default.properties/yml 和 application-prod.properties/yml

未指定虚拟机参数 启动主配置类
application-default.properties
application-default.yml
application.properties【没有spring.profiles属性】
application.yml【没有spring.profiles属性】
8080
不会加载application-dev.properties/yml,application-prod.properties/yml 和 application.properties/yml【有spring.profiles属性】

加载位置

我这里测试版本是:2.2.2.RELEASE(可能会和1.x.x不一样)
【下面的加载顺序会形成互补配置】
在这里插入图片描述
①只有test.properties配置文件生效【其他四个地方全失效】
java -jar .\spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=D:/test.properties
②还会加载那四个位置,但test.properties中的内容会赋值已有的内容(相当于它比那四个位置加载优先级还要高)
java -jar .\spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.additional-location=D:/test.properties

外部化配置加载顺序

2.2.2.RELEASE外部配置加载顺序-官方文档
在这里插入图片描述

自动配置原理

在上面我们已经讲到了主入口类注解@SpringBootApplication会加载自动化配置类,文件位置:spring-boot-autoconfigure-2.2.2.RELEASE.jar!\META-INF\spring.factories
可参考HelloWorld分析-主程序类,主入口类注解@SpringBootApplication
下面我们来分析一下自动配置的原理
在这里插入图片描述
2.2.2.RELEASE官方文档理解自定义配置(@Conditional注解)

SpringBoot的精髓:

1
2
3
4
​   1、SpringBoot启动会加载大量的自动配置类
​ 2、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
​ 3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
​ 4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;

xxxxAutoConfigurartion:自动配置类;,给容器中添加组件,xxxxProperties:封装配置文件中相关属性;

@Conditional派生注解

可参考2.2.2.RELEASE官方文档理解自定义配置(@Conditional派生注解)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

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

自动配置类必须在一定的条件下才能生效;,我们怎么知道哪些自动配置类生效;
==我们可以通过启用 debug=true属性(或使用命令行参数java -jar xxx.jar –debug=true);来让控制台打印自动配置报告==
在这里插入图片描述

日志

日志框架

  • 一个故事概括

    1
    2
    3
    4
    5
    6
    7
    8
    小张;开发一个大型系统;
    ​ 1、System.out.println("");将关键数据打印在控制台;去掉?写在一个文件?
    ​ 2、框架来记录系统的一些运行时信息;日志框架 ; zhanglogging.jar;
    ​ 3、高大上的几个功能?异步模式?自动归档?xxxx? zhanglogging-good.jar?
    ​ 4、将以前框架卸下来?换上新的框架,重新修改之前相关的API;zhanglogging-prefect.jar;
    ​ 5、JDBC---数据库驱动;
    ​ 写了一个统一的接口层;日志门面(日志的一个抽象层);logging-abstract.jar;
    ​ 给项目中导入具体的日志实现就行了;我们之前的日志框架都是实现的抽象层;
  • 市面上的日志框架;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    日志门面(日志的抽象层)- Interface
    JCL(Jakarta Commons Logging)
    SLF4j(Simple Logging Facade for Java)
    jboss-logging(只有Hibernate在用)
    日志实现 - implements
    Log4j(有点垃圾)
    JUL(java.util.logging)
    Log4j2(太新了)
    Logback

    选一个(抽象层)和 一个实现; 【SLF4J + Logback】
    SpringBoot:底层是Spring框架,Spring框架默认是用JCL;

==SpringBoot选用 SLF4j和logback;==
在这里插入图片描述

SpringBoot日志关系

场景启动器

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

SpringBoot使用【日志场景启动器】来做日志功能;

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

总结:
​ 1)、SpringBoot底层也是使用slf4j+logback的方式进行日志记录
​ 2)、SpringBoot也把其他的日志都替换成了slf4j;
​ 3)、中间替换包?

1
2
3
4
5
6
@SuppressWarnings("rawtypes")
public abstract class LogFactory {

static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";

static LogFactory logFactory = new SLF4JLogFactory();

​ 4)、如果我们要引入其他框架?一定要把这个框架的默认日志依赖移除掉?

​ Spring框架用的是commons-logging;

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

==SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时,需要把这个框架依赖排除掉即可;==
在这里插入图片描述

日志使用

默认配置

SpringBoot默认帮我们配置好了日志;
在这里插入图片描述
在这里插入图片描述

1
2
3
4
5
6
7
8
9
日期和时间:毫秒精度,易于排序。
日志级别:ERROR,WARN,DEBUG和TRACE
进程ID。
一个---分隔符,用于区分实际日志消息的开始。
线程名称:用方括号括起来(输出可能会被控制台截断)。
记录器名称:这通常是源类名称(通常缩写)。
日志消息。

注意:Logback没有FATAL级别。 它映射到ERROR。

SpringBoot修改日志的默认配置
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
logging.level.com.atguigu=trace
logger.level.root=debug


# 不指定路径在当前项目下生成springboot.log日志
# 可以指定完整的路径;
#logging.file.name=G:/springboot.log

# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
logging.file.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

日志输出格式:

1
2
3
4
5
6
7
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
logging.file logging.path Example Description
(none) (none) 只在控制台输出
指定文件名 (none) my.log 输出日志到my.log文件
(none) 指定目录 /var/log 输出到指定目录的 spring.log 文件中

指定配置

给类路径下放上每个日志框架自己的配置文件即可;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功能

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

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<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]

切换日志框架

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <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-over-slf4j</artifactId>
    <groupId>org.slf4j</groupId>
    </exclusion>
    </exclusions>
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    </dependency>
  • 切换为log4j2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
       <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>