分布式微服务架构之SpringBoot基础篇

一,springboot入门

1.springboot简介

简化spring应用开发

整个spring技术栈的一个大整合

j2ee开发的一站式解决方案

2.微服务

微服务:架构风格

一个应用应该是一组小型服务;可以通过HTTP的方式进行互通;

单体应用:ALL IN ONE

微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元;

3.创建一个springboot项目

向服务器发送 /hello ,服务器返回Hello Spring Boot !

1.创建一个普通的maven jar工程

2.导入依赖

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

3.编写springboot的主程序,用来启动项目

/**
 * @author yinhuidong
 * @createTime 2020-05-04-20:45
 */
//标注一个主程序,说明这是一个SpringBoot应用
@SpringBootApplication
public class SpringBootHelloWorld {
   
    public static void main(String[] args) {
   
        SpringApplication.run(SpringBootHelloWorld.class,args);
    }
}

4.编写控制器

/**
 * @author yinhuidong
 * @createTime 2020-05-04-20:47
 */
//@Controller
//如果整个控制器都需要@ResponseBody注解,那么可以用--替代
@RestController
public class HelloController {
   

    @RequestMapping("/hello")
    //@ResponseBody
    public String Hello(){
   

        return "hello SpringBoot!";
    }
}

5.结果

在这里插入图片描述

4.入门程序分析(自动配置原理)

1.pom文件

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.2.6.RELEASE</version>
    </parent>

点进去源码看他的上一层:

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>

由他来真正管理spring boot里面的所有的依赖版本。

2.启动器

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

spring-boot-starter:spring-boot场景启动器;帮我们导入了web模块正常运行所依赖的组件;

Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器

3.主启动类

//标识在一个主程序上,表示这是一个springboot应用程序的启动器,
// 也是整个应用程序的入口
@SpringBootApplication
public class Application {
   
    public static void main(String[] args) {
   
        SpringApplication.run(Application.class,args);
    }
}

点进这个注解

//表示这是一个springboot的配置类
@SpringBootConfiguration
//开启自动配置,springboot自动配置的核心
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
   

首先点击去 @SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//spring的原生注解,标识在一个类上,表示这是一个spring的配置类
@Configuration
public @interface SpringBootConfiguration {
   

回到上一层,点击进去@EnableAutoConfiguration

以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//自动配置包
@AutoConfigurationPackage
//@import spring的原生注解,往容器中导入AutoConfigurationImportSelector.class
//将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
   

点击进入 @AutoConfigurationPackage

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//往容器中导入自动配置包的注册器类
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
   

}

这两个@Import注解,会将SpringBoot依赖中的
在这里插入图片描述
这两个spring.factory文件导入到容器中。
点开spring.factory:
在这里插入图片描述
这里面有springboot的大量的自动配置类,容器启动时,就会自动的将我们需要的自动配置导入进来。

J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-2.2.6.RELEASE.jar;

4.@EnableAutoConfiguration

这个注解的底层有一个@Import(AutoConfigurationImportSelector.class),
他往容器中导入了一个AutoConfigurationImportSelector.class。
这个类是什么呢?

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
   
		if (!isEnabled(annotationMetadata)) {
   
			return NO_IMPORTS;
		}
		//这个类里面调用了一个loadMetadata()方法,在容器启动的时候,往容器中加载元数据
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

再看loadMetadata():

	static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
   
		return loadMetadata(classLoader, PATH);
	}

这个PATH是什么?

protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";

他往容器中加载的就是这个配置文件,点开可以看到里面都是springboot的自动配置类。
另外一个@Import(AutoConfigurationPackages.Registrar.class),他往容器中导入了一个AutoConfigurationPackages.Registrar.class,这个类是干什么的呢?

	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
   

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
   
			return Collections.singleton(new PackageImport(metadata));
		}

	}

这个类实现了ImportBeanDefinitionRegistrar,这个类在ioc容器创建的源码中出现过,再次不再细说,它会将刚才导入进来的bean在容器创建的时候,全部注册到容器中。

整理一下思路

@SpringBootApplication
    @SpringBootConfiguration
        @Configuration
    @EnableAutoConfiguration
        @AutoConfigurationPackage
            @Import(AutoConfigurationPackages.Registrar.class)
        @Import(AutoConfigurationImportSelector.class)
    @ComponentScan

5.具体的自动配置类

这里以字符编码过滤器为例

//表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@Configuration(proxyBeanMethods = false)

//启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中
@EnableConfigurationProperties(HttpProperties.class)

//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果
满足指定的条件,整个配置类里面的配置就会生效;    判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)

//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass(CharacterEncodingFilter.class)

 //判断配置文件中是否存在某个配置  spring.http.encoding.enabled;如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
   

	//他已经和SpringBoot的配置文件映射了 
	private final HttpProperties.Encoding properties;
	//只有一个有参构造器的情况下,参数的值就会从容器中拿
	public HttpEncodingAutoConfiguration(HttpProperties properties) {
   
		this.properties = properties.getEncoding();
	}

	@Bean //给容器中添加一个组件,这个组件的某些值需要从properties中获取
	@ConditionalOnMissingBean
	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;
	}

5.使用Spring Initializer快速创建Spring Boot项目

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

二,配置文件

1.配置文件

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

yaml

标记语言:
以前的配置文件;大多都使用的是  **xxxx.xml**文件;
​	YAML:**以数据为中心**,比json、xml等更适合做配置文件;

示例

server:
	port: 8081

2.yml语法

1)基本语法

k:(空格)v:表示一对键值对(空格必须有);

空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的

server:
    port: 8081
    path: /hello

属性和值也是大小写敏感

2)值的写法

字面量:普通的值(数字,字符串,布尔)

​ k: v:字面直接来写;

​ 字符串默认不用加上单引号或者双引号;

​ “”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思

​ name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi

​ ‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据

​ name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

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

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

​ 对象还是k: v的方式

friends:
		lastName: zhangsan
		age: 20

行内写法:

friends: {
   lastName: zhangsan,age: 18}
数组(List、Set):

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

pets:
 - cat
 - dog
 - pig

行内写法:

pets: [cat,dog,pig]

3)配置文件值注入

Person类
/**
 * @author yinhuidong
 * @createTime 2020-05-04-23:14
 * 将配置文件中配置的每一个属性的值,映射到这个组件中
 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
 *      prefix = "person":配置文件中哪个下面的所有属性进行一一映射
 *  
 * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
   

    private String lastName;
    private String email;
    private Map<String,Object> maps;
    private List<String> lists;
    private Dog dog;
application.yaml
person:
  last-name: 张三
  email: 1972039773@qq.com
  maps:
    k1: v1
    k2: v2
  lists:
    - k1
    - k2
    - k3
  dog:
    name: 毛毛
    age: 9
测试类
/**
 * @author yinhuidong
 * @createTime 2020-05-04-23:35
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test1 {
   

    @Autowired
    private Person person;
    @Test
    public void test1(){
   
        System.out.println(person);
    }
}

我们可以导入配置文件处理器,以后编写配置就有提示了

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

4)@Value获取值和@ConfigurationProperties获取值比较

@ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

配置文件yml还是properties他们都能获取到值;

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
   

    /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * <bean/>
     */
    @Value("21")
    private String lastName;
    @Value("#{person.email}")
    private String email;
    private Map<String,Object> maps;
    private List<String> lists;
    private Dog dog;

5)配置文件注入值数据校验

@Component
@ConfigurationProperties(prefix = "person")
@Validated//校验
public class Person {
   

    /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * <bean/>
     */
    @Value("21")
    private String lastName;
    @Email
    private String email;
    private Map<String,Object> maps;
    private List<String> lists;
    private Dog dog;

3.@PropertySource&@ImportResource&@Bean

1)@PropertySource:加载指定的配置文件;

@Component
@ConfigurationProperties(prefix = "person")
//@Validated//校验
@PropertySource("classpath:person.properties")
public class Person {
   

    /**
     * <bean class="Person">
     *      <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
     * <bean/>
     */
    @Value("21")
    private String lastName;
    @Email
    private String email;
    private Map<String,Object> maps;
    private List<String> lists;
    private Dog dog;

2)@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上

主配置类
@SpringBootApplication
@ImportResource("classpath:applicationContext.xml")
public class Springboot01Application {
   

    public static void main(String[] args) {
   
        SpringApplication.run(Springboot01Application.class, args);
    }

}

spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="personService" class="com.yhd.springboot01.service.PersonService"></bean>
</beans>

测试类

@Autowired
    private PersonService service;
    @Test
    public void test(){
   
        System.out.println(service);
    }

3)SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式

1、配置类@Configuration------>Spring配置文件

2、使用 @Bean 给容器中添加组件

/**
 * @author yinhuidong
 * @createTime 2020-05-05-0:39
 *
 * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
 *
 * 在配置文件中用<bean><bean/>标签添加组件
 *
 */
@Configuration
public class MyConfig {
   

    @Bean
    public PersonService getService(){
   
        return new PersonService();
    }
}

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
1.在配置文件中指定spring.profile.active=dev
2.命令行:
	java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
可以直接在测试的时候,配置传入命令行参数
3.虚拟机参数:
	-Dspring.profiles.active=dev

6.配置文件加载位置

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

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

优先级由高到低,高优先级的配置会覆盖低优先级的配置。

spring boot 会从这四个位置全部加载主配置文件,互补配置。

我们还可以通过spring.config.location来改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties

7.外部配置加载顺序

SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置

1)命令行参数

所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
多个配置用空格分开; --配置项=值

2)来自java:comp/env的JNDI属性
3)Java系统属性(System.getProperties()

4)操作系统环境变量
5)RandomValuePropertySource配置的random.*属性值

由jar包外向jar包内进行寻找;

优先加载带profile

6)jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7)jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
再来加载不带profile
8)jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9)jar包内部的application.properties或application.yml(不带spring.profile)配置文件

10)@Configuration注解类上的@PropertySource

11)通过SpringApplication.setDefaultProperties指定的默认属性

参考官方文档

8.自动配置原理

配置文件到底能写什么?怎么写?自动配置原理;
配置文件能配置的属性参照

1.自动配置原理

Spring boot 启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration

@EnableAutoConfiguration 作用:
	利用EnableAutoConfigurationImportSelector给容器中导入一些组件
	可以查看selectImports()方法的内容
	List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下  META‐INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中

所有在配置文件中能配置的属性都是在xxxxProperties类中封装着‘;配置文件能配置什么就可以参照某个功能对应的这个属性类

@ConfigurationProperties(prefix = "spring.http")//从配置文件中获取指定的值和bean的属
性进行绑定
public class HttpProperties {
   

    public static class Encoding {
   

            public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;	
            private Charset charset = DEFAULT_CHARSET;
            private Boolean force;
            private Boolean forceRequest;		
            private Boolean forceResponse;
            private Map<Locale, Charset> mapping;

在这里插入图片描述
总结:
springBoot启动会加载大量的自动配置类

我们看我们需要的功能有没有SpringBoot默认写好的自动配置类

我们再来看这个自动配置类中到底配置了哪些组件

给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这
些属性的值;

2.细节

1、@Conditional派生注解(Spring注解版原生的@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存在指定项

自动配置类必须在一定的条件下才能生效;
我们怎么知道哪些自动配置类生效;
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置
类生效;

Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - found 'session' scope (OnWebApplicationCondition)

三,日志

1.日志框架

开发一个日志框架

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

市面上的日志框架

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

左边选一个抽象层接口,右边选一个接口的实现类。

接口:SLF4J

日志实现:Logback

SpringBoot底层是Spring框架,Spring框架默认是JCL

SpringBoot选用SLF4j和logback


2.SLF4J使用

1.如何在开发中使用SLF4j

以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;给系统里面导入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以后,配置文件还是做成日志实现框架本身的配置文件。

2.遗留问题
a(slf4j+logback): Spring(commons-logging)、Hibernate(jboss-logging)、MyBatis、xxxx
统一日志记录,即使是别的框架和我一起统一使用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;
3)、中间替换包?
@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();

在这里插入图片描述

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

Spring框架用的是commons-logging;

<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的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可;

4.日志使用

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日志...");        
} 

SpringBoot修改日志的默认配置

logging.level.com.atguigu=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

日志输出格式

日志输出格式:
%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.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>

example:

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

5.切换日志框架

sl4j+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-over-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>

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="atguigu-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
			%d表示日期时间,
			%thread表示线程名,
			%-5level:级别从左显示5个字符宽度
			%logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
			%msg:日志消息,
			%n是换行符
        -->
        <layout class
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值