• SpringBoot实战技能


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

    1. public class Addition {
    2. //实现两个数的加法
    3. public int add(int a,int b){
    4. int m=a+b;
    5. return m;
    6. }
    7. }
    8. import com.msds.demo.Addition;
    9. import org.junit.Assert;
    10. import org.junit.jupiter.api.Test;
    11. import org.junit.runner.RunWith;
    12. import org.springframework.boot.test.context.SpringBootTest;
    13. import org.springframework.test.context.junit4.SpringRunner;
    14. @RunWith(SpringRunner.class)//使@SpringBootTest注解生效 加载Springboot测试
    15. @SpringBootTest//创建Spring的ApplicationContext,并将其注入到测试类中
    16. class Ch031junitApplicationTests {
    17. @Test
    18. void contextLoads() {
    19. Addition addition=new Addition();
    20. int temp=addition.add(1,1);
    21. System.out.println(temp);
    22. Assert.assertEquals("计算的结果正确!",temp,2);
    23. }
    24. }

    读取配置文件

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

    application.properties

    application.yml

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

    YAML语法

    – 使用缩进表示层级关系

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

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

    – 大小写敏感

    1.YAML——基本语法

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

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

    1. server:
    2. 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:大写用_ 

    演示案例:

    配置文件

    1. user12:
    2. #userName: "张\n三"
    3. userName: '张\n三'
    4. age: 18
    5. boss: true
    6. brith: 2020/10/1
    7. #maps: {key01: one,key02: two}
    8. maps:
    9. key01: one
    10. key02: two
    11. #lists: [list01,list02,list03]
    12. lists:
    13. - list01
    14. - list02
    15. - list03
    16. #dog: {name: 欢欢, age: 6}
    17. dog:
    18. name: 欢欢
    19. age: 6
    20. #str: [str01,str02,str03]
    21. str:
    22. - str01
    23. - str02
    24. - str03

     JavaBean

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

     

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

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

     测试类

    1. @Autowired
    2. private User user;
    3. @Test
    4. void contextLoads() {
    5. String result=user.toString();
    6. System.out.println(result);
    7. }

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

    1. # idea使用的是utf-8
    2. # 配置user的值
    3. user12.userName=张三1001
    4. user12.age=18
    5. user12.boss=true
    6. user12.brith=2020/10/1
    7. user12.maps.key01=value01
    8. user12.maps.key02=value02
    9. user12.lists=集合1,集合2,集合3
    10. user12.dog.name=贝贝
    11. user12.dog.age=8
    12. user12.str=数组1,数组2,数组3

    解决方案:

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

     

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

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

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

    配置文件注入值数据校验

     

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

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

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

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

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

    1. import org.springframework.boot.context.properties.ConfigurationProperties;
    2. import org.springframework.context.annotation.PropertySource;
    3. import org.springframework.stereotype.Component;
    4. @Component
    5. @PropertySource(value = {"classpath:student.properties"})//加载指定的配置文件
    6. @ConfigurationProperties(prefix = "stu")//加载指定的配置文件的前缀
    7. public class Student {
    8. private String stuName;
    9. private Integer stuAge;
    10. //此处省略 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配置当前启用的环境

    1. spring:
    2. profiles:
    3. active: test
    4. #指定使用哪个环境
    5. ---
    6. server:
    7. port: 8282
    8. spring:
    9. profiles: dev
    10. #指定属于哪个环境
    11. ---
    12. server:
    13. port: 8484
    14. spring:
    15. profiles: test
    16. #指定属于哪个环境

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

    Spring Boot的自动配置

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

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

    演示案例

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

    1. <!--此依赖的作用是给项目引入与JDBC操作相关的依赖-->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-starter-jdbc</artifactId>
    5. </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注解的源码,如下

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

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

    1. @Configuration(
    2. proxyBeanMethods = false
    3. )
    4. @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
    5. @ConditionalOnMissingBean(
    6. type = {"io.r2dbc.spi.ConnectionFactory"}
    7. )
    8. @EnableConfigurationProperties({DataSourceProperties.class})
    9. @Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class})
    10. public class DataSourceAutoConfiguration {
    11. public DataSourceAutoConfiguration() {
    12. }
    13. //省略部分代码。。。
    14. }
    15. @Configuration:让一个类变成一个配置类,拥有与Spring的配置文件相同的功能
    16. @ConditionalOnClass:条件注解,是@Conditional的扩展注解。可以判断当前某些类存在时进行后续代码的操作。
    17. 如上述代码表示项目中同时有DataSource.class和EmbeddedDatabaseType.class时,
    18. 执行@EnableConfigurationProperties注解的操作。
    19. @EnableConfigurationProperties:为某个类中的属性赋值,如上述代码表示为DataSourceProperties的属性赋值
    20. @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:判断是否满足自动配置的条件,如果满足,则完成自动配置

    1. public class SayHello {
    2. private String helloMsg;
    3. public String sayHello(){
    4. return "hello "+helloMsg;
    5. }
    6. public String getHelloMsg() {
    7. return helloMsg;
    8. }
    9. public void setHelloMsg(String helloMsg) {
    10. this.helloMsg = helloMsg;
    11. }
    12. }
    13. -----------------------------------------------------
    14. import org.springframework.boot.context.properties.ConfigurationProperties;
    15. //读取application.yml文件中配置的以hello为前缀、名为helloMsg的属性的值。这里给helloMsg设置了默认值为"spring boot"
    16. @ConfigurationProperties(prefix = "hello")
    17. public class SayHelloProperties {
    18. private String helloMsg="spring boot";
    19. public String getHelloMsg() {
    20. return helloMsg;
    21. }
    22. public void setHelloMsg(String helloMsg) {
    23. this.helloMsg = helloMsg;
    24. }
    25. }
    26. -----------------------------------------------------
    27. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    28. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    29. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    30. import org.springframework.boot.context.properties.EnableConfigurationProperties;
    31. import org.springframework.context.annotation.Bean;
    32. import org.springframework.context.annotation.Configuration;
    33. import javax.annotation.Resource;
    34. @Configuration
    35. @ConditionalOnClass({SayHello.class})
    36. @EnableConfigurationProperties({SayHelloProperties.class})
    37. @ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)
    38. /*
    39. @ConditionalOnProperty注解的作用是通过prefix、value、matchIfMissing三个属性来决定是否
    40. 给项目提供SayHello实例。当matchIfMissing为false时,则必须在application.yml中找到指定的
    41. prefix为hello、名称为helloMsg的配置项。如果找不到,则自动配置无法给项目提供SayHello实例。
    42. 反之,当matchIfMissing为true时,不管application.yml文件中是否有所需要的配置项,自动配置
    43. 都会给项目提供SayHello实例
    44. */
    45. public class SayHelloAutoConfiguration {
    46. @Resource
    47. private SayHelloProperties sayHelloProperties;
    48. @Bean
    49. @ConditionalOnMissingBean({SayHello.class})
    50. public SayHello sayHello(){
    51. SayHello sayHello = new SayHello();
    52. sayHello.setHelloMsg(sayHelloProperties.getHelloMsg());
    53. return sayHello;
    54. }
    55. }

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

    1. # Auto Configure
    2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    3. com.msds.demo.SayHelloAutoConfiguration

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

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

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

    1. import com.msds.demo.SayHello;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.stereotype.Controller;
    4. import org.springframework.web.bind.annotation.RequestMapping;
    5. import org.springframework.web.bind.annotation.ResponseBody;
    6. @Controller
    7. public class HelloController {
    8. @Autowired
    9. private SayHello sayHello;
    10. @RequestMapping("/hello")
    11. @ResponseBody
    12. public String hello(){
    13. return sayHello.sayHello();
    14. }
    15. }

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

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

    1. hello:
    2. helloMsg: mybatis

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

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

    关闭Spring Boot 的自动配置

    关闭方式一:注解方式

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

    @SpringBootApplication( exclude={ DataSourceAutoConfiguration.class } )

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

    1. spring:
    2. autoconfigure:
    3. exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

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

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

    在application.properties配置文件中添加

    # 开启SpringBoot的debug模式

    debug=true

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

    1. Positive matches:(自动配置类启动)
    2. -----------------
    3. DispatcherServletAutoConfiguration matched:
    4. - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
    5. - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition)
    6. Negative matches:(没有启动,没有匹配成功的自动配置类)
    7. -----------------
    8. ActiveMQAutoConfiguration:
    9. Did not match:
    10. - @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.添加如下依赖

    1. <dependency>
    2. <groupId>javax.servletgroupId>
    3. <artifactId>javax.servlet-apiartifactId>
    4. <scope>providedscope>
    5. dependency>
    6. <dependency>
    7. <groupId>javax.servletgroupId>
    8. <artifactId>jstlartifactId>
    9. dependency>
    10. <dependency>
    11. <groupId>org.springframework.bootgroupId>
    12. <artifactId>spring-boot-starter-tomcatartifactId>
    13. dependency>
    14. <dependency>
    15. <groupId>org.apache.tomcat.embedgroupId>
    16. <artifactId>tomcat-embed-jasperartifactId>
    17. dependency>

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

    1. spring:
    2. mvc:
    3. view:
    4. prefix: /WEB-INF/jsp/
    5. suffix: .jsp

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

    1. @Controller
    2. public class HelloController {
    3. @RequestMapping(value = "/login",method = RequestMethod.GET)
    4. public String index(Map<String,Object> map){
    5. System.out.println("你好-SpringBoot!");
    6. map.put("name","你好-SpringBoot!");
    7. return "index";
    8. }
    9. }

    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

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="user" class="com.msds.bean.User">
    6. <property name="who">
    7. <value>张三</value>
    8. </property>
    9. </bean>
    10. </beans>

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

    1. public class User {
    2. private String who;
    3. public String getWho() {
    4. return who;
    5. }
    6. public void setWho(String who) {
    7. this.who = who;
    8. }
    9. }

    在test测试类编写

    1. @SpringBootTest
    2. class Ch036duxmlApplicationTests {
    3. @Test
    4. void contextLoads1() {
    5. ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
    6. User us=(User)ac.getBean("user");
    7. System.out.println(us.getWho());
    8. }
    9. @Resource
    10. private User user;
    11. @Test
    12. void contextLoads() {
    13. System.out.println(user.getWho());
    14. }
    15. }

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

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

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

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

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

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

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

    1. import org.springframework.context.annotation.Bean;
    2. import org.springframework.context.annotation.Configuration;
    3. /**
    4. * @Configuration 指明当前类是一个配置类,就是来代替之前的Spring配置文件
    5. * 在配置文件中用标签添加组件
    6. */
    7. @Configuration
    8. public class MyAppConfig {
    9. //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
    10. @Bean
    11. public User user01(){
    12. System.out.println("配置类@Bean给容器中添加组件了...");
    13. User us=new User();
    14. us.setWho("李四");
    15. return us;
    16. }
    17. }

    在test测试类编写

    1. @SpringBootTest
    2. class Ch036duxmlApplicationTests {
    3. @Resource
    4. private User user01;
    5. @Test
    6. void contextLoads() {
    7. System.out.println(user01.getWho());
    8. }
    9. }

    使用LogBack 日志

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

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

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

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

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter</artifactId>
    4. <version>2.3.4.RELEASE</version>
    5. <scope>compile</scope>
    6. </dependency>

     SpringBoot使用它来做日志功能;

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-logging</artifactId>
    4. <version>2.3.4.RELEASE</version>
    5. <scope>compile</scope>
    6. </dependency>

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

    总结:

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

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

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

    在application.properties中配置LogBack 日志

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

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

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

    默认配置

    1. import org.junit.jupiter.api.Test;
    2. import org.slf4j.Logger;
    3. import org.slf4j.LoggerFactory;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. @SpringBootTest
    6. class Ch0371rizhiApplicationTests {
    7. //记录器
    8. //private Logger log= LoggerFactory.getLogger(Ch0371rizhiApplicationTests.class.getName());
    9. private Logger log= LoggerFactory.getLogger(getClass());
    10. @Test
    11. void contextLoads() {
    12. //日志级别
    13. //由低到高 trace < debug < info < warn < error
    14. //可以调整输出的日志级别;日志就只会在这个级别以后的高级别生效
    15. //修改application.properties——logging.level.包名=级别
    16. log.trace("这是trace日志。。。跟踪");
    17. log.debug("这是debug日志。。。调试");
    18. //SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
    19. log.info("这是info日志。。。");
    20. log.warn("这是warn日志。。。警告");
    21. log.error("这是error日志。。。错误");
    22. }
    23. }

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

    1. application.properties文件中设置
    2. #logging.level.包名=级别 只有该包下的类会使用该级别
    3. logging.level.com.msds=trace
    4. ---------------------------------------------------------
    5. application.yml文件中设置
    6. logging:
    7. level:
    8. com:
    9. 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修改日志的默认配置

    1. #logging.level.包名=级别 只有该包下的类会使用该级别
    2. logging.level.com.bdqn=trace
    3. #logging.file.path= 指定log日志的路径
    4. #不指定路径在当前项目下生成springboot.log日志
    5. #logging.file.name=springboot.log
    6. #可以指定完整的路径
    7. #logging.file.name=E:/springboot.log
    8. #在当前磁盘的根路径下创建spring文件夹和里面的springboot.log文件
    9. logging.file.name=spring/springboot.log
    10. #在控制台输出日志的格式
    11. logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
    12. #指定文件中日志输出的格式
    13. logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n
    14. #设置日志的格式时,如果写在了yml文件中会提示如下错误
    15. #Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token
    16. #found character '%' that cannot start any token. (Do not use % for indentation)
    17. #解决方式是将值 整个的用英文单引号引起来

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

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

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

    1. application.yml 文件
    2. #logging:
    3. # config: classpath:日志配置文件的位置和名称
    4. logging:
    5. config: classpath:a.xml
    6. application.properties 文件
    7. #logging.config=classpath:日志配置文件的位置和名称
    8. logging.config=classpath:a.xml

    注意:

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

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

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

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <configuration>
    3. <!--输出日志到控制台-->
    4. <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
    5. <layout>
    6. <pattern>
    7. <!--
    8. %p:日志级别
    9. %d:时间 精确到毫秒
    10. %msg:日志消息
    11. %n:换行
    12. -->
    13. [%p]%d -- %msg%n
    14. </pattern>
    15. </layout>
    16. </appender>
    17. <!--输出日志到文件-->
    18. <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    19. <filter class="ch.qos.logback.classic.filter.LevelFilter">
    20. <level>debug</level>
    21. <onMatch>DENY</onMatch>
    22. </filter>
    23. <encoder>
    24. <pattern>
    25. [%p]%d -- %msg%n
    26. </pattern>
    27. </encoder>
    28. <!--指定文件的输出位置-->
    29. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    30. <fileNamePattern>
    31. E:/logs2021/%d.log
    32. </fileNamePattern>
    33. </rollingPolicy>
    34. </appender>
    35. <root level="info">
    36. <appender-ref ref="consoleLog"></appender-ref>
    37. <appender-ref ref="fileLog"></appender-ref>
    38. </root>
    39. </configuration>

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

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

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

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

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

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

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

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

    1. <!--输出日志到控制台-->
    2. <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
    3. <!--可以指定某段配置只在某个环境下生效-->
    4. <layout>
    5. <springProfile name="kaifa">
    6. <pattern>
    7. [%-5level]%d - %contextName 开发 - %msg%n
    8. </pattern>
    9. </springProfile>
    10. <springProfile name="!kaifa">
    11. <pattern>
    12. [%-5level]%d - %contextName - %msg%n
    13. </pattern>
    14. </springProfile>
    15. </layout>
    16. </appender>

    application.properties中激活环境

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

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

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

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

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

    的子元素

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

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

     日志过滤器,如可以过滤指定级别的日志等

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

    1. <filter class="ch.qos.logback.classic.filter.LevelFilter">
    2. <level>ERRORlevel>
    3. <onMatch>DENYonMatch>
    4. <onMismatch>ACCEPTonMismatch>
    5. filter>

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

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

    日志输出时的循环策略。常用的循环策略为TimeBasedRollingPolicy

    1. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    2. <fileNamePattern>
    3. ${logback.dir}/info.${logback.projname}.%d{yyyy-MM-dd}.log
    4. fileNamePattern>
    5. <maxHistory>90maxHistory>
    6. <totalSizeCap>1GBtotalSizeCap>
    7. rollingPolicy>

     

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

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

    子元素,用来设置日志输出策略

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

  • 相关阅读:
    pyplot设置字体格式大小、坐标轴刻度在图内
    制作sd卡启动盘
    从源码看vue(v2.7.10)的computed的实现原理
    Python自学教程4-数据类型学什么
    【深度学习】4-梯度确认时遇bug:写了个糟糕的softmax函数
    关于Reactor模型,我们需要知道哪些内容
    前端框架Vue2.0+Vue3.0学习笔记01
    前端——HTML基础
    Android Gradle8.0以上多渠道写法以及针对不同渠道导入包的方式,填坑!
    postgresql搭建
  • 原文地址:https://blog.csdn.net/weixin_47541976/article/details/126718644