SpringBoot系列

Spring Boot简介

  1. Spring boot是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring boot能简化我们之前采用SpringMVC+Spring+Mybatis框架进行开发的过程。
  2. 在以往我们采用SpringMVC+Spring+Mybatis框架进行开发的时候,搭建和整合三大框架,我们需要做很好工作,比如配置web.xml,配置Spring,配置Mybatis,并将它们整合在一起等,而Spring boot框架对此开发过程进行了革命性的颠覆,抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程。
  3. 所以采用Spring boot可以非常容易和快速的创建基于Spring框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控也变简单了。
  4. 正因为Spring boot它化繁为简,让开发变得极其简单和快捷,所以在业界备受关注。Spring boot在国内的关注趋势也日渐超过Spring。
  1. 能够快速创建基于Spring的应用程序。(简化配置)
  2. 能够直接使用java的main方法启动内嵌的Tomcat,Jetty服务器运行Spring boot程序,不需要部署war包文件。
  3. 提供约定的starter POM来简化来简化Maven配置,让Maven配置变得简单。
  4. 根据项目的maven依赖配置,Spring boot自动配置Spring,SpringMVC等其它开源框架。
    .提供程序的健康检查等功能。(检查内部的运行状态等)
    基本可以完全不使用xml配置文件,采用注解配置。(或者默认约定的配置,代码中已经实现)

微服务

微服务:架构风格

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

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

环境准备

环境约束

-jdk1.8

-maven 3.x

-springboot1.5.9RELEASE

MAVEN设置

1
2
3
4
5
6
7
8
9
10
11
12
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

Spring Boot HelloWorld

浏览器发送hello请求,服务器接受请求并处理,响应HelloWorld字符串;

创建一个maven工程(jar)

导入springBoot 依赖

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
    <exclusion>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
</dependencies>

编写主程序,启动Spring Boot应用

/**
 * @Date2020/5/23 12:53
 * SpringBootApplication来标注一个主程序
 **/
@SpringBootApplication
public class HelloWorldMainApplication {
    public static void main(String[] args) {
        //spring应用启动起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}

编写相关的Controller、Service

运行主程序测试

简化部署

<!--可以将应用打包成一个可执行的jar宝-->
<build>
    <plugins>
        <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
将这个应用打成jar包,直接用java -jar的命令进行执行;
终止运行
netstat -aon|findstr "8080"
taskkill /f /pid 8976  终止jar命令运行的程序

Hello World探究

pom文件

父文件
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

Spring Boot的版本仲裁中心

以后我们导入依赖默认是不需要写版本号的(没有在dependencies里面管理的依赖自然需要声明版本号)

导入的依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter-web:

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

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

主程序类
/**
 * @Date2020/5/23 12:53
 * SpringBootApplication来标注一个主程序,说明这是一个Spring Boot应用
 **/
@SpringBootApplication
public class HelloWorldMainApplication {

    private static Logger log= LoggerFactory.getLogger(HelloWorldMainApplication.class);

    public static void main(String[] args) {
        log.info("HelloWorldMainApplication is success!");
        //spring应用启动起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}

@SpringBootApplication Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用。

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

@SpringBootConfiguration:SpringBoot的配置类;

​ 标注在某个类上,标识这是一个SpringBoot的配置类;

​ @Configuration:配置类上来标注这个注解:

​ 配置类—配置文件;配置类也是容器中的一个组件;@Componet

@EnableAutoConfiguration:开启自动配置功能

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

@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})

@AutoConfigurationPackage:自动配置包

@Import({Registrar.class})

​Spring的底层注解@Import,给容器中导入一个组件;导入的组件由Registrar.class

将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到

Spring容器;

​@Import({EnableAutoConfigurationImportSelector.class})

​给容器中导入组件

​EnableAutoConfigurationImportSelector:导入那些组件的选择器;

​将所有需要导入的组件以全类名的方式返回;

​会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所

有组件,并配置好这些组件;免去了我们手动编写配置注入功能组件的工作。

SpringFactoriesLoader.loadFactoryNames(
  getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

Spring Boot在启动的时候从类路径下的”META-INF/spring.factories”中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。

J2EE的整体整合解决方案和自动配置都在m2\repository\org\springframework\boot\spring-boot-autoconfigure\1.5.9.RELEASE\spring-boot-autoconfigure-1.5.9.RELEASE.jar

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

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

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

默认生成的Spring Boot项目

  1. 主程序已经生成好了,只需要实现我们自己的逻辑

  2. resources文件夹的目录结构

    static:保存所有的js css images

    templates:保存所有的页面模板;(Spring Boot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面);可以使用模板引擎(freemarker、thymeleaf);

    application.properties:Spring Boot 的配置文件,可以修改一些默认设置;

配置文件

SpringBoot使用一个全局的配置文件,配置文件名是固定的;

application.properties

application.yml

配置文件的作用:修改SpringBoot自动配置的默认值

SpringBoot在底层都给我们自动配置好;

YAML是一个标记语言:以前的配置大都使用xxx.xml文件,而yaml以数据为中心,比json,xml更适合作配置文件

YAML语法

k: v :标识一对键值对(空格必须有)

以空格的缩进来控制层级关系,只要左对齐的一列数据,都是一个层级的,属性和值也是大小写敏感;

值的写法

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

​ 字面量直接来写,字符串默认不用加上单引号或者双引号

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

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

​ ‘’:单引号,会转义特殊字符,输出zhangsan \n lisi

对象、map(属性和值)(键值对)

​k:v :对象还是k:v的形式

friends:
lastName: zhangsan
    age: 18

行内写法

friends{lastName:zhangsan,age:18}

数组(list、set)

pets:
  - cat
  - dog
 - pig

行内写法

pets:{cat,dog,pig}

配置文件的注入和校验

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

person:
  name: zhangsan
  age: 18
  boss: false
  birth: 2020/12/12
  map: {k1: v1,k2: 12}
  objectList:
    - lisi
    - wangwu
  dog:
    name: mumu
    age: 2

javaBean

/**
 * @ClassNamePerson
 * @Description 将配置文件中的每一个属性的值映射到这个组件中
 * @Author
 * @Date2020/5/23 16:08
 * @ConfigurationProperties告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
 * prefix = "person":配置文件中哪个下面的所有属性进行一一映射
 * 只有这个组件是容器中的组件,才能用容器提供的@ConfigurationProperties功能,需要加上@Component
 * @ConfigurationProperties(prefix = "person")默认从全局配置文件中获取值
 **/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private boolean boss;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> objectList;
    private Dog dog;

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

<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
 </dependency>
@ConfigurationProperties @Value
功能 批量注入文件的属性 一个个指定
松散绑定 支持(lastName,last-name) 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

配置文件yml还是properties都可获取到值

如果只需要获取简单属性值可用@Value

@PropertySource&ImportResource

@PropertySource:加载指定的配置文件,需要指定配置文件的路径

/**
 * @Description 将配置文件中的每一个属性的值映射到这个组件中
 * @ConfigurationProperties告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
 * prefix = "person":配置文件中哪个下面的所有属性进行一一映射
 * 只有这个组件是容器中的组件,才能用容器提供的@ConfigurationProperties功能,需要加上@Component
 **/
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private boolean boss;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> objectList;
    private Dog dog;

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

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别,想让Spring的配置文件生效,加载进来;@ImportResource需要标注在一个配置类上

@ImportResource(locations = {"classpath:beans.xml"})

导入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="helloService" class="com.think.hello.service.HelloService"></bean>
</beans>

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

1、配置类===Spring配置文件

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

@Configuration
public class myAppConfig {
    //将方法的返回值添加到容器,容器中这个组件默认的id就是方法名
    @Bean
    public HelloService helloService(){
        return new HelloService();
    }
}

配置文件占位符

占位符后期之前配置的值,如果没有可用:指定默认值

person:
  name: zhangsan${random.uuid}
  boss: false
  age: ${random.int}
  birth: 2020/12/12
  map: {k1: v1,k2: 12}
  objectList:
    - lisi
    - wangwu
    - zhangsan
  dog:
    name: ${person.hello:hello}mumu
    age: 2

Profile

多profile文件

我们在主配置文件编写的时候,文件名可用applicaton-{profile}.properties/yml

默认使用application.properties的配置

yml支持多文档块的方式

server:
  port: 8080
spring:
  profiles:
    active: prod
---
server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: prod

激活指定profile

在配置文件中指定spring.profiles.active=dev
命令行的方式

​ 在启动配置里 –spring.profiles.active=dev或java -jar xxx.jar –spring.profiles.active=dev

虚拟机参数

​ -Dspring.profiles.active=dev

配置文件的加载默认的优先级由高到低

高优先级的配置会覆盖低优先级的配置生效;

SpringBoot会从这四个位置全部加载主配置文件;互补配置;

-file:./conifg/

-file:./

-classpath:/config/

-classpath:/

我们还可用通过spring.config.location来改变默认的配置文件位置

项目打包后可用命令行参数的形式,启动项目的时候来指定配置文件的新位置,指定配置文件会和默认加载的这些配置文件共同起作用形成配置

-jar xxx.jar –server.port=8080

自动配置原理

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

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties

@SpringBootApplication
@SpringBootApplication是一个复合注解或派生注解,在@SpringBootApplication中有一个注解@EnableAutoConfiguration,该注解是开启自动配置
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

@EnableAutoConfiguration也是一个派生注解,其中的关键功能是由@Import提供,其导入的AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包。 spring-boot-autoconfigure-x.x.x.x.jar里就有一个spring.factories文件。spring.factories文件由一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表, 这些类名以逗号分隔。
spring-boot-autoconfigure-x.x.x.x.jar -> META-INF/spring.factories -> org.springframework.boot.autoconfigure.xxx.xxxAutoConfiguration 类列表将会被实例化到Spring容器。
SpringBoot项目启动时,@SpringBootApplication用在启动类SpringApplication.run()的内部就会置顶selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。

以redis自动配置,解析Spring自动配置原理

将redis starter依赖加入

<!--redis jar-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration会被实例化到容器。该类为什么会被实例化? 因为它在META-INF/spring.factories的Auto Configure列表。
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration被实例化,然而redis也会被实例化即创建RedisTemplate在Spring容器。

然而实例化redis对象是有条件的即@ConditionalOnClass({RedisOperations.class}),意思:当给定的类名在类路径上存在,则实例化当前Bean。

也就是想Spring创建redis实例对象,必须需要将redis starter包:spring-boot-starter-data-redis依赖引入。有了redis starter依赖springboot自动配置就会检测到classpath路径下有相关的类,然后就可以实例化对应的类了,这就是自动配置的原理。

知识点:类上有该注解@Configuration,类被实例化 时@bean会自动执行,生成对应的bean实例,放入Spring容器。

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration会导入JedisConnectionConfiguration.class
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})

JedisConnectionConfiguration.class有注解:@ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class}) 

spring是怎样读取redis配置参数?

关键是org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration的注解:@EnableConfigurationProperties({RedisProperties.class})

知识点:@EnableConfigurationProperties会将配置文件的key-value映射成Java对象。
redis配置类,如果没redis配置,使用本地的redis这需要本地安装redis服务,如果有redis配置就设置redis host、port等属性

appliccation.yml redis配置。必须以spring.redis开头

spring-boot-starter

SpringBoot 可以省略众多的繁琐配置,它的众多starter可以说功不可没。 例如集成redis,只需要pom.xml中引入spring-boot-starter-data-redis,配置文件application.yml中加入spring.redis.database等几个关键配置项即可,常用的starter还有spring-boot-starter-web、spring-boot-starter-test等,相比传统的xml配置大大减少了集成的工作量。

原理

利用starter实现自动化配置只需要两个条件–maven依赖、配置文件。引入maven实质就是导入jar包,spring-boot启动的时候会找到starter jar包中的resources/META-INF/spring.factories文件,根据spring.factories文件中的配置,找到需要自动配置的类。

注解 说明
@Configuration 表明是一个配置文件,被注解的类将成为一个bean配置类
@ConditionalOnClass 当classpath下发现该类的情况下进行自动配置
@ConditionalOnBean 当classpath下发现该类的情况下进行自动配置
@EnableConfigurationProperties 使@ConfigurationProperties注解生效
@AutoConfigureAfter 完成自动配置后实例化这个bean

实现

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.air</groupId>
    <artifactId>starter-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>starter-demo</name>
    <description>spring-boot-starter demo</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Source -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,在IDE中编辑配置文件时,会出现提示。 打包选择jar-no-fork,因为这里不需要main函数。

EnableDemoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnableDemoConfiguration {
}

DemoProperties

@Data
@ConfigurationProperties(prefix = "demo")
public class DemoProperties {
    private String name;
    private Integer age;
}

name和age对应application.properties里面的demo.name和demo.age

DemoAutoConfiguration

@Configuration
@ConditionalOnBean(annotation = EnableDemoConfiguration.class)
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    DemoService demoService (){
        return new DemoService();
    }

}

这里设置自动配置的相关条件,和相关操作,由于这里只想写一个最简单的demo,所以这里只需要简单注入一个bean,没有复杂逻辑,实际开发中,这个类是最关键的。

DemoService

public class DemoService {

    @Autowired
    private DemoProperties demoProperties;

    public void print() {
        System.out.println(demoProperties.getName());
        System.out.println(demoProperties.getAge());
    }
}

这里不需要@Service,因为已经通过DemoAutoConfiguration注入spring容器了。

spring.factories

在resources/META-INF/下创建spring.factories文件:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.air.starterdemo.config.DemoAutoConfiguration
告诉spring-boot,启动时需要扫描的类。

测试

pom.xml 本地mvn install之后,在新的spring-boot项目里面引入

com.air
starter-demo
0.0.1-SNAPSHOT

配置文件

demo.name = ooo
demo.age = 11

如果使用的是IDEA,在编辑时会出现提示。

测试

@SpringBootApplication
@EnableDemoConfiguration
public class Demo1Application {

    @Autowired
    private DemoService demoService;

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

    @PostConstruct
    public void test() {
        demoService.print();
    }
}

启动main函数,控制台会打印出配置文件中的name和age,一个简单的spring-boot-starter就写好了

spring.factories

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider

每一个autoconfigure类都是容器中的一个组件,都加入到容器中,用他们来做自动配置

每一个自动配置类进行自动配置功能;

以HttpEncodingAutoConfiguration为例解释自动配置原理

@Configuration(//表示这是一个自动配置类
proxyBeanMethods = false
)
@EnableConfigurationProperties({ServerProperties.class})//启用configurationProperties功能,将配置文件中对应的值和xxxProperties绑定起来
@ConditionalOnWebApplication(//Spring底层@Conditional注解,根据不同条件,如果满足指定条件,整个配置里里面的配置就会生效,判断当前应用是否是web应用,是就生效不是就不生效
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})//判断当前项目有没有这个类
CharacterEncodingFilter:SpringMVC中进行乱码解决的过滤器
@ConditionalOnProperty(//判断配置文件中是否存在某个配置server.servlet.encoding.enabled如果不存在判断也是成立的,即使我们的配置文件中不配置server.servlet.encoding.enabled=true,也是默认生效的  
    prefix = "server.servlet.encoding",//从配置文件中获取指定的值和bean的属性进行绑定
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {

根据当前不同的条件判断,决定这个配置类是否生效

如果生效,这个配置类就会给容器中添加各种组件,这些组件的属性是从对应的properties类中获取的,这些类里面的每一个又是和配置文件绑定的

@Bean//给容器中添加一个组件,这个组件的某些值需要从properties中获取
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
    CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    filter.setEncoding(this.properties.getCharset().name());
    filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
    filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
    return filter;
}

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

总结 1、SpringBoot启动会加载大量的自动配置类;

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

​ 3、我们再来看这个自动配置类中配置了哪些组件,只要我们要用的组件有,就不需要再来配置了,

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

xxxAutoConfiguration:自动配置类

给容器中添加组件

xxxProperties:封装配置文件中相关属性

自动配置类哪个生效了

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

============================
CONDITIONS EVALUATION REPORT
============================


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)

DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class 'javax.servlet.ServletRegistration' (OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)


Negative matches:(没有启用的,没匹配成功的)
-----------------

ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

AopAutoConfiguration.AspectJAutoProxyingConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)

ArtemisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

SpringBoot与日志

日志门面SLF4J日志实现Logback;

SpringBoot:底层是Spring框架,Spring框架默认用JCL;

SpringBoot选用SLF4J(日志的抽象层)和logback;

以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象曾里面的方法。

应该给系统导入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后,配置文件还是做成日志实现框架自己本身的配置文件

遗留问题

不同系统有不同的日志框架,需要做到统一日志记录,即使别的框架和我一起使用slf4j进行输出

如何让系统中所有日志都统一到slf4j

将系统中其他日志框架排除,用中间包替换原有的日志框架,再导入slf4d其他的实现

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

SpringBoot 使用它来做日志

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

<dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-to-slf4j</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jul-to-slf4j</artifactId>
      <scope>compile</scope>
    </dependency>
</dependencies>

总结:1、SpringBoot底层也是使用slf4j+logback的方式进行日志记录

​ 2、SpringBoot也把其他的日志都替换成了slf4j

​ 3、中间替换包

​ 4、如果要引入其他框架,一定要把这个框架的默认日志移除掉

​ Spring框架用的commons-logging;

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-console</artifactId>
    <version>${activemq.version}</version>
        <exclusions>
            <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
</dependency>

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

private static Logger logger = LoggerFactory.getLogger(HelloApplication.class);
public static void main(String[] args) {
    SpringApplication.run(HelloApplication.class, args);
    //日志级别由低到高
    //可以调整输出的日志级别
    logger.trace("trace");
    logger.debug("debug");
    logger.info("HelloApplication is Success");
    logger.warn("warn");
    logger.error("error");
}

logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n

%d表示日期时间
%thread表示线程名
%-5level:级别从左显示5个字符的宽度
%logger{50}表示logger名字最长50个字符,否则按照句点分割
%msg:日志消息
%n换行符

SpringBoot修改默认日志配置

logging.level.com.think=trace
#当前项目下生成springboot.log日志,可以指定完整的路径D:/springboot.log
#logging.file.name=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

<!-- 日志记录器,日期滚动记录 -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">

<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/log_error.log</file>

<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<!-- 归档的日志文件的路径,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>

<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>

<!-- 追加方式记录日志 -->
<append>true</append>

<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>

<!-- 此日志文件只记录error级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

可以按照slfj的日志适配图,进行相关的切换

idea依赖分析-pom.xml-右键-Diagrams-Show Dependencies

SpringBoot与Web开发

使用SpringBoot

创建SpringBoot应用,选中我们需要的模块;

SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来;

自己编写业务逻辑代码;

自动配置原理

这个场景SpringBoot帮我们配置了什么,能不能修改,能修改哪些配置,能不能扩展

xxxAutoConfiguration:帮我们给容器中自动配置组件

xxxProperties:配置类来封装配置文件中的内容

SpringBoot对静态资源的映射规则

ResourceProperties可以设置静态资源有关的参数,缓存时间等

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
            "classpath:/resources/", "classpath:/static/", "classpath:/public/" };

    /**
     * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
     * /resources/, /static/, /public/].

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
        return;
    }
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    if (!registry.hasMappingForPattern("/webjars/**")) {
        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
        .addResourceLocations("classpath:/META-INF/resources/webjars/")
        .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
    .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
    .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
}

所有/webjars/**都去classpath:/META-INF/resources/webjars/找资源

webjars:以jar包的方式引入静态资源;

https://www.webjars.org/

http://localhost:8080/webjars/jquery/3.5.1/jquery.js

<!--引入jquery-webjar-->
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>

/**访问当前项目的任何资源(静态资源文件夹)

"/":当前项目的根路径
"classpath:/META-INF/resources/",
"classpath:/resources/", 
"classpath:/static/", 
"classpath:/public/

以什么样的路径访问静态资源

spring.mvc.static-path-pattern=/static/**
Spring Boot 2.3要在配置文件配置静态资源访问路径

欢迎页,静态资源文件夹下所有的index.html页面;被”/**“映射

所有的**/favicon.ico都是在静态资源文件下找

模板引擎

Thymeleaf

语法更简单,功能更强大

引入Thymeleaf

<!--模板引擎-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

    private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
    //只要我们把html页面放在classpath:/templates/,thymeleaf就能自动渲染
    public static final String DEFAULT_PREFIX = "classpath:/templates/";

    public static final String DEFAULT_SUFFIX = ".html";

    /**
     * Whether to check that the template exists before rendering it.
     */
    private boolean checkTemplate = true;

导入thymeleaf的名称空间
<html xmlns:th="http://www.thymeleaf.org">

语法

参考thymeleaf手册

SpringMVC自动配置

Spring Boot自动配置好了SpringMVC

以下是SpringBoot对SpringMVC的默认

The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View)视图对象决定如何渲染,是转发还是重定向)
    • ContentNegotiatingViewResolver符合所有的视图解析器的
    • 如何定制:我们可以给容器中添加一个视图解析器@Bean;自动将其组合进来
    • 如何验证是否添加进来了-搜索DispatcherServlet-doDispatch-在这打断点,用debug方式运行
    • 随便请求一个页面可以看到DispatcherServlet的viewResolvers里面已经包含了我们自定义的视图解析器
  • Support for serving static resources, including support for WebJars (covered later in this document)).静态资源文件夹路径,webjars

  • Automatic registration of Converter, GenericConverter, and Formatter beans.

    • Converter:转换器 类型转换使用
    • Formatter:格式化器日期的转换
  • Support for HttpMessageConverters (covered later in this document).

    • HttpMessageConverters:SpringMVC用来转换Http请求和响应的;User–Json
  • Automatic registration of MessageCodesResolver (covered later in this document).

    • 定义错误代码生成规则的
  • Static index.html support.(静态首页访问)

  • Custom Favicon support (covered later in this document).(favicon.ico)

  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

    • 我们可以配置一个ConfigurableWebBindingInitializer来替换默认的

      初始化WebDataBinder;
      请求数据===JavaBean

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

使用WebMvcConfigurerAdapter扩展SpringMVC的功能

编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型;不能标注@EnableWebMvc。

既保留了所有的自动配置,也能用我们扩展的配置

//作用:请求me的时候会到success页面
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter{

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/me").setViewName("success");
    }
}

原理:

  1. WebMvcAutoConfiguration 是SpringMVC的自动配置类

  2. 在做其他自动配置时会导入@Import(EnableWebMvcConfiguration.class)

    @Configuration(proxyBeanMethods = false)
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
    
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
    
    //从容器中获取所有WebMvcConfigurer的配置
    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
        this.configurers.addWebMvcConfigurers(configurers);
            //一个参考实现,将所有的WebMvcConfigurer相关配置都来一起调用
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                for (WebMvcConfigurer delegate : this.delegates) {
                    delegate.addViewControllers(registry);
                }
            }
        }
    }
    
  3. 容器中所有的WebMvcConfigurer都会一起起作用,包括自己写的配置类

全面接管SpringMVC

SpringBoot对SpringMVC的自动配置不需要,所有都是我们自己配,只需要在配置类中添加@EnableWebMvc

原理:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {//这个注解上导入了DelegatingWebMvcConfiguration
}

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {//DelegatingWebMvcConfiguration.class又继承了WebMvcConfigurationSupport

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
//容器种没有(WebMvcConfigurationSupport)这个组件的时候,这个自动配置类才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

@EnableWebMvc将WebMvcConfigurationSupport组件导入进来;
导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能;

如何修改SpringBoot的默认配置

  1. SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean,@Component)如果有就用用户配置的,如果没有才自动配置;如果有些组件可以有多个,他是将用户配置的和自己默认的组合起来
  2. 在SpringBoot种会有非常多的xxxConfigurer帮助我们进行扩展配置

登陆页面

 //所有的WebMvcConfigurerAdapter组件都会一起起作用
@Bean//将组件注册到容器中
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
    WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("login");
            registry.addViewController("/login.html").setViewName("login");
        }
    };
    return adapter;
}

国际化

  1. 编写国际化文件,抽取页面需要显示的国际化消息

  1. SpringBoot自动配置好了管理国际化资源文件的组件

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Conditional(ResourceBundleCondition.class)
    @EnableConfigurationProperties
    public class MessageSourceAutoConfiguration {

    private static final Resource[] NO_RESOURCES = {};

    @Bean
    @ConfigurationProperties(prefix = “spring.messages”)
    public MessageSourceProperties messageSourceProperties() {

    return new MessageSourceProperties();
    

    }

    @Bean
    public MessageSource messageSource(MessageSourceProperties properties) {

    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    if (StringUtils.hasText(properties.getBasename())) {
        //设置国际化资源文件的基础名
        messageSource.setBasenames(StringUtils
                .commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
    }
    if (properties.getEncoding() != null) {
        messageSource.setDefaultEncoding(properties.getEncoding().name());
    }
    messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
    Duration cacheDuration = properties.getCacheDuration();
    if (cacheDuration != null) {
        messageSource.setCacheMillis(cacheDuration.toMillis());
    }
    messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
    messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
    return messageSource;
    

    }

  2. 去页面获取国际化的值

idea file-setting-FileEncodings-fileEncodeing将properties编码改成UTF-8,让他自动转成ascii码(只对当前项目生效)
要改默认的在file-Other Setting-DefaultSetting来修改全局默认设置