Fork me on GitHub

Spring Boot

前言

简单!快速!方便!

Spring Boot 是由Pivotal团队提供的全新框架,目的是简化Spring应用的初始搭建及开发过程。它默认配置了很多框架的使用方式(习惯优于配置)。

  • Spring Boot使编码变简单
  • Spring Boot使配置变简单
  • Spring Boot使部署变简单
  • Spring Boot使监控变简单

    springboot项目启动

    非springboot项目

    一个非springboot项目需要N(很多)个文件才能启动
  1. applicationContext.xml
  2. services.xml
  3. web.xml
  4. pom.xml
  5. mybatis.xml
  6. mysql-db.xml
  7. mongo-db.xml
  8. **Servlet.java
  9. 需要安装Tomcat或者Jetty容器、
  10. …….

搭建一个非springboot项目起码需要半天以上,而且新增别的模块的时候,比如说redis,还需要增加繁琐的redis.xml的配置文件

springboot项目

一个springboot项目只需要2个文件就能启动

  1. pom.xml :maven的pom文件,用于引入依赖
  2. SampleController :启动类

pom.xml:

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.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

hello/SampleController.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package hello;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;
@Controller
@EnableAutoConfiguration
public class SampleController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleController.class, args);
}
}

搭建一个springboot项目只需要2分钟,除了pom.xml不需要任何xml配置,新增别的模块比如说redis的时候只需要引入相关依赖,并在application.properties中增加相关的port等配置即可

springboot自动配置

为什么用了springboot很多配置都不需要了?
Spring Boot关于自动配置的源码在spring-boot-autoconfigure中


tomcat的自动配置

@ConfigurationProperties:加载properties配置,prefix指定前缀

1
2
3
4
5
6
7
8
9
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties
implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
/**
* Server HTTP port.
*/
private Integer port;
......

还是这个类;根据container对象的类型来判断究竟是使用哪个容器

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
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (getPort() != null) {
container.setPort(getPort());
}
if (getAddress() != null) {
container.setAddress(getAddress());
}
if (getContextPath() != null) {
container.setContextPath(getContextPath());
}
if (getDisplayName() != null) {
container.setDisplayName(getDisplayName());
}
if (getSession().getTimeout() != null) {
container.setSessionTimeout(getSession().getTimeout());
}
container.setPersistSession(getSession().isPersistent());
container.setSessionStoreDir(getSession().getStoreDir());
if (getSsl() != null) {
container.setSsl(getSsl());
}
if (getJspServlet() != null) {
container.setJspServlet(getJspServlet());
}
if (getCompression() != null) {
container.setCompression(getCompression());
}
container.setServerHeader(getServerHeader());
if (container instanceof TomcatEmbeddedServletContainerFactory) {
getTomcat().customizeTomcat(this,
(TomcatEmbeddedServletContainerFactory) container);
}
if (container instanceof JettyEmbeddedServletContainerFactory) {
getJetty().customizeJetty(this,
(JettyEmbeddedServletContainerFactory) container);
}
if (container instanceof UndertowEmbeddedServletContainerFactory) {
getUndertow().customizeUndertow(this,
(UndertowEmbeddedServletContainerFactory) container);
}
container.addInitializers(new SessionConfiguringInitializer(this.session));
container.addInitializers(new InitParameterConfiguringServletContextInitializer(
getContextParameters()));
}

container对象是怎么来的呢?也可以说springboot是怎么知道我们想用的是jetty还是tomcat或者是别的容器呢?

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
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(BeanPostProcessorsRegistrar.class)
public class EmbeddedServletContainerAutoConfiguration {
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
......

  • @ConditionalOnClass:条件注解
    对应的类在classpath目录下存在时,才会去解析对应的配置文件
  • Spring Boot自动配置的原理:Spring 4.x 提供了基于条件来配置Bean的能力
1
2
3
4
5
6
7
8
9
10
11
@Configuration
@EnableConfigurationProperties
@ConditionalOnWebApplication
public class ServerPropertiesAutoConfiguration {
@Bean
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
public ServerProperties serverProperties() {
return new ServerProperties();
}
......
  • @Configuration
    用@Configuration注解该类,等价 与XML中配置beans
  • @Bean:用@Bean标注方法等价于XML中配置bean

springboot自动配置流程

  1. 判断是否有相应的类
  2. 如果有相应的类,就在java配置类中配置相应的Properties Bean对象
    这些相应的类都是我们通过pom.xml依赖进来的;

mysql的自动配置


参数配置类:DataSourceProperties

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
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
private ClassLoader classLoader;
private Environment environment;
/**
* Name of the datasource.
*/
private String name = "testdb";
/**
* Generate a random datasource name.
*/
private boolean generateUniqueName;
/**
* Fully qualified name of the connection pool implementation to use. By default, it
* is auto-detected from the classpath.
*/
private Class<? extends DataSource> type;
/**
* Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
*/
private String driverClassName;
/**
* JDBC url of the database.
*/
private String url;
......

mybatis的一些配置;一般的配置都可以在相应的properties文件中找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author Clinton Begin
*/
public class Configuration {
protected Environment environment;
protected boolean safeRowBoundsEnabled = false;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase = false;
protected boolean aggressiveLazyLoading = true;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys = false;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true;
protected boolean callSettersOnNulls = false;
......

小结

  1. 繁琐的**.xml配置,springboot已经通过java配置的方式帮我们都做好了。
  2. springboot通过基于条件来配置Bean的方式实现了自动配置
  3. pom.xml依赖了哪个模块的jar包,就能实现哪个模块的自动配置
  4. 如果要修改某个模块的配置,可以通过对应的*Properties类来查看修改,或者直接通过官网的文档。

打包运行

直接打成jar包,通过java -jar xx.jar来运行
需要pom.xml增加配置

完美…

「真诚赞赏,手留余香」