整合JUnit 测试

代码测试是开发工作中一个非常重要的环节,之前课程中学习了使用Junit进行代码测试的方法。创建Spring Boot项目时,默认会为项目添加一个名为spring-boot-starter-test的依赖,此依赖会为项目引入相关的测试组件。这些组件支持多种测试框架,如:JUnit、AssertJ、Hamcrest 等

演示案例:

在IDEA中创建Spring Boot项目,实现两位数的加法并使用JUnit对该方法进行测试

用于测试类的注解

@RunWith(SpringRunner.class):使@SpringBootTest 注解生效

@SpringBootTest:创建Spring 的 ApplicationContext,并将其注入到测试类中

@Before、@Test、@After等

最后提示: 虽然 idea生成的测试类,只自动生成了一个@SpringBootTest注解;没有@RunWith注解;也是能够运行的;

但是建议:标准测试类里还是要有@RunWith的,作用是告诉java你这个类通过用什么运行环境运行,例如启动和创建spring的应用上下文。否则你需要为此在启动时写一堆的环境配置代码。你在IDEA里去掉@RunWith仍然能跑是因为在IDEA里识别为一个JUNIT的运行环境,相当于就是一个自识别的RUNWITH环境配置。但在其他IDE里并没有。所以,为了你的代码能在其他IDE里边正常跑,建议还是加@RunWith

public class Addition {//实现两个数的加法public int add(int a,int b){int m=a+b;return m;}}import com.msds.demo.Addition;import org.junit.Assert;import org.junit.jupiter.api.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)//使@SpringBootTest注解生效  加载Springboot测试@SpringBootTest//创建Spring的ApplicationContext,并将其注入到测试类中class Ch031junitApplicationTests {@Testvoid contextLoads() {Addition addition=new Addition();int temp=addition.add(1,1);System.out.println(temp);Assert.assertEquals("计算的结果正确!",temp,2);}}

读取配置文件

SpringBoot使用一个全局的配置文件,配置文件名是固定的 (必须是下面的);

application.properties

application.yml

在Web项目中,经常需要从properties文件获取配置信息。在Spring项目中可以通过@PropertySource和@Value注解实现该功能。而在Spring Boot项目中使用@Value和@ConfigurationProperties注解,即可获取application.properties或application.yml文件中的配置信息。

YAML语法

– 使用缩进表示层级关系

– 缩进时不允许使用Tab键,只允许使用空格。

– 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

– 大小写敏感

1.YAML——基本语法

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

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

server:port: 8082

属性和值也是大小写敏感

YAML支持的三种数据结构

– 字面量:单个的、不可再分的值

– 对象、map:键值对的集合

– 数组、list和set集合:一组按次序排列的值

2.YAML——值的写法

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

k: v  字面直接来写

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

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

name: "zhangsan \n lisi":输出;zhangsan 换行 lisi

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

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

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

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

对象还是k: v的方式

friends:
lastName: zhangsan
age: 18
########################################################
对象名:
属性名: 属性值
属性名: 属性值
########################################################
map集合名:
key: value
key: value

行内写法

friends: {lastName: zhangsan,age: 18}
#########################################################
对象名: {属性名: 属性值,属性名: 属性值...}
#########################################################
friends: {key: value,key: value...}

2.3数组、集合(List、Set):

-(空格)值表示数组中的一个元素

pets:
- cat
- dog
- pig
#########################################################
数组名:
- 值1
- 值2
- 值3
#########################################################
list或set集合名:
- 值1
- 值2
- 值3

行内写法

pets: [cat,dog,pig]
#########################################################
数组名: [值1,值2,值3...]
#########################################################
list或set集合名: [值1,值2,值3...]

配置文件值得注入

属性名匹配规则(Relaxed binding) 

– user.userName:使用标准方式

– user.user-name:大写用-

– user.user_name:大写用_

演示案例:

配置文件


user12:#userName: "张\n三"userName: '张\n三'age: 18boss: truebrith: 2020/10/1#maps: {key01: one,key02: two}maps:key01: onekey02: two#lists: [list01,list02,list03]lists:- list01- list02- list03#dog: {name: 欢欢, age: 6}dog:name: 欢欢age: 6#str: [str01,str02,str03]str:- str01- str02- str03

JavaBean

import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.Arrays;import java.util.Date;import java.util.List;import java.util.Map;
/*** 将配置文件中配置的每一个属性的值,映射到这个组件中* @ConfigurationProperties 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定*          prefix = "user12",配置文件中那个下面的所有属性进行一一映射,YAML文件中的属性一定要和Bean的属性进行关联* 只有这个组件是容器中的组件,才能使用容器提供的功能   添加@Component* @ConfigurationProperties(prefix = "user12")默认从全局配置文件中获取值* @ConfigurationProperties注解实际上是通过属性的setter方法来进行注入,因此要获取配置信息的相关属性* 需要在其所在的Bean类中创建该属性的setter方法*/@Component@ConfigurationProperties(prefix = "user12")public class User {private String userName;//用户姓名private Integer age;//用户年龄private boolean boss;//用户老板private Date brith;//用户生日private Map<String,Object> maps;private List<Object> lists;private Dog dog;private String[] str;//此处省略 getter and setter  toString()}public class Dog {private String name;private Integer age;//此处省略 getter and setter}

我们可以导入配置文件处理器,以后编写配置就有提示了,在pom.xml中进行配置

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

测试类

 @Autowiredprivate User user;@Testvoid contextLoads() {String result=user.toString();System.out.println(result);}

properties配置文件在idea中默认utf-8可能会乱码

# idea使用的是utf-8# 配置user的值user12.userName=张三1001user12.age=18user12.boss=trueuser12.brith=2020/10/1user12.maps.key01=value01user12.maps.key02=value02user12.lists=集合1,集合2,集合3user12.dog.name=贝贝user12.dog.age=8user12.str=数组1,数组2,数组3

解决方案:

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

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

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

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

配置文件注入值数据校验


import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import org.springframework.validation.annotation.Validated;import javax.validation.constraints.Email;import java.util.Date;@Component//@ConfigurationProperties(prefix = "user12")//@Validated //JSR303数据校验public class Person {@Value("${user12.userName}")private String perName;//用户姓名@Value("#{11*2}") //#{SpringEL}private Integer age;//用户年龄@Value("${user12.brith}")private Date brith;//用户生日//@Email //JSR303数据校验 email必须是邮箱格式private String email;//像数组集合对象等 复杂类型是不支持的//此处省略 getter and setter  toString()

JSR303数据校验,需在pom.xml中引入依赖

  <!--JSR303数据校验,添加的依赖--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.1.5.Final</version></dependency>

使用@PropertySource加载指定的配置文件

@PropertySource(value = {"classpath:文件名称.properties"})//加载指定的配置文件

import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.PropertySource;import org.springframework.stereotype.Component;@Component@PropertySource(value = {"classpath:student.properties"})//加载指定的配置文件@ConfigurationProperties(prefix = "stu")//加载指定的配置文件的前缀public class Student {private String stuName;private Integer stuAge;//此处省略 getter and setter  toString()

多环境配置

问题

在实际的项目开发过程中,往往会有多套运行环境

开发环境

测试环境

生产环境

在项目开发、测试、上线过程中,开发者需要不断修改项目的配置信息,使得项目的开发及部署很容易出错

解决方案:

Spring Boot提供了一种多环境配置的解决方案

为项目提供多套环境配置

在不同运行环境中为项目加载不同的配置文件

实现多环境配置有properties文件和YAML文件两种方式

使用properties文件实现多环境配置

使用properties文件实现多环境配置时,每个环境都需要有单独的properties文件

使用properties实现多环境配置时,需要注意以下两点:

1.文件的命令方式,必须为application-环境名称.properties的形式。环境名称由开发者自行指定。

2.由于两个配置文件只能有一个生效,所以需要指定当前环境启动的是哪个配置文件。在application.properties文件中使用spring.profiles.active来进行此项配置。该属性的值必须指定为配置文件名称“application-环境名称.properties”中的“环境名称”。

使用YAML文件实现多环境配置

只需一个配置文件即可,所有配置信息均放在application.yml中

两套配置信息之间用“---”隔开

通过spring.profiles.active配置当前启用的环境


spring:profiles:active: test#指定使用哪个环境---server:port: 8282spring:profiles: dev#指定属于哪个环境---server:port: 8484spring:profiles: test#指定属于哪个环境

使用YAML文件实现多环境配置时,也可以采用和properties文件类似的多文件配置的方式

Spring Boot的自动配置

使用Spring Boot开发项目时,很多配置都是Spring Boot默认配置好的。

但是在真实的项目开发过程中,项目需求是灵活多变的,为了实现某些需求,经常需要对这些默认配置进行修改。

演示案例

创建一个Spring Boot项目,在pom.xml中添加如下依赖

 <!--此依赖的作用是给项目引入与JDBC操作相关的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency>

启动项目,查看项目的启动日志,如图

分析:为什么Spring Boot 会自动地寻找数据库连接的地址呢?

当Spring Boot 项目中引入了spring-boot-starter-web 和spring-boot-starter-test 这两个依赖之后,会添加两个与自动配置相关的Jar包

两个Jar 包下面都包含名为“spring.factories”的文件

打开spring.factories 文件,会看到很多自动配置的类

这些类是怎么被Spring Boot读取到的呢?

Spring Boot项目的启动类上需要添加@SpringBootApplication注解。此注解为复合注解,由多个注解组合而成。其中就包含一个名为@EnableAutoConfiguration的注解。在项目中找到此注解,按住Ctrl键单击此注解,进入@EnableAutoConfiguration注解的源码,如下

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import({AutoConfigurationImportSelector.class})//在@EnableAutoConfiguration源码中通过@Import注解引入了AutoConfigurationImportSelector类。//在AutoConfigurationImportSelector类中,通过分析可以发现程序会去所有的自动配置包中//查找spring.factories文件,再从spring.factories文件中加载所有的自动配置类。public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};}

在spring.factories这个文件中,可以找到一个名为DataSourceAutoConfiguration的自动配置类。DataSourceAutoConfiguration的源码如下

@Configuration(proxyBeanMethods = false)@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})@ConditionalOnMissingBean(type = {"io.r2dbc.spi.ConnectionFactory"})@EnableConfigurationProperties({DataSourceProperties.class})@Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})public class DataSourceAutoConfiguration {public DataSourceAutoConfiguration() {}//省略部分代码。。。}@Configuration:让一个类变成一个配置类,拥有与Spring的配置文件相同的功能@ConditionalOnClass:条件注解,是@Conditional的扩展注解。可以判断当前某些类存在时进行后续代码的操作。如上述代码表示项目中同时有DataSource.class和EmbeddedDatabaseType.class时,执行@EnableConfigurationProperties注解的操作。@EnableConfigurationProperties:为某个类中的属性赋值,如上述代码表示为DataSourceProperties的属性赋值@Import:将某个类的实例引入Spring的IoC容器

项目中未添加spring-boot-starter-jdbc依赖时,项目中只有DataSource.class,没有EmbeddedDatabaseType.class,不满足执行@EnableConfigurationProperties的条件

引入spring-boot-starter-jdbc依赖之后,由于此依赖中包含EmbeddedDatabaseType.class,满足@EnableConfigurationProperties的操作条件,为DataSourceProperties的属性进行赋值

赋值需要url属性,Spring Boot会去application.yml文件中寻找,未找到故引发异常

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

演示案例——加深对Spring Boot自动配置的理解

需求:在Spring Boot项目启动时,判断项目中是否存在名为SayHello的类。如果存在,则实例化此类并给其属性赋值

1.创建Spring Boot项目

2.并在该项目中创建3个类分别为:SayHello、SayHelloProperties、SayHelloAutoConfiguration这3个类分别代表的含义如下:

SayHello:核心业务类,此类中编写自动配置的核心业务

SayHelloProperties:读取配置信息,以便赋值给SayHello类的属性

SayHelloAutoConfiguration:判断是否满足自动配置的条件,如果满足,则完成自动配置

public class SayHello {private String helloMsg;public String sayHello(){return "hello "+helloMsg;}public String getHelloMsg() {return helloMsg;}public void setHelloMsg(String helloMsg) {this.helloMsg = helloMsg;}}-----------------------------------------------------import org.springframework.boot.context.properties.ConfigurationProperties;//读取application.yml文件中配置的以hello为前缀、名为helloMsg的属性的值。这里给helloMsg设置了默认值为"spring boot"@ConfigurationProperties(prefix = "hello")public class SayHelloProperties {private String helloMsg="spring boot";public String getHelloMsg() {return helloMsg;}public void setHelloMsg(String helloMsg) {this.helloMsg = helloMsg;}}-----------------------------------------------------import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;@Configuration@ConditionalOnClass({SayHello.class})@EnableConfigurationProperties({SayHelloProperties.class})@ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)/*@ConditionalOnProperty注解的作用是通过prefix、value、matchIfMissing三个属性来决定是否给项目提供SayHello实例。当matchIfMissing为false时,则必须在application.yml中找到指定的prefix为hello、名称为helloMsg的配置项。如果找不到,则自动配置无法给项目提供SayHello实例。反之,当matchIfMissing为true时,不管application.yml文件中是否有所需要的配置项,自动配置都会给项目提供SayHello实例*/public class SayHelloAutoConfiguration {@Resourceprivate SayHelloProperties sayHelloProperties;@Bean@ConditionalOnMissingBean({SayHello.class})public SayHello sayHello(){SayHello sayHello = new SayHello();sayHello.setHelloMsg(sayHelloProperties.getHelloMsg());return sayHello;}}

3.为了让SpringBoot能够对自动配置进行管控,需要在项目的resources/META-INF目录中添加spring.factories文件,并在此文件添加如下代码


# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.msds.demo.SayHelloAutoConfiguration

4.将该项目打包到本地仓库

5.创建第二个SpringBoot项目。在pom文件中添加依赖,将上一个项目依赖到该项目中

6.在第二个项目中创建控制层代码,创建HelloController类,并注入SayHello的实例。实现了当前台请求hello()方法时能返回sayHello()方法的内容

import com.msds.demo.SayHello;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class HelloController {@Autowiredprivate SayHello sayHello;@RequestMapping("/hello")@ResponseBodypublic String hello(){return sayHello.sayHello();}}

7.启动该项目,请求控制器中的hello()方法,可以看到请求效果,如图

8.在该项目的application.yml文件中添加如下代码

hello:helloMsg: mybatis

再次请求hello()方法,看到前台页面会显示“hello mybatis”,代表自动配置成功

实现Spring Boot 自动配置的关键在于@EnableAutoConfiguration 注解可以开启Spring Boot 的自动配置。条件判断注解可以根据项目的当前条件,根据需要进行Bean 的管理和属性的配置

关闭Spring Boot 的自动配置

关闭方式一:注解方式

在启动类的@SpringBootApplication 注解上通过配置exclude 属性进行指定,如需关闭多个类的自动配置,可以用逗号隔开

@SpringBootApplication( exclude={ DataSourceAutoConfiguration.class } )

关闭方式二:配置文件方式:在application.yml中配置


spring:autoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

我们怎么知道项目中哪些自动配置类生效

我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

在application.properties配置文件中添加

# 开启SpringBoot的debug模式

debug=true

在启动服务。会在控制台中出现如下信息:


Positive matches:(自动配置类启动)-----------------DispatcherServletAutoConfiguration matched:- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)- @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition)Negative matches:(没有启动,没有匹配成功的自动配置类)-----------------ActiveMQAutoConfiguration:Did not match:- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

Spring Boot整合JSP

Spring Boot 默认支持的模板引擎有4 种,分别为FreeMarker、Groovy、Thymeleaf 和Mustache,不包括JSP 模板引擎。

但可以通过引入相关依赖来整合JSP 模板引擎。

实现步骤如下:

1.添加如下依赖

<!--整合JSP--><!--添加servlet依赖模块--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><!--添加jstl标签库依赖模块--><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId></dependency><!--添加tomcat依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><!--<scope>provided</scope>--></dependency><!--使用jsp引擎,springboot内置tomcat没有此依赖--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency>

2.配置视图解析器:在application.yml文件中添加如下配置,该配置可以将逻辑视图名解析成具体的JSP文件在项目中的路径

spring:mvc:view:prefix: /WEB-INF/jsp/suffix: .jsp

3.编写控制器:在Controller类中编写如下代码


@Controllerpublic class HelloController {@RequestMapping(value = "/login",method = RequestMethod.GET)public String index(Map<String,Object> map){System.out.println("你好-SpringBoot!");map.put("name","你好-SpringBoot!");return "index";}}

4.在项目的src/main下创建webapp/WEB-INF/jsp,在jsp文件夹下放jsp文件(必须有webapp/WEB-INF这个包,否则访问不到)。

解决无法新建jsp文件问题:点击File-Project Structrue,选择Modules,展开项目下的web,如下图

在弹出的窗口指定你的项目资源路径,项目名\src\main\webapp

保存退出,现在可以在项目中建jsp文件了

5.启动项目测试:请求http://服务器地址:端口号/项目别名/login。

启动成功,访问路径进入了Controller中指定的方法,但是页面404;

解决办法:

在对话框中设置箭头所指的为当前内容即可。如何没有该选项,maven clean 和 compile 完毕即可看到该内容。

使用XML的配置

在Spring Boot 项目中,除了application.yml、application.properties文件,一般很少添加其他配置文件;但是在实际开发中为了集成其他框架或者配置一些中间件,也会不得不添加XML配置文件。

在Spring Boot 项目中,可以使用@ImportResource 注解读取XML配置文件

第一步:将@ImportResource 注解标注到启动类上,或者某个配置类(即添加了@Configuration注解的类)上

第二步:指定要引入的XML配置文件的位置。如:在资源目录下存在的applicationContext.xml配置文件则可以通过@ImportResource(value="classpath:applicationContext.xml")

演示案例

导入Spring的配置文件,让配置文件里面的内容生效;

编写applicationContext.xml

<?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="user" class="com.msds.bean.User"><property name="who"><value>张三</value></property></bean></beans>

编写applicationContext.xml文件中对应的User类


public class User {private String who;public String getWho() {return who;}public void setWho(String who) {this.who = who;}}

在test测试类编写

@SpringBootTestclass Ch036duxmlApplicationTests {@Testvoid contextLoads1() {ApplicationContext ac=new  ClassPathXmlApplicationContext("applicationContext.xml");User us=(User)ac.getBean("user");System.out.println(us.getWho());}@Resourceprivate User user;@Testvoid contextLoads() {System.out.println(user.getWho());}}

运行测试方法,发现程序报错,无法获取配置文件,所以:

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

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


//以下@ImportResource的两种写法都可以@ImportResource(value = "classpath:applicationContext.xml")//@ImportResource(locations = {"classpath:applicationContext.xml"})//想让Spring的配置文件生效,加载进来@SpringBootApplicationpublic class Ch036duxmlApplication {public static void main(String[] args) {SpringApplication.run(Ch036duxmlApplication.class, args);}}

现在在程序中不推荐使用上面的方式,SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式(下一章节会讲到:实现java配置方式)

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

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

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** @Configuration 指明当前类是一个配置类,就是来代替之前的Spring配置文件* 在配置文件中用<bean></bean>标签添加组件*/@Configurationpublic class MyAppConfig {//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名@Beanpublic User user01(){System.out.println("配置类@Bean给容器中添加组件了...");User us=new User();us.setWho("李四");return us;}}

在test测试类编写

@SpringBootTestclass Ch036duxmlApplicationTests {@Resourceprivate User user01;@Testvoid contextLoads() {System.out.println(user01.getWho());}}

使用LogBack 日志

在开发和调试阶段,日志可以帮助开发者更高效、便捷的定位问题。在应用的运维阶段,日志也可以记录系统运行过程中的异常信息。

常用的日志记录框架主要有三种:Log4j 、Log4j2 、LogBack 

LogBack 和Log4j2 都是Log4j 的升级版,LogBack 在性能上比Log4j 更加高效

Spring Boot 把LogBack 作为首选的日志记录框架,spring-boot-starter-web 依赖默认包含了LogBack 的相关依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.3.4.RELEASE</version><scope>compile</scope></dependency>

SpringBoot使用它来做日志功能;

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId><version>2.3.4.RELEASE</version><scope>compile</scope></dependency>

底层依赖关系(在pom.xml文件中右键Diagrams--->Show Dependencies)

总结:

1).SpringBoot底层也是使用slf4j+logback的方式进行日志记录

2).SpringBoot也把其他的日志都替换成了slf4j;

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

在application.properties中配置LogBack 日志

SpringBoot项目启动后所输出的日志即为基于logback组件所输出的日志

以上为默认的日志输出格式,在实际的开发中,有时需要灵活配置日志输出方式,比如日志的格式、输出级别、日志输出的位置等。

通过application.yml 文件,可以实现部分日志配置

默认配置


import org.junit.jupiter.api.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestclass Ch0371rizhiApplicationTests {//记录器//private Logger log= LoggerFactory.getLogger(Ch0371rizhiApplicationTests.class.getName());private Logger log= LoggerFactory.getLogger(getClass());@Testvoid contextLoads() {//日志级别//由低到高  trace < debug < info < warn < error//可以调整输出的日志级别;日志就只会在这个级别以后的高级别生效//修改application.properties——logging.level.包名=级别log.trace("这是trace日志。。。跟踪");log.debug("这是debug日志。。。调试");//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别log.info("这是info日志。。。");log.warn("这是warn日志。。。警告");log.error("这是error日志。。。错误");}}

SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;我们可以在application.properties设置日志级别,如下:


application.properties文件中设置#logging.level.包名=级别   只有该包下的类会使用该级别logging.level.com.msds=trace---------------------------------------------------------application.yml文件中设置logging:level:com:msds: debug
日志输出格式:%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.包名=级别   只有该包下的类会使用该级别logging.level.com.bdqn=trace#logging.file.path=    指定log日志的路径#不指定路径在当前项目下生成springboot.log日志#logging.file.name=springboot.log#可以指定完整的路径#logging.file.name=E:/springboot.log#在当前磁盘的根路径下创建spring文件夹和里面的springboot.log文件logging.file.name=spring/springboot.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#设置日志的格式时,如果写在了yml文件中会提示如下错误#Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token#found character '%' that cannot start any token. (Do not use % for indentation)#解决方式是将值 整个的用英文单引号引起来

编写单独的LogBack 日志(如果需要更详细的日志配置,可以使用单独的日志配置文件

在默认情况下,SpringBoot项目可以读取resources资源目录中特定名字的日志配置文件,比如logback-spring.xml、logback.xml。

application.yml 中可以通过logging.config 属性指定自定义日志配置文件的位置


application.yml 文件#logging:#  config: classpath:日志配置文件的位置和名称logging:config: classpath:a.xmlapplication.properties 文件#logging.config=classpath:日志配置文件的位置和名称logging.config=classpath:a.xml

注意:

SpringBoot官方推荐使用带有-spring的文件名作为日志配置,即使用logback-spring.xml,而不是logback.xml。

当然,如果需要根据不同的环境概况使用不同的日志配置,也可以自定义日志配置文件的名称

logback-spring.xml通过标签元素来配置LogBack日志,开发者必须掌握这些标签元素的作用,才能熟练进行LogBack的配置。如下:


<?xml version="1.0" encoding="UTF-8"?><configuration><!--输出日志到控制台--><appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><layout><pattern><!--%p:日志级别%d:时间 精确到毫秒%msg:日志消息%n:换行-->[%p]%d -- %msg%n</pattern></layout></appender><!--输出日志到文件--><appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>debug</level><onMatch>DENY</onMatch></filter><encoder><pattern>[%p]%d -- %msg%n</pattern></encoder><!--指定文件的输出位置--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>E:/logs2021/%d.log</fileNamePattern></rollingPolicy></appender><root level="info"><appender-ref ref="consoleLog"></appender-ref><appender-ref ref="fileLog"></appender-ref></root></configuration>

logback-spring.xml文件常用元素及其作用

1.<configuration>:配置文件的根元素节点。包含3 个属性

scan:当此属性设置为true 时表示如果配置文件发生改变,将被重新加载,反之则不对配置文件是否发生改变进行检测。默认为true

scanPeriod:监测日志配置文件是否有修改的时间间隔,默认是1分钟

debug:当此属性设置为true 时,将输出LogBack 默认日志信息。默认值为false

2.<contextName>:日志的上下文名称。用于区分不同程序的日志

<contextName>testLogback</contextName><!--输出日志到控制台--><appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><layout><pattern><!--%p:日志级别%-5level:级别从左显示5个字符宽度%d:时间 精确到毫秒%msg:日志消息%n:换行%contextName:取出contextName标签中的值-->[%-5level]%d - %contextName - %msg%n</pattern></layout></appender>

可以指定某段配置只在某个环境下生效

<!--输出日志到控制台--><appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><!--可以指定某段配置只在某个环境下生效--><layout><springProfile name="kaifa"><pattern>[%-5level]%d - %contextName 开发 - %msg%n</pattern></springProfile><springProfile name="!kaifa"><pattern>[%-5level]%d - %contextName - %msg%n</pattern></springProfile></layout></appender>

application.properties中激活环境


#激活环境spring.profiles.active=kaifa

3.<property>:设置变量值,在日志配置文件中使用。有两个属性:name 和value。其中name的值是变量的名称,value的值是变量的值。定义的变量值可以通过“${}”调用。

  <property name="logback.dir" value="E:/logback/test"/><property name="logback.projname" value="logbackproj"/>

4.<appender>:配置日志输出的策略。有两个属性:name 和class

class 用来指定具体采用的输出策略。常用的有两种:ConsoleAppender 控制台输出策略 和 RollingFileAppender 文件输出策略

<appender>的子元素

<layout>:指定日志格式,在ConsoleAppender 控制台输出策略中使用

<encoder>:指定日志格式,和layout 的格式化方式相同,只是encoder须在RollingFileAppender 文件输出策略中使用。采用RollingFileAppender 策略则必须指定该属性,否则日志将输出不到文件中

<filter>:日志过滤器,如可以过滤指定级别的日志等

一个<appender>可以有多个过滤器,按照配置顺序执行。最常用的过滤器是LevelFilter级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMatch和onMismatch接受或拒绝日志。示例如下:

  <filter class="ch.qos.logback.classic.filter.LevelFilter"><!--过滤Error级别的日志--><level>ERROR</level><!--匹配到Error级别的日志就禁止--><onMatch>DENY</onMatch><!--没有匹配到就允许--><onMismatch>ACCEPT</onMismatch></filter>

<file>:当输出日志到文件时,指定文件的路径和文件名,可以是相对路径,也可以是绝对路径。如果上级目录不存在会自动创建。没有默认值。

注意——在Windows中,反斜杠\需要转义,也可以使用正斜杠/。

<rollingPolicy>:日志输出时的循环策略。常用的循环策略为TimeBasedRollingPolicy

 <!--指定文件的输出位置--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--定义把每一天的日志归档到一个文件中,其中用到了property定义的变量logback.dir和logback.projname--><fileNamePattern>${logback.dir}/info.${logback.projname}.%d{yyyy-MM-dd}.log</fileNamePattern><!--只保留最近90天的日志--><maxHistory>90</maxHistory><!--用来指定日志文件的上限大小,到了这个值,就会删除旧的日志--><totalSizeCap>1GB</totalSizeCap></rollingPolicy>

5.<root>:设置日志输出级别和采用哪种日志输出策略

level 属性,用来指定日志的输出级别

<appender-ref>子元素,用来设置日志输出策略

可以配置多个<appender>,并指定让这些<appender>同时生效

SpringBoot实战技能相关推荐

  1. 视频教程-SpringBoot实战开发视频-Java

    SpringBoot实战开发视频 十余年计算机技术领域从业经验,在中国电信.盛大游戏等多家五百强企业任职技术开发指导顾问,国内IT技术发展奠基人之一. 杨千锋 ¥69.00 立即订阅 扫码下载「CSD ...

  2. 视频教程-SpringBoot实战教程:SpringBoot入门及前后端分离项目开发-Java

    SpringBoot实战教程:SpringBoot入门及前后端分离项目开发 十三,CSDN达人课课程作者,CSDN 博客作者,现就职于某网络科技公司任职高级 Java 开发工程师,13blog.sit ...

  3. 视频教程-SpringBoot实战视频教程-Java

    SpringBoot实战视频教程 书籍<分布式中间件技术实战 Java版>的作者,拥有6年Java后端开发经验和2年项目管理经验,熟悉Java领域流行技术,拥有多个微服务.分布式项目实战. ...

  4. 都在强力进阶学习 springboot 实战派文档

    不仅如此,本文还对比讲解了多种同类技术的使用和区别,读者可以根据自己的喜好进行选择. 开发模式:本文讲解了历史悠久,但现在依然被广泛使用的分层应用开发模式 MVC(ModelView Controll ...

  5. SpringBoot实战手册,值得收藏,每个Java工程师都必须要掌握

    如今,我们处在一个快速变化的年代,软件技术的更迭越来越快.之前,Java工程师必须掌握的技能是SSH框架(Struts+Spring+Hibernate) ,但是很快就变成了SSM框架(Spring ...

  6. 提升 NLP 实战技能的一点建议

    作为最典型的 AI 领域之一,NLP  (自然语言处理,Natural Language Processing) 被誉为"人工智能皇冠上的明珠",这些年也是越来越热门,基本上是各大 ...

  7. SpringBoot 实战 (八) | 使用 Spring Data JPA 访问 Mysql 数据库

    微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 如题,今天介绍 Spring Data JPA 的使用. 什么是 Spring Data JPA 在介绍 Spri ...

  8. SpringBoot 实战 (九) | 整合 Mybatis

    微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,本文通过注解的形式实 ...

  9. SpringBoot 实战:如何从零开发 “淘宝”

    疫情期间,不少人选择宅家购物. 但当你每天在"淘宝""京东""网易考拉"上剁手买买买,钱包瘪下去的时候,有没有考虑一下自己开发个商城呢? 钱 ...

最新文章

  1. 多线程中使用mktime和setenv函数
  2. jupyter怎么调字体_AJ里最低调的系列之一:Air Jordan 3
  3. mac无法访问samba共享 提示输入用户名密码
  4. 石油化工静设备计算机辅助设计桌面系统,PV Desktop 石油化工静设备计算机辅助设计桌面系统简介...
  5. iOS项目架构 小谈
  6. yii2 js加载顺序呢
  7. Linux中brk()系统调用,sbrk(),mmap(),malloc(),calloc()的异同【转】
  8. 【时间统计】windows/linux 获取本地时间(精确到微妙)
  9. 基于应用程序级的Apache认证配置(普通认证篇)
  10. MySQL数据库环境变量设置
  11. 新海诚没有参与制作的作品_还未开始!新海诚的下一部作品还是白纸
  12. pascal方格稿纸
  13. java ruby 比较_java和ruby的一些比较
  14. 市场调研及发展前景分析报告有什么作用
  15. Linux磁盘分区初始化
  16. Jenkins插件下载失败或下载慢或报错There were errors checking the update sites: SSLHandshakeException: sun.secu解决方案
  17. 【重学计算机网络】DHCP IP的“孽缘“
  18. win10的c语言程序闪退,Win10专业版软件打不开闪退怎么办?
  19. grafana mysql 时间段选择_mysql – 选择特定时间段内的所有可用项目
  20. linux安装php漏洞补丁教程,LAAP Linux+Apache+Mysql(AliSQL)+PHP安装教程

热门文章

  1. Java可变参数Object... args
  2. API设计中性能提升的10个建议
  3. 使用notepadd++运行python命令
  4. 谈谈JavaScript数组使用注意事项及踩过的坑,排序问题,for in遍历问题等
  5. 个性化推荐系统:“网络爬虫+相似矩阵”技术运作流程
  6. String、StringBuilder、StringBuffer,谁性能最高?
  7. win10装vc6.0
  8. dynaform5.8.1曲面网格划分
  9. 星起航:适合抖音小店的产品类目有哪些
  10. 鼠标点击某处, 让精灵移动到该处 (如下图) 鼠标移动时, 让精灵跟随鼠标移动