1、什么是spring boot
需要思考为什么要做spring boot,spring的核心思想是为了解决什么问题?
-
减少配置
-
简化开发工作量
-
使用嵌入式的servlet容器,应用无需打成war包,即:可以生成直接运行的jar包,下面的代码是需要配置在pom文件中的,这样在maven直接打包的时候就可以将嵌入式的tomcat放在里面了
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> -
starters自动依赖与版本控制,本质上是因为在spring boot中我们引入了parent
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>spring-boot-starter-parent:配置了相关依赖信息
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.2.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>spring-boot-dependencies:就是spring-boot管理依赖的配置文件,所有的依赖包以及版本控制信息都是放在这里面进行管理的
<properties> <activemq.version>5.15.11</activemq.version> <antlr2.version>2.7.7</antlr2.version> <appengine-sdk.version>1.9.77</appengine-sdk.version> <artemis.version>2.10.1</artemis.version> <aspectj.version>1.9.5</aspectj.version> <assertj.version>3.13.2</assertj.version> <atomikos.version>4.0.6</atomikos.version> <awaitility.version>4.0.1</awaitility.version> <bitronix.version>2.1.4</bitronix.version> <build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version> <byte-buddy.version>1.10.4</byte-buddy.version> <caffeine.version>2.8.0</caffeine.version> <cassandra-driver.version>3.7.2</cassandra-driver.version> <classmate.version>1.5.1</classmate.version> <commons-codec.version>1.13</commons-codec.version> <commons-dbcp2.version>2.7.0</commons-dbcp2.version> <commons-lang3.version>3.9</commons-lang3.version> <commons-pool.version>1.6</commons-pool.version> <commons-pool2.version>2.7.0</commons-pool2.version> ……………………………………
2、什么是微服务
-
独立进程的小服务,每个服务可以独立运行
-
每个服务可以独立替换和升级
-
部署和运维带来了非常大的挑战。如何解决?
这个就是spring cloud要解决的问题,以及后面spring boot也会解决的事情
-
性能问题如何考虑和解决?
网络开销带来了性能的降低,需要考虑如何解决网络开销带来性能降低的问题,这个需要在服务设计层面进行考虑,尽量的将服务调用频繁的放在一起,减少这类开销
3、学习spring boot的前置条件
-
spring4、maven、idea
-
环境约束:
- jdk1.8
- maven3.3+
- spring boot 1.5.9
-
maven设置:
- 给maven的setting配置文件,添加profile配置
-
idea设置:
- 将自己安装的maven设置到idea中
4、spring boot第一个程序-HelloWorld
-
创建maven项目
- 选择maven基本信息

- 填写项目信息

- 填写项目信息

-
导入spring boot相关依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> -
编写一个主程序(启动spring boot应用)
@SpringBootApplication public class HelloWorldMainApplication { public static void main(String[] args) { SpringApplication.run(HelloWorldMainApplication.class,args); } } -
编写相关的controller和service等业务类
@Controller //表示这是一个controller类 public class HelloWroldController { @ResponseBody //表示这个方法需要返回一个报文体给调用端 @RequestMapping("/hello") //设置请求路径 public String hello(){ return "Hello World!"; } } -
运行主程序测试
-
部署
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>在pom文件中配置了以上的编译插件,就可以打包生成一个可执行的jar包了。
运行的时候,直接就使用如下命令就可以
java -jar XXXXXXX.jar
5、hello world 项目探究
1、pom文件
- 版本管控
父依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring-boot-starter-parent的父依赖是spring-boot-dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
spring-boot-dependencies:版本管控
<properties>
<activemq.version>5.15.11</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.77</appengine-sdk.version>
<artemis.version>2.10.1</artemis.version>
<aspectj.version>1.9.5</aspectj.version>
<assertj.version>3.13.2</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<awaitility.version>4.0.1</awaitility.version>
<bitronix.version>2.1.4</bitronix.version>
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
<byte-buddy.version>1.10.4</byte-buddy.version>
<caffeine.version>2.8.0</caffeine.version>
<cassandra-driver.version>3.7.2</cassandra-driver.version>
<classmate.version>1.5.1</classmate.version>
<commons-codec.version>1.13</commons-codec.version>
<commons-dbcp2.version>2.7.0</commons-dbcp2.version>
<commons-lang3.version>3.9</commons-lang3.version>
<commons-pool.version>1.6</commons-pool.version>
<commons-pool2.version>2.7.0</commons-pool2.version>
<couchbase-cache-client.version>2.1.0</couchbase-cache-client.version>
<couchbase-client.version>2.7.11</couchbase-client.version>
<db2-jdbc.version>11.5.0.0</db2-jdbc.version>
<dependency-management-plugin.version>1.0.8.RELEASE</dependency-management-plugin.version>
……
</properties>
- 包下载
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
spring-boot-starter-web:管理和下载包
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.2.RELEASE</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
2、主程序
- 主程序
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@SpringBootConfiguration注解,底层是spring的configuration注解,此注解代表该类是一个配置类等效于以前spring中的xml配置文件。
@Configuration
public @interface SpringBootConfiguration {
@Configuration下面是组件注解
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
boolean proxyBeanMethods() default true;
}
@EnableAutoConfiguration注解是自动配置包注解(@AutoConfigurationPackage)和导入注解(@Import(AutoConfigurationImportSelector.class))
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage注解导入了**@Import(AutoConfigurationPackages.Registrar.class)**这个类,其中Registrar方法如下
/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
//将主启动类的所在包的路径获取到并在该包下面,将所有的controller进行注册。所以如果某个controller没有放到主主启动类的子包下面,将不会被扫描到,从而不能被注册
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
@Import(AutoConfigurationImportSelector.class)注解导入了,自动配置导入选择器类
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);//自动配置元数据加载器,其中loadMetadata调用的方法如下
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
loadMetadata方法归属的类AutoConfigurationMetadataloader
/**
* Internal utility used to load {@link AutoConfigurationMetadata}.
*
* @author Phillip Webb
*/
final class AutoConfigurationMetadataLoader {
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
private AutoConfigurationMetadataLoader() {
}
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, PATH);
}
从PATH路径描述,可以看出来,配置文件加载路径是在**"META-INF/spring-autoconfigure-metadata.properties"**文件中进行配置的。

通过自动加载的方式,将所需要的配置文件,通过类的方式自动加载到容器中,所以就省略了ApplicationContext.xml配置文件的配置工作。举例如ElasticsearchAutoConfiguration的配置类
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} for Elasticsearch.
*
* @author Artur Konczak
* @author Mohsin Husen
* @author Andy Wilkinson
* @since 1.1.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Client.class, TransportClientFactoryBean.class })
@ConditionalOnProperty(prefix = "spring.data.elasticsearch", name = "cluster-nodes", matchIfMissing = false)
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticsearchAutoConfiguration {
private final ElasticsearchProperties properties;
public ElasticsearchAutoConfiguration(ElasticsearchProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public TransportClient elasticsearchClient() throws Exception {
TransportClientFactoryBean factory = new TransportClientFactoryBean();
factory.setClusterNodes(this.properties.getClusterNodes());
factory.setProperties(createProperties());
factory.afterPropertiesSet();
return factory.getObject();
}
private Properties createProperties() {
Properties properties = new Properties();
properties.put("cluster.name", this.properties.getClusterName());
properties.putAll(this.properties.getProperties());
return properties;
}
}
elasticsearchClient作为bean注入到了容器中,从而完成配置