SpringBoot 核心技术

Posted by 余腾 on 2019-04-30
Estimated Reading Time 31 Minutes
Words 7k In Total
Viewed Times

一、Spring Boot 入门

1、Spring Boot 简介

Spring Boot来简化Spring应用开发,约定大于配置,just run就能创建一个独立的产品级别应用。

  • 简化Spring应用开发的一个框架;
  • 整个Spring技术栈的一个大整合;
  • J2EE开发的一站式解决方案;

2、微服务

微服务:架构风格(服务微化)
一个应用应该是一组小型服务;可以通过HTTP的方式进行互通。

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

二、Spring Boot HelloWorld

1、创建一个maven工程;(jar)

2、导入spring boot相关的依赖

1
2
3
4
5
6
7
8
9
10
11
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
</dependencies>

3、编写一个主程序;启动Spring Boot应用

1
2
3
4
5
6
7
8
9
10
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}

4、编写相关的Controller、Service

1
2
3
4
5
6
7
8
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "Hello World!";
}
}

5、简化部署

1
2
3
4
5
6
7
8
9
<!‐‐ 这个插件,可以将应用打包成一个可执行的jar包;‐‐>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐maven‐plugin</artifactId>
</plugin>
</plugins>
</build>

6、运行主程序测试



Hello World探究

1、POM文件

1
2
3
4
5
6
7
8
9
10
11
12
13
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
他的父项目是
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring‐boot‐dependencies</relativePath>
</parent>
他是来真正管理Spring Boot应用里面的所有依赖版本;

Spring Boot的版本仲裁中心;
我们导入依赖默认是不需要写版本(没有在dependencies里面管理的依赖自然需要声明版本号)


2、启动器

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

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

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

3、主程序类,主入口类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

public static void main(String[] args) {

// Spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
  • @SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;

@SpringBootApplication —>点进去发现

1
2
3
4
5
6
7
8
9
10
@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 {

@SpringBootConfiguration:Spring Boot的配置类。

1
2
@Configuration
public @interface SpringBootConfiguration {
  • —> @Configuration:spring 配置类。配置类 —– 配置文件;

    • —> @Component:配置类也是容器中的一个组件;

@EnableAutoConfiguration:开启自动配置功能;

1
2
3
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  • @AutoConfigurationPackage:自动配置包。将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器。

    • —> @Import(AutoConfigurationPackages.Registrar.class):Spring的底层注解@Import,给容器中导入一个组件;
  • @Import(EnableAutoConfigurationImportSelector.class);:给容器中导入组件

    • EnableAutoConfigurationImportSelector:导入组件的选择器; 将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中。会给容器中导入非常多的自动配置类(xxxAutoConfiguration)给容器导入这个场景需要的所有组件,并配置好组件;

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



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

IDEA:使用 Spring Initializer快速创建项目

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


四、Spring Boot配置

1、配置文件

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

Spring Boot 使用一个全局的配置文件

  • application.properties
  • application.yml

YAML:以数据为中心,比json、xml等更适合做配置文件;

1
2
server:
port: 8081

2、YAML语法

基本语法:k:(空格)v —> 表示一对键值对(空格必须有)。

  • 以空格的缩进来控制层级关系,左对齐的一列数据,都是同一个层级的,属性和值也是大小写敏感。
1
2
3
server:
port: 8081
path: /hello

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

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

  • “”:双引号; 不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思。
    name: "Spring \n Boot" 输出 ——> Spring 换行 Boot
  • ‘’:单引号; 会转义特殊字符,特殊字符最终只是一个普通的字符串数据。
    name: "Spring \n Boot" 输出 ——> Spring \n Boot

对象、Map(属性和值)(键值对):
k: v 在下一行来写对象的属性和值的关系;注意缩进。

  • k: v
1
2
3
friends:
lastName: zhangsan
age: 20
  • 行内写法:
1
friends: {lastName: zhangsan,age: 18}

数组(List、Set):

  • - 值 表示数组中的一个元素
1
2
3
4
pets:
cat
dog
pig
  • 行内写法
1
pets: [cat,dog,pig]


3、配置文件值注入

配置文件 yml

1
2
3
4
5
6
7
8
9
10
11
12
person:
lastName: Spring
age: 18
boss: false
birth: 2019/1/1
maps: {k1: v1,k2: v2}
lists:
lisi
zhaoliu
dog:
name: 小狗
age: 12

@ConfigurationProperties

  • @ConfigurationProperties:SpringBoot 将本类中所有属性和配置文件相关的配置进行绑定
  • @ConfigurationProperties(prefix = “person”) 默认从全局配置文件中获取值;

Javabean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
*/

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;

导入配置文件处理器,编写配置提示

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐configuration‐processor</artifactId>
<optional>true</optional>
</dependency>

@Value

@Value(“${person.last-name}”)

配置文件注入值数据校验:@Validated

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

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

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



@PropertySource & @ImportResource & @Bean

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

1
@PropertySource(value = {"classpath:person.properties"})

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

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

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

SpringBoot不推荐编写 Spring 配置文件


配置类

SpringBoot推荐给容器中添加组件使用全注解方式:配置类@Configuration—>Spring配置文件

@Configuration: 指明当前类是一个配置类;就是来替代之前的Spring配置文件。

@Bean: 给容器中添加组件。


配置文件占位符

随机数

1
2
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}

占位符获取之前配置的值,如果没有可以是用:指定默认值

1
person.last‐name=${person.hello:hello}


Profile

1、多Profile文件

  • 我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml
  • 默认使用 application.properties 的配置;

2、yml支持多文档块方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8081
spring:
profiles:
active: dev
‐‐‐
server:
port: 8083
spring:
profiles: dev
‐‐‐
server:
port: 8084
spring:
profiles: prod

3、激活指定profile

  • a、在配置文件中指定 spring.profiles.active=dev

  • b、命令行:可以直接在测试的时候,配置传入命令行参数

1
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
  • c、虚拟机参数;
    1
    -Dspring.profiles.active=dev

配置文件加载位置

springboot 启动会扫描以下位置的 application.properties 或者 application.yml 文件。

file:当前项目根目录。

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

优先级由高到底,所有位置的文件都会被加载,高优先级的配置会覆盖低优先级的配置;
SpringBoot 会从这四个位置全部加载主配置文件:互补配置;

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

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

1
java -jar spring-boot-config-0.0.1-SNAPSHOT.jar --spring.config.location=C:/application.properties

外部配置加载顺序

Spring Boot 支持多种外部配置方式

  • 1. 命令行参数
    1
    java -jar spring-boot-config-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
  • 2. 来自java:comp/env的JNDI属性
  • 3. Java系统属性(System.getProperties())
  • 4. 操作系统环境变量
  • 5. RandomValuePropertySource配置的random.*属性值

由jar包外向jar包内进行寻找;优先加载带profile

  • 6. jar包外部的application-{profile}.properties或application.yml(带spring.profile)
  • 7. jar包内部的application-{profile}.properties或application.yml(带spring.profile)

再来加载不带profile

  • 8. jar包外部的application.properties或application.yml(不带spring.profile)配置文件
  • 9. jar包内部的application.properties或application.yml(不带spring.profile)配置文件
  • 10. @Configuration注解类上的@PropertySource
  • 11. 通过SpringApplication.setDefaultProperties指定的默认属性

自动配置原理

配置文件属性参照

1、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2、@EnableAutoConfiguration 作用:

  • 利用 EnableAutoConfigurationImportSelector 给容器中导入一些组件。
  • 可以查看selectImports()方法的内容;
  • List configurations = getCandidateConfigurations(annotationMetadata, attributes);
1
2
3
4
5
SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下 META‐INF/spring.factories

把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中
  • 将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;
  • 每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 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.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
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.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
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.redis.RedisAutoConfiguration,\
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.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
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.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.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
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.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
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.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

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

4、以 HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

//已经和SpringBoot的配置文件映射了
private final HttpEncodingProperties properties;

//只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}

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

@Bean
public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
return new LocaleCharsetMappingsCustomizer(this.properties);
}

private static class LocaleCharsetMappingsCustomizer
implements EmbeddedServletContainerCustomizer, Ordered {

private final HttpEncodingProperties properties;

LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
this.properties = properties;
}

@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (this.properties.getMapping() != null) {
container.setLocaleCharsetMappings(this.properties.getMapping());
}
}

@Override
public int getOrder() {
return 0;
}
}
}

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

  • @Configuration: 表示这是一个配置类,可以给容器中添加组件
  • @EnableConfigurationProperties(HttpEncodingProperties.class): 启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中。
  • @ConditionalOnWebApplication: Spring底层@Conditional注解。根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;判断当前应用是否是web应用,如果是,当前配置类生效。
  • @ConditionalOnClass(CharacterEncodingFilter.class): 判断当前项目有没有这个类 CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
  • @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true):判断配置文件中是否存在某个配置spring.http.encoding.enabled;如果不存在,判断也是成立的。

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

1
2
3
4
@ConfigurationProperties(prefix = "spring.http.encoding")
public class HttpEncodingProperties {

public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
  • @ConfigurationProperties(prefix = "spring.http.encoding"): 从配置文件中获取指定的值和bean的属性进行绑定。

SpringBoot 精髓

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

@Conditional派生注解

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

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

我们可以在yml中配置 debug=true属性;来让控制台打印自动配置报告。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
=========================
AUTO-CONFIGURATION REPORT
=========================


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)


五、日志

市面上的日志框架: JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j….

日志的抽象层 日志实现
JCL(Jakarta Commons Logging) SLF4j(Simple LoggingFacade for Java) jboss-logging Log4j JUL(java.util.logging)Log4j2 Logback

SpringBoot 左边选一个门面(抽象层)、右边来选一个实现;

  • 日志门面: SLF4J;
  • 日志实现:Logback;

SpringBoot:底层是Spring框架,Spring框架默认是用JCL;SpringBoot选用 SLF4j和logback;


1、SLF4j使用

SLF4j 使用手册

  • a、日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法;
  • b、每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;
  • c、由于 log4j 和 JUL 在 SLF4j 之前出现,所以需要适配层调用。
1
2
3
4
5
6
7
8
9
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");
}
}

2、解决 log

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

  • 1、将系统中其他日志框架先排除出去。(一定要把这个框架的默认日志依赖移除掉)
  • 2、用中间包来替换原有的日志框架。
  • 3、我们导入slf4j其他的实现。

3、日志使用

日志的级别:

  • a、由低到高 trace<debug<info<warn<error
  • b、可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效。
  • c、SpringBoot默认给我们使用的是 info 级别的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //记录器
    Logger logger = LoggerFactory.getLogger(getClass());
    @Test
    public void contextLoads() {
    logger.trace("这是trace日志...");
    logger.debug("这是debug日志...");
    logger.info("这是info日志...");
    logger.warn("这是warn日志...");
    logger.error("这是error日志...");
    }

4、SpringBoot 修改日志的默认配置

1
2
3
4
5
6
7
8
9
10
11
logging.level.root=trace
#logging.path=
# 不指定路径在当前项目下生成springboot.log日志
# 可以指定完整的路径;
#logging.file=D:/springboot.log
# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
logging.path=/spring/log
# 在控制台输出的日志的格式
logging.pattern.console=%d{yyyy‐MM‐dd} [%thread] %‐5level %logger{50} %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy‐MM‐dd} === [%thread] === %‐5level === %logger{50} ==== %msg%n
logging.file logging.path Example Description
(none) (none) . 只在控制台输出
指定文件名 (none) my.log 输出日志到my.log文件
(none) 指定目录 /var/log 输出到指定目录的 spring.log 文件中
1
2
3
4
5
6
7
日志输出格式:
%d表示日期时间
%thread表示线程名
%‐5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息
%n是换行符

5、指定配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用默认配置了。

Logging System Customization
Logback logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

logback.xml: 直接就被日志框架识别了;
logback-spring.xml: 日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用 SpringBoot 的高级 Profile 功能。在 xml 文件中配置以下内容。

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

如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误
no applicable action for [springProfile]


6、切换日志框架

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



六、Spring Boot Web开发

1、SpringBoot 对静态资源的映射规则

1
2
3
4
5
6
<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>

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

Springboot ——> SpringMVC 默认配置

  • 1、所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源。

  • 2、”/**“ 访问当前项目的任何资源,都去(静态资源的文件夹)找映射。

    1
    2
    3
    4
    5
    "classpath:/META‐INF/resources/",
    "classpath:/resources/",
    "classpath:/static/",
    "classpath:/public/"
    "/":当前项目的根路径
  • 3、欢迎页, 静态资源文件夹下的所有 index.html 页面;被”/**“映射;

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


2、模板引擎 Thymeleaf

JSP、Velocity、Freemarker、Thymeleaf

R~_((Y411Z}U)B0EMVDZONV.png

1、引入Thymeleaf;

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<properties>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<!‐‐ 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 ‐‐>
<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
</properties>

2、Thymeleaf 使用

  • 把 HTML 页面放入 classpath:/templates/ —> Thymeleaf 自动渲染

原理:

1
2
3
4
5
6
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = Charset.forName("UTF‐8");
private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

使用:

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

3、语法规则

  • th:任意html属性;来替换原生属性的值

    • th:text=${ }:会转义特殊字符。
    • th:utext=${ }:不会转义特殊字符

    行内取法

    • [[…]] 对应 th:text=${ }
    • [(…)] 对应 th:utext=${ }
1
2
3
4
Simple expressions:(表达式语法)
Variable Expressions: ${...}:获取变量值;OGNL;
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:
1
2
3
4
5
6
7
8
Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;

补充:配合 th:object="${session.user} ——> *{firstName} == ${session.user.firstName}
<div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
1
2
3
Message Expressions: #{...}:获取国际化内容
Link URL Expressions: @{...}:定义URL
Fragment Expressions: ~{...}:片段引用表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Literals(字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…

Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|

Arithmetic operations:(数学运算)
Binary operators: + , ‐ , * , / , %
Minus sign (unary operator): ‐

Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not

Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )

Conditional operators:条件运算(三元运算符)
If‐then: (if) ? (then)
If‐then‐else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No‐Operation: _


SpringMVC自动配置

https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications

27.1.1 Spring MVC auto-configuration

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:

WebMvcAutoConfiguration

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
    • 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发 or 重定向))
    • ContentNegotiatingViewResolver:组合所有的视图解析器。
  • Support for serving static resources, including support for WebJars (see below).
    • 静态资源文件夹路径:webjars
  • Automatic registration of Converter, GenericConverter, Formatter beans.
    • Converter:转换器; public String hello(User user):
    • Formatter 格式化器; 2019.5.12 === Date;
    • 自己添加的格式化器转换器,只需要放在容器中即可。
  • Support for HttpMessageConverters (see below).
    • HttpMessageConverter:用来转换Http请求和响应;User—Json;
    • HttpMessageConverters:获取所有的HttpMessageConverter;
  • Automatic registration of MessageCodesResolver (see below).
    • 定义错误代码生成规则。
  • Static index.html support.:静态首页访问
  • Custom Favicon support (see below).:favicon.ico
  • Automatic use of a ConfigurableWebBindingInitializer bean (see below).
    • 可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)。
      1
      2
      初始化WebDataBinder;
      请求数据=====JavaBean;
      If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.)you can add your own @Configuration class of type WebMvcConfigurerAdapter, but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping,RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you can declare a WebMvcRegistrationsAdapter instance providing such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc. 全面控制 Spring MVC


扩展SpringMVC

编写一个配置类(@Configuration),是 WebMvcConfigurerAdapter 类型;不能标注@EnableWebMvc; 这样既保留了所有的自动配置,也能用我们扩展的配置;

1
2
3
4
5
6
7
8
9
10
//使用 WebMvcConfigurerAdapter 可以来扩展SpringMVC的功能
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// super.addViewControllers(registry);
//浏览器发送 /Spring 请求来到 success
registry.addViewController("/Spring").setViewName("success");
}
}

原理:

  • 1、WebMvcAutoConfiguration是SpringMVC的自动配置类
  • 2、在做其他自动配置时会导入;@Import(EnableWebMvcConfiguration.class)
    1
    2
    @Configuration
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

    //从容器中获取所有的 WebMvcConfigurer
    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
    if (!CollectionUtils.isEmpty(configurers)) {
    this.configurers.addWebMvcConfigurers(configurers);
    }
    }
  • 3、容器中所有的WebMvcConfigurer都会一起起作用;
  • 4、我们的配置类也会被调用;

效果:SpringMVC 的自动配置和我们的扩展配置都会起作用;



全面接管SpringMVC @EnableWebMvc

我们需要在配置类中添加 @EnableWebMvc 即可;

1
2
3
4
5
6
7
8
9
10
11
//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
@EnableWebMvc
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// super.addViewControllers(registry);
//浏览器发送 /Spring 请求来到 success
registry.addViewController("/Spring").setViewName("success");
}
}

原理:

  • 1、@EnableWebMvc的核心

    1
    2
    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
  • 2、DelegatingWebMvcConfiguration.class

    1
    2
    @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
  • 3、WebMvcAutoConfiguration

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    @Configuration
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
    //容器中没有这个组件的时候,这个自动配置类才生效
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
    TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {
  • 4、@EnableWebMvc 将 WebMvcConfigurationSupport 组件导入进来;

  • 5、导入的 WebMvcConfigurationSupport 只是SpringMVC最基本的功能;


如何修改 SpringBoot 的默认配置

模式:

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

感谢阅读


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !