中台指南系列一:SpringBoot开发指南
目前部门正在向平台化和中台化方面转变,基于这个背景,我对中台的一些理论进行了一些探索。可以说,未来任何一项技术的研发不能是孤立的,必须自上而下有一个体系化的思考和解决方案。今天做中台和平台不是为了明天变得更少,而是为了明天变得更大更快更颠覆。希望我整理的文档和研发的技术能帮到大家。
更多详情请点击:中台技术体系建设的探索之路
1 前言
SpringBoot微框架目前已经风靡了整个阿里技术社区,主要有AE-SpringBoot和PandoraBoot两个团队在这方面深耕细作,致力于为大家提供一些公共的Starter和问题答疑。我为了迎合团队基础技术建设的趋势,也着手用Starter开了一些基础组件和业务组件,写本文的目的是想把开发中积累的一些经验总结一下,期望能帮助到那些想了解Starter并进行开发的同学。
在本文开始前,我们先要了解下SpringBoot是什么,可以说SpringBoot框架的命名关键在“Boot”上,也就是快速启动一个Spring应用。从最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。SpringBoot的优势如下:
1)Spring Boot使编码变简单,使用Starter POM管理包依赖,天然地集成了一些开发框架等;
2)Spring Boot使配置变简单,采用Java Config减少了繁琐的配置;
3)Spring Boot使部署变简单,跟Docker结合部署内嵌的容器;
4)Spring Boot使监控变简单,Actuator和Health Check提供了完善的监控方案。
2 SpringBoot核心知识
2.1 SpringApplication
SpringApplication将一个典型的Spring应用启动流程“模板化”,并在合适的流程结点开放了一系列不同类型的扩展点,让我们根据需求自由进行扩展。SpringBoot的一站式启动流程如下:
1、如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
1)根据classpath里面是否存在某个特征类ConfigurableWebApplicationContext来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
2)使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
3)使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
4)推断并设置main方法的定义类。
2、SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
3、创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4、遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
5、如果SpringApplication的showBanner属性被设置为true,则打印banner。
6、根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
7、ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8、遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
9、最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10、遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
11、调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12、查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13、正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)。
整个过程看起来冗长无比,但其实很多都是一些事件通知的扩展点,如果我们将这些逻辑暂时忽略,那么,其实整个SpringBoot应用启动的逻辑就可以压缩到极其精简的几步:
2.2 静态资源
在web开发中,静态资源的访问是必不可少的,例如图片、js、css等资源的访问。SpringBoot对静态资源访问提供了很好的支持,基本使用默认配置就能满足开发需求。
一、默认静态资源映射
SpringBoot默认将 “/**” 所有访问映射到以下目录,优先级从高到底:
classpath:/META-INF/resourcesclasspath:/resourcesclasspath:/staticclasspath:/public
二、自定义静态资源映射
在实际开发中,可能需要自定义静态资源访问路径,那么可以继承WebMvcConfigurerAdapter来实现。
1、静态资源配置类
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//将所有/static/** 访问都映射到classpath:/static/ 目录下
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
2、在application.properties配置
spring.mvc.static-path-pattern=/static/**
2.3 日志配置
SpringBoot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。Spring Boot默认使用Logback来记录日志。
1、自定义日志文件配置
由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
1)Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
2)Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
3)Log4j2:log4j2-spring.xml, log4j2.xml
4)JDK (Java Util Logging):logging.properties
SpringBoot官方推荐优先使用带有-spring的文件名作为你的日志配置,SpringBoot可以为它添加一些SpringBoot特有的配置项。
2、日志参数配置
logging:
file: # 日志文件,绝对路径或相对路径
path: # 保存日志文件目录路径
config: # 日志配置文件,Spring Boot默认使用classpath路径下的日志配置文件
level: # 日志级别
org.springframework.web: DEBUG # 配置spring web日志级别
这些属性配置在不同地方的优先级:Diamond > application.properties > logback-spring.xml
3、日志级别控制
配置格式:logging.level. = LEVEL
logging.level:日志级别控制前缀,为包名或Logger名
LEVEL:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
配置举例:
logging.level.com.union.demo=DEBUG:com.union.demo包下所有class以DEBUG级别输出
logging.level.root=WARN:root日志以WARN级别输出
自SpringBoot 1.5版本,我们可以通过端点/loggers查看所有日志的配置,也可以通过/loggers/查看具体包名或者Logger名的日志级别,通过发送Post请求也可以动态修改日志级别。
*4、控制台输出
在Spring Boot中默认配置了ERROR、WARN和INFO级别的日志输出到控制台。我们可以通过两种方式切换至DEBUG级别:
1)在运行命令后加入—debug标志,如:$ java -jar myapp.jar —debug。
2)在application.properties中配置debug=true,该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。
如果你的终端支持ANSI,设置彩色输出会让日志更具可读性。通过在application.properties中设置spring.output.ansi.enabled参数来支持。
1)NEVER:禁用ANSI-colored输出(默认项)。
2)DETECT:会检查终端是否支持ANSI,是的话就采用彩色输出(推荐项)。
3)ALWAYS:总是使用ANSI-colored格式输出,若终端不支持的时候,会有很多干扰信息,不推荐使用。
2.4 Actuator监控
spring-boot-actuator模块提供了一个监控和管理生产环境的模块,可以使用http、jmx、ssh、telnet等拉管理和监控应用。审计(Auditing)、健康(health)、数据采集(metrics gathering)会自动加入到应用里面。
一、原生监控端点分类
1)应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
2)度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计等。
3)操作控制类:提供了对应用的关闭等操作类功能。
一、监控端点暴露功能
| HTTP方法 | 路径 | 描述 | 鉴权 |
|---|---|---|---|
| GET | /autoconfig | 查看自动配置的使用情况 | true |
| GET | /configprops | 查看配置属性,包括默认配置 | true |
| GET | /beans | 查看bean及其关系列表 | true |
| GET | /dump | 打印线程栈 | true |
| GET | /env | 查看所有环境变量 | true |
| GET | /env/{name} | 查看具体变量值 | true |
| GET | /health | 查看应用健康指标 | false |
| GET | /info | 查看应用信息 | false |
| GET | /mappings | 查看所有url映射 | true |
| GET | /metrics | 查看应用基本指标 | true |
| GET | /metrics/{name} | 查看具体指标 | true |
| POST | /shutdown | 关闭应用 | true |
| GET | /trace | 查看基本追踪信息 | true |
| GET/POST | /loggers | 动态修改日志级别 | true |
更多信息请看:监控端点小结
2.5 Profile多环境配置
什么是Profile呢?很多时候,我们项目在开发环境和生成环境的环境配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境的时候,我们是用正式的数据,这时候,我们可以利用profile在不同的环境下用不同的配置文件。
可以用spring.profiles.active来激活一个或者多个profile:
spring.profiles.active=env
1)各个环境公共的配置写在application.properties中。
2)各个模块独有的配置配置在自己的application-{env}.properties文件中。
3)程序先读取spring.profiles.active中设置的profile配置,读不到才会application.properties去取。
还可以用spring.profiles.include来叠加profile:
spring.profiles: env1
spring.profiles.include: env2,env3
3 SpringBoot注解知识
3.1 SpringBootApplication注解
@SpringBootApplication是一个“三体”结构,实际上是一个复合Annotation:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
要想理解@SpringBootApplication这个注解,就必须对它构成的注解进行分析:
一、@Configuration
@SpringBootConfiguration包含@Configuration,而@Configuration是用注解配置Spring,也就是说这是个配置文件,和原来xml配置是等效的,只不过现在用java代码进行配置了并加上一个@Configuration注解就行了。很多SpringBoot的代码示例都喜欢在启动类上直接标注@Configuration或者@SpringBootApplication,对于初学者不便于理解,如果拆分为两个独立的Java类,那么就更清晰了:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {
@Bean
public Controller controller() {
return new Controller();
}
}
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoConfiguration.class, args);
}
}
所以,启动类DemoApplication其实就是一个标准的Standalone类型Java程序的main函数启动类,没有什么特殊的。而@Configuration标注的DemoConfiguration定义其实也是一个普通的JavaConfig形式的IoC容器配置类。
二、@EnableAutoConfiguration
@EnableAutoConfiguration其实也是一个复合Annotation:
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
其中@Import(EnableAutoConfigurationImportSelector.class)最为关键,借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器,就像“八爪鱼”一样:
借助于Spring框架原有的一个工具类SpringFactoriesLoader的支持,@EnableAutoConfiguration的“智能”自动配置功效才能够发挥作用。SpringFactoriesLoader主要功能就是从指定的配置文件META-INF/spring.factories加载配置,spring.factories配置的格式为Key=Value形式,比如:
example.MyService=example.MyServiceImpl1,example.MyServiceImpl2
然后框架就可以根据某个类型作为Key来查找对应的类型名称列表了,并将其中含有@EnableAutoConfiguration对应的配置项通过Java反射实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
三、@ComponentScan
@ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中。加载bean定义到Spring的IoC容器,我们可以手工单个注册,不一定非要通过批量的自动扫描完成,所以说@ComponentScan是可有可无的。
一般将SpringBoot启动类放在需要扫描的包的根路径下,就不需要额外配置@ComponentScan了。
3.2 Value注解
一、注入方式
1)注入普通字符串
2)注入操作系统属性
3)注入表达式结果
4)注入其他Bean属性:注入beanInject对象的属性another
5)注入文件资源
6)注入URL资源
@Value("normal")
private String normal; // 注入普通字符串
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName; // 注入操作系统属性
@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber; //注入表达式结果
@Value("#{beanInject.another}")
private String fromAnotherBean; // 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面
@Value("classpath:com/hry/spring/configinject/config.txt")
private Resource resourceFile; // 注入文件资源
@Value("http://www.baidu.com")
private Resource testUrl; // 注入URL资源
注入其他Bean属性:注入beanInject对象的属性another
@Component
public class BeanInject {
@Value("其他Bean的属性")
private String another;
public String getAnother() {
return another;
}
public void setAnother(String another) {
this.another = another;
}
}
一、使用方法
1、#{…}使用方法
通过@Value(“spelDefault.value”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value(“spelDefault.value”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value(“{spelDefault.value:127.0.0.1}”)
// 如果属性文件没有spelDefault.value,则会报错
// @Value("${spelDefault.value}")
// private String spelDefault2;
// 使用default.value设置值,如果不存在则使用默认值
@Value("${spelDefault.value:127.0.0.1}")
private String spelDefault;
2、${…}使用方法
${…}的{}里面的内容必须符合SpEL表达式,语法详情查看:SpEL表达式语法
// SpEL:调用字符串Hello World的concat方法
@Value("#{'Hello World'.concat('!')}")
private String helloWorld;
// SpEL: 调用字符串的getBytes方法,然后调用length属性
@Value("#{'Hello World'.bytes.length}")
private String helloWorldbytes;
3.3 Conditional注解
Conditional的官方文档定义为:“Indicates that a component is only eligible for registration when all specified conditions match”,意思是只有满足一些列条件之后创建一个bean。
1、注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Conditional {
Class<? extends Condition>[] value();
}
2、注解位置
1)类级别可以放在注标识有@Component(包含@Configuration)的类上。
2)作为一个meta-annotation组成自定义注解。
3)方法级别可以放在标识由@Bean的方法上。
3、常用注解
| 注解名称 | 注解作用 |
|---|---|
| ConditionalOnMissingBean | 判断是否执行初始化代码,即如果用户已经创建了bean,则相关的初始化代码不再执行 |
| ConditionalOnBean | 当且仅当指定的bean classes and/or bean names在当前容器中,才创建标记上该注解的类的实例 |
| ConditionalOnBean | 当且仅当指定的bean classes and/or bean names不存在当前容器中,才创建标记上该注解的类的实例,有指定忽略ignored的参数存在,可以忽略Class、Type等 |
| ConditionalOnClass | 当且仅当ClassPath存在指定的Class时,才创建标记上该注解的类的实例 |
| ConditionalOnMissingClass | 当且仅当ClassPath不存在指定的Class时,创建标记上该注解的类的实例 |
| ConditionalOnProperty | 当且仅当Application.properties存在指定的配置项时,创建标记上了该注解的类的实例 |
| ConditionalOnExpression | 表达式用${..}=false等来表示 |
| ConditionalOnResource | 在classpath下存在指定的resource时创建 |
| ConditionalOnWebApplication | 在web环境下创建 |
3.4 调整Bean顺序
我们可以使用@AutoConfigureBefore或者@AutoConfigureAfter让当前配置或者组件在某个其他组件之前或者之后进行,比如,假设我们希望某些JMX操作相关的bean定义在MBeanServer配置完成之后进行,那么我们就可以提供一个类似如下的配置:
@Configuration
@AutoConfigureAfter(JmxAutoConfiguration.class)
public class AfterMBeanServerReadyConfiguration {
@Autowired
MBeanServer mBeanServer;
......
}
4 SpringBoot属性知识
4.1 属性自动装配原理
一、Properties属性示例
1、定义Properties类
@ConfigurationProperties(prefix = "union.demo")
public class DemoProperties {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、添加配置
spring.demo.name=test
3、注入Properties类
@Configuration
@EnableConfigurationProperties({DemoProperties.class})
public class DemoConfiguration {
}
二、属性自动装配实现
1、在解析@Congiguration的时候,会调用@Import中引入的类;
1)如果@Import中是ImportBeanDefinitionegistar的子类,会直接调用registerBeanDefinitions;
2)如果@Import中是ImportSelector类型,会调用selectImports()返回的bean的registerBeanDefinitions方法;
前者是为了注入配置properties类,后者为属性绑定值。
2、registerBeanDefinitions方法会向BeanFactory中添加新的bean。
注意这里注入了ConfigurationPropertiesBindingPostProcessor,这才是属性赋值的关键:
注意到ConfigurationPropertiesBindingPostProcessor继承自BeanPostProcessor,他会在bean初始化前后调用before和after后置处理。
更详细的原理解释请看这里
4.2 属性配置优先级
SpringBoot的核心为“约定优先于配置”,优先级从高到底:
1)命令行参数
2)Diamond的Properties配置
3)Java系统属性(System Properties)
4)操作系统环境变量
5)jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
6)jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7)jar包外部的application.properties或application.yml(不带spring.profile)配置文件
8)jar包内部的application.properties或application.yml(不带spring.profile)配置文件
9)@Configuration注解类上的@PropertySource
10)通过SpringApplication.setDefaultProperties指定的默认属性
4.3 属性配置格式
1、参数引用
com.sam.name=sam
com.sam.age=11
com.sam.desc=${name} is ${age} years old.
通过如${com.sam.name:默认名称}还可以设置默认值
2、获取随机数
#获取随机int:${random.int}
#获取10以内的随机数:${random.int(10)}
#获取10-20的随机数:${random.int[10,20]}
#获取随机long:${random.long}
#获取随机uuid:${random.uuid}
#获取随机字符串:${random.value}
com.sam.randomValue=${random.value}
3、支持yml语法
server:
port: 9999
port: 9999 中间是有空格的,yml语法请参考:yml配置文件用法
4.4 属性读取方式
举个例子,我们在application.properties里添加一些属性信息:
union.demo.name=张三
union.demo.address[0]=北京
union.demo.address[1]=上海
union.demo.phone.number=1111111
对于属性的读取方式,我总结了有以下五种:
1、使用@Value
@Value("${union.demo.name}")
private String name;
2、使用@ConfigurationProperties
1)首先定义Properties类
@Component
@ConfigurationProperties(prefix = "union.demo")
public class PeopleProperties {
private String name;
private List<String> address;
private Phone phone;
......
}
2)然后注入Properties类
@Configuration
@EnableConfigurationProperties({PeopleProperties.class})
public class PeopleConfiguration {
@Autowired(required = false)
private PeopleProperties properties;
}
3、使用Environment
1)注入环境变量
@Autowired
private Environment env;
2)使用环境变量进行访问:
env.getProperty("union.demo.name")
4、使用RelaxedDataBinder
PeopleProperties properties = new PeopleProperties();
MutablePropertySources propertySources = environment.getPropertySources();
new RelaxedDataBinder(properties, "union.demo").bind(
new PropertySourcesPropertyValues(propertySources));
5、使用PropertiesLoaderUtils
通过注册监听器(Listeners) + PropertiesLoaderUtils的方式加载属性文件,比较复杂,这里不再赘述。
4.5 常用属性介绍
1、debugging
debug:会打印除应用之外其他的jar的日志。
spring.diamond.print-properties:设置为true时应用启动时,会打印出最终的Spring环境所有的key/value,还有从哪里加载的,方便调试。
2、mvc
spring.mvc.async.request-timeout:设定async请求的超时时间,以毫秒为单位,如果没有设置的话,以具体实现的超时时间为准,比如tomcat的servlet3的话是10秒。
spring.mvc.date-format:设定日期的格式,比如dd/MM/yyyy。
spring.mvc.favicon.enabled:是否支持favicon.ico,默认为: true。
spring.mvc.locale:指定使用的Locale。
spring.mvc.view.prefix:指定mvc视图的前缀。
spring.mvc.view.suffix:指定mvc视图的后缀。
3、resources
spring.resources.add-mappings:是否开启默认的资源处理,默认为true。
spring.resources.cache-period:设定资源的缓存时效,以秒为单位。
spring.resources.chain.cache:是否开启缓存,默认为:true。
spring.resources.chain.enabled:是否开启资源 handling chain,默认为false。
spring.resources.static-locations:指定静态资源路径。
4、multipart
multipart.enabled:是否开启文件上传支持,默认为true。
multipart.file-size-threshold:设定文件写入磁盘的阈值,单位为MB或KB,默认为0。
multipart.location:指定文件上传路径。
multipart.max-file-size:指定文件大小最大值,默认1MB。
multipart.max-request-size:指定每次请求的最大值,默认为10MB。
5、http
spring.http.converters.preferred-json-mapper:是否优先使用JSON mapper来转换.
spring.http.encoding.charset:指定http请求和相应的Charset,默认为UTF-8。
spring.http.encoding.enabled:是否开启http的编码支持,默认为true。
spring.http.encoding.force:是否强制对http请求和响应进行编码,默认为true。
6、json
spring.jackson.date-format:指定日期格式,比如yyyy-MM-dd HH:mm:ss。
spring.jackson.deserialization:是否开启Jackson的反序列化。
spring.jackson.generator:是否开启json的generators。
spring.jackson.joda-date-time-format:指定Joda date/time的格式,如果没有配置的话,dateformat会作为backup。
spring.jackson.locale:指定json使用的Locale。
spring.jackson.mapper:是否开启Jackson通用的特性。
spring.jackson.parser是否开启jackson的parser特性。
spring.jackson.serialization:是否开启jackson的序列化。
spring.jackson.time-zone:指定日期格式化时区,比如America/Los_Angeles或者GMT+10。
7、server
server.port:设定http监听端口。
server.address:指定server绑定的地址。
server.compression.enabled:是否开启压缩,默认为false。
server.compression.mime-types:指定要压缩的MIME type,多个以逗号分隔。
server.context-path:设定应用的context-path。
server.servlet-path:设定dispatcher servlet的监听路径,默认为“/”。
8、session
server.session.cookie.domain:指定session cookie的domain。
server.session.cookie.http-only:是否开启HttpOnly。
server.session.cookie.max-age:设定session cookie的最大age。
server.session.cookie.name:设定Session cookie 的名称。
server.session.cookie.path:设定session cookie的路径。
server.session.timeout:session的超时时间。
9、datasource
spring.datasource.initial-size:指定启动连接池时,初始建立的连接数量。
spring.datasource.connection-timeout:指定连接的超时时间,毫秒单位。
spring.datasource.max-active:指定连接池中最大的活跃连接数。
spring.datasource.max-age:指定连接池中连接的最大年龄。
spring.datasource.max-idle:指定连接池最大的空闲连接数量。
spring.datasource.max-lifetime:指定连接池中连接的最大生存时间,毫秒单位。
spring.datasource.max-wait:指定连接池等待连接返回的最大等待时间,毫秒单位。
spring.datasource.maximum-pool-size:指定连接池最大的连接数,包括使用中的和空闲的连接。
10、security
security.basic.authorize-mode:要使用权限控制模式。
security.basic.enabled:是否开启基本的鉴权,默认为true。
security.require-ssl:是否对所有请求开启SSL,默认为false。
security.sessions:指定Session的创建策略(always, never, if_required, stateless)。
security.user.name:指定默认的用户名,默认为user。
security.user.password:默认的用户密码。
security.user.role:默认用户的授权角色。
11、aop
spring.aop.auto:是否支持@EnableAspectJAutoProxy,默认为true。
spring.aop.proxy-target-class:true为使用CGLIB代理,false为JDK代理,默认为false。
更多SpringBoot属性请点我
5 Starter核心知识
5.1 Starter基本介绍
一、Starter的基本概念
可以认为Starter是一种服务,使得使用某个功能的开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot自动通过classpath路径下的类发现需要的Bean,并织入bean。正规的starter是一个独立的工程,然后在maven中新仓库注册发布,其他开发人员就可以使用你的starter了。
二、starter的基本原理
虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。因为Spring Boot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter的ConfigurationProperties还使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。
三、Starter包含内容
1、自动配置文件,根据classpath是否存在指定的类来决定是否要执行该功能的自动配置。
2、spring.factories,指导SpringBoot找到指定的自动配置文件。
3、endpoint:可以理解为一个admin,包含对服务的描述、界面、交互(业务信息的查询)
4、health indicator:该starter提供的服务的健康指标
四、Starter执行过程
在应用程序启动过程中,SpringBoot使用SpringFactoriesLoader查找EnableAutoConfiguration关键字对应的Java配置文件。Spring Boot会遍历在各个jar包种META-INF目录下的spring.factories文件,构建成一个配置文件链表。除了EnableAutoConfiguration关键字对应的配置文件,还有其他类型的配置文件:
org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationListener
org.springframework.boot.SpringApplicationRunListener
org.springframework.boot.env.PropertySourceLoader
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider
org.springframework.test.contex.TestExecutionListener
5.2 Starter代码规范
1、Starter命名规范
命名规则:{Starter名称}-spring-boot-starter
规则描述:Starter名称如果由小写英文单词组成,名称前可以增加库名称。
规则举例:
tddl-spring-boot-starter
pandora-diamond-spring-boot-starter
union-core-spring-boot-starter
2、属性命名规范
命名规则:spring.{组件名称}.{属性名称}
规则描述:组件名称和属性名称都是由小写英文单词组成,多个英文单词用“-”分隔。
规则举例:
spring.doom.enabled
spring.diamond.data-id
spring.diamond.group-id
5.3 自定义Bom清单
SpringBoot通过maven的依赖管理为我们写好了很多依赖项及其版本,我们可直接拿来使用。主要有以下两种使用方法:
1、继承
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<type>pom</type>
</dependency>
2、导入
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
此外,继承时可简单地通过属性定制依赖项版本。比如改为使用较新的spring版本:
<properties>
<spring.version>4.1.6.RELEASE<spring.version>
</properties>
不过,此法只对继承有效,导入无效。那么导入时有没有较简单的方法呢?我们可先继承后导入。
1、先建一个过渡性工程,继承后定制依赖项的版本。
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<groupId>com.alibaba.union</groupId>
<artifactId>union-boot-starter-bom</artifactId>
<version>1.0.0-RELEASE</version>
<packaging>pom</packaging>
<properties>
<spring.version>1.5.3.RELEASE</spring.version>
</properties>
</project>
2、然后导入到自己的工程里。
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.union</groupId>
<artifactId>union-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.union</groupId>
<artifactId>union-boot-starter-bom</artifactId>
<version>1.0.0-RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
这样,虽然多建了一个过渡性工程,但定制依赖项版本同继承时一样简单。
5.4 自定义Starter
下面以本人封装的Tddl组件为例:
1、创建union-tddl-spring-boot-starter工程
2、引入spring-boot和pandora-boot的配置
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.taobao.pandora</groupId>
<artifactId>pandora-boot-starter-bom</artifactId>
<version>${pandora-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3、定义一个pojo用来接收properties中配置的信息
@ConfigurationProperties(prefix = "spring.tddl")
public class TddlProperties {
private String mapperPath;
private String typeAliasesPackage;
private String basePackage;
......
}
4、创建AutoConfiguration注册Bean
@Configuration
@EnableConfigurationProperties(TddlProperties.class)
public class TddlAutoConfiguration implements EnvironmentAware {
@Autowired
private TddlProperties properties;
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage(properties.getTypeAliasesPackage());
return factoryBean.getObject();
}
}
5、在新建的spring.factories文件中配置自动启动类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.union.tddl.TddlAutoConfiguration
6、在新建的spring.provides文件中配置Starter的名字
provides: union-tddl-spring-boot-starter
7、发布你的starter
更多详情请参考以下代码:
Starter源码
Starter示例
6 参考资料
SpringBoot官网
AE-SpringBoot Wiki
PandoraBoot Wiki
UnionBoot Wiki
