SpringBoot Quickstart

SpringBoot Intro

SpringBoot是顺应如今微服务(MicroServices)理念而产生的一个微框架(同类微框架可供选择的还有Dropwizard), 用来构建基于Spring框架的标准化的独立部署应用程序(“再也tmd不用寄人篱下,活在WebContainer的屋檐下了”)。html

咱们原来选择试用Dropwizard做为Web API的标准框架, 也完成了一些项目,整体上来讲, Dropwizard是能够知足这些场景的,且它对metrics的支持尤为优秀。从技术因素 1上来讲, Dropwizard是OK的, 但结合公司内部和外部层面其它更多因素考虑,则选型Dropwizard可能不是最合适的作法。java

咱们仍是一个比较年轻的团队, 你们有很好的上进意愿,并且咱们有优秀的技术leader来带领他们前行,但罗马不是一天建成的,因此, 如今你们仍是对如今java生态圈中流行的技术更为熟悉,好比Spring, MyBatis等口口相传的开源框架,如何让你们在现有经验积累的前提下高效完成工做是咱们目前的主要目标, 预留20%的空间给团队和我的成长应该是第二目标,并且, Spring社区已经足够成熟, 能够持续完善和支撑现有技术方案与社区成长,故此,咱们决定使用SpringBoot来做为咱们的微框架,以标准化支持咱们的微服务战略。git

2 SpringBoot Quickstart

咱们使用Maven构建项目,因此新建一个maven项目, pom.xml中添加以下两个关键因素:github

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version></parent>...<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency></dependencies>

使用spring-boot-starter-parent做为当前项目的parent能够享受到spring boot应用相关的一系列依赖(dependency), 插件(plugins)等装备, 而添加spring-boot-starter-web这个依赖,则纯粹是咱们但愿构建一个独立运行的web应用而已(注意, 没有version元素定义,由于spring-boot-starter-parent已经提供了相应的dependencyManagement)。web

有了以上配置,咱们就能够按照SpringMVC的套路添加相应的Controller实现就能够了, 好比:redis

// let's say, it is under package com.xxx.controller@Controllerpublic class HelloController {    @RequestMapping("/")    @ResponseBody    String home() {        return "Hello SpringBoot!";    } }// let's say, it is under package com.xxx.controller@Controllerpublic class HelloController {    @RequestMapping("/")    @ResponseBody    String home() {        return "Hello SpringBoot!";    } }

最后,要让SpringBoot能够独立运行和部署,咱们须要一个Main方法入口, 好比:spring

// let's say, it's located under package com.xxx@SpringBootApplicationpublic class HelloSpringBoot {    public static void main(String[] args) throws Exception {        SpringApplication.run(HelloSpringBoot.class, args);    } }// let's say, it's located under package com.xxx@SpringBootApplicationpublic class HelloSpringBoot {    public static void main(String[] args) throws Exception {        SpringApplication.run(HelloSpringBoot.class, args);    } }

That's it, 剩下的就是运行HelloSpringBoot, 而后打开浏览器,访问路径http://localhost:8080看看发生了什么吧!2mongodb

是否是很简单? 是啊, 不过也太过于简单了(Everything Should Be Made as Simple as Possible, But Not Simpler), 若是仅止步于次, 那咱们这些自称为技术精英的人们还有什么颜面活在这个世上那? 咱们要深挖洞,广积粮...shell

3 How Spring Boot Works?

要让一个开源软件产品在公司内部落地并成长乃至成熟, 须要咱们投入精力来熟悉它, 打磨和完善它,而后才是使用它来简洁高效的交付相应的软件产品乃至高效运维之。数据库

为了能让SpringBoot落地生根发芽,让咱们先来了解它是如何工做吧!

3.1 Spring Features Revisited

做为使用Spring框架的老一辈技术革命家之一, 哥已经脱离应用开发一线多年, 虽然Spring框架从根儿上没有什么变化,但从哥那时起也已经发展了2,3个大的版本了, 因此,在深刻SpringBoot以前,有必要先了解一下新版本Spring中那些相关的特性来铺垫铺垫...

若是各位看官从开始就一直在使用较新或者最新的Spring框架的话,能够忽略这部份内容,直接从"Understanding @EnableAutoConfiguration"章节继续好了, 不过话说回来, 看看也是好的嘛 ^_-

3.1.1 XML Configuration VS. JavaConfig

哥是从Spring使用xml作依赖注入和绑定的那个时代走出来的,对xml形式的配置会比较清楚也比较“情有独钟”一些,但并不是说排斥其它形式,只是会根据状况来权衡。好比SpringBoot倡导基于JavaConfig的形式来“装配”应用, 但有些层面,咱们仍是但愿根据公司的生态圈和基础设施现状,对其进行一些定制,以便更好的融入并享受一系列生态, 这就会加一些已有系统的集成啦, 对SpringBoot原来的Convention进行Configuration明确化调整啦等等, 而大部分要集成外部已有系统的时候, 经过xml集中明确化配置我认为是比较合适的作法。

总之, 这两种方式不该该是东风压倒西风,而应该根据状况来选择。 从个人角度来说,我但愿在SpringBoot里,除了Main入口类和autoscan相关的地方使用JavaConfig, 其它最好以xml配置,而后像一个bag似的,能够处处背着处处搬, 反正也不知道这个比喻各位看官可否看明白 ;)

3.1.2 @Configuration

@Configuration这个Annotation就是JavaConfig的典型表明啦,标注了这个Annotation的Java类定义会以Java代码的形式(对应于xml定义的形式)提供一系列的bean定义和实例, 结合AnnotationConfigApplicationContext和自动扫描的功能,就能够构建一个基于Spring容器的Java应用了。

一系列标注了@Configuration的Java类的集合,对应于“昨日”的一系列xml配置文件。

3.1.3 @ComponentScan

@ComponentScan对应xml时代的<context:component-scan>, 用来扫描classpath下标注了相应Annotation的bean定义,而后加载到Spring容器之中。

通常配合@Configuration来使用, 你能够将@Configuraiton作的事情是纯手工定义bean而后添加到Spring容器, 而@ComponentScan则是自动收集bean定义并添加到Spring容器。

3.1.4 @Import

Spring容器的配置能够分散在多个物理存在的配置类或者配置文件中, @Import容许将其它JavaConfig形式的配置类引入到当前的@Configuration标注的配置类当中, 对应于原来xml时代的<import/>, 甚至于也能够经过@ImportResource将xml形式定义的配置也引入当前JavaConfig形式的配置类当中。

3.1.5 @PropertySource

配合@Configuration使用, 用来加载.properties内容到Environment,好比:@PropertySource("classpath:/application.properties"),固然,要生效, 同时须要容器中配置一个PropertySourcesPlaceholderConfigurer。

@PropertySource和@PropertySources的区别在于, 后者属于前者的Aggregation类型, 在有多个.properties资源须要引入的状况下,若是可以使用Java8的repeatable annotation特性,则只须要声明多个@PropertySource就好了, 不然,做为fallback方案,使用@PropertySources而后再其中引用多个@PropertySource好了

3.1.6 Environment和Profile

这两个概念应该是Spring3时代引入的, Environment用来统一表达当前应用程序运行环境的概念,会以Properties的形式提供一系列该环境下的上下文信息,并且容许当前应用程序获取activeProfile是哪一个。

说实话, Environment的设计,我以为到提供上下文信息这一关键职能就能够了, 而Profile的设计,则有些太过于Monolithic时代的作事风格。 Profile通常用来提供某些灵活性, 但这种灵活性是内部化的, 这意味着, 你的软件实体须要知道外面可能提供多少种profiles, 而后在不一样的profile下,个人软件实体须要作什么样的调整。 而实际上, 软件实体从研发到交付和使用, 最好是在整条流水线上设计和生产都是一致, 只有“销售”以前,才根据目标环境或者目标客户调整“包装”和配置, 而后“发货”, 用户拿到手的产品(固然包括咱们搞的软件产品)应该是开箱即用的, 这个产品既不会存在我不须要的功能,也不该该每次使用的时候先本身“很智能”的扫描一下上下文环境而后决定使用哪个Profile。尤为是在微服务时代,随着你服务数量的增加, 服务数量 * Environment数量 * 所谓的Profile数量更是指数级增加 3, 若是应用开发的时候还要考虑这么多,那出问题的概率就更大了。

因此, 在Microservices时代,咱们更建议外部化你的软件产品差别化配置管理, 尽可能减小Profile的滥用甚至不用(这就减小一个纬度的管理)。

3.2 Understanding @EnableAutoConfiguration

在本文以前提到的全部Annotation都属于SpringFramework提供的, 如今要说的这个Annotation,即@EnableAutoConfiguration, 则属于SpringBoot。

@EnableAutoConfiguration的定义信息以下

@Target(value=TYPE)@Retention(value=RUNTIME)@Documented@Inherited@Import(value={org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.class,org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar.class})public @interface EnableAutoConfiguration@Target(value=TYPE)@Retention(value=RUNTIME)@Documented@Inherited@Import(value={org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.class,org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar.class})public @interface EnableAutoConfiguration

标注了这个Annotation的配置类将触发一系列动做, 也是SpringBoot“黑魔法”的核心, 魔法大致上是这样发生的: SpringBoot一旦发现@EnableAutoConfiguration, 那么就使用Spring框架提供的SpringFactoriesLoader这个特性去扫描当前应用classpath下全部META-INF/spring.factories元信息配置, 而后根据当前使用场景须要, 加载符合当前场景须要的配置类型并供当前或者后继流程使用, 对于@EnableAutoConfiguration的场景,就是提取以org.springframework.boot.autoconfigure.EnableAutoConfiguration做为key标志的一系列Java配置类,而后将这些Java配置类中的bean定义加载或者说灌入Spring容器中。

固然, EnableAutoConfiguration经过SpringFactoriesLoader筛选并加载进来的这些Java配置类里面,咱们其实还能够进一步对要加载到容器的bean定义进行筛选, 这就会用Spring3系列引入的@Conditional“军团”, 经过像@ConditionalOnClass, @ConditionalOnMissingBean等具体的类型和条件来进一步决定加载仍是不加载哪些bean定义

3.3 Enter Main

有了上面的这些“前戏”, 下面咱们正式进入正题了...

每个SpringBoot应用都有一个入口类,在其中定义main方法, 而后使用SpringApplication这个类来加载指定配置并运行SpringBoot应用程序, 在不少SpringBoot的介绍中,都会使用当前入口类既做为配置(标注@Configuration)又做为入口类, 好比咱们的HellSpringBoot:

@SpringBootApplicationpublic class HelloSpringBoot {    public static void main(String[] args) throws Exception {        SpringApplication.run(HelloSpringBoot.class, args);    } }@SpringBootApplicationpublic class HelloSpringBoot {    public static void main(String[] args) throws Exception {        SpringApplication.run(HelloSpringBoot.class, args);    } }

@SpringBootApplication等效于@Configuraiton + @EnableAutoConfiguration + @ComponentScan, 因此, 当咱们将HelloSpringBoot.class做为JavaConfig配置类传入SpringApplication.run方法以后, SpringApplication.run方法就知道从哪里加载并扫描必要的bean定义了。

如今,剩下的就是要搞清楚SpringApplication.run里面发生了什么:


how-spring-boot-autoconfigure-works

其实SpringApplication做为一个bootstrap类, 既能够加载JavaConfig形式的配置, 也能够加载XML形式的配置, 而后根据状况下建立相应类型的ApplicationContext实例, 为了简化理解难度,咱们以JavaConfig为主线, 那么通常状况下, SpringBoot就会建立一个对应处理JavaConfig形式配置的AnnotationConfigApplicationContext实例(或者若是有Servlet等类,则建立ConfigurableWebApplicationContext)。

而后一个CommandLinePropertySource会被建立且其内容会加载到当前SpringBoot应用的Environment之中(这也就是为何命令行上提供的参数能够优先覆盖其它配置的缘由),固然, 其它的PropertySource这个时候也会随后一块儿加载而后并到Environment, 而后交给ApplicationContext实例后继使用(不要纠结与代码细节,虽然代码细节里是先作了包括设置env的一些事情而后再建立ApplicationContext实例)。

在ApplicationContext建立的以前和以后, SpringBoot会使用SpringFactoriesLoader这个特性,从当前classpath下全部的META-INF/spring.factories下加载以下类型的一些callback接口并在前中后等不一样时机执行:

  1. org.springframework.boot.SpringApplicationRunListener

  2. org.springframework.context.ApplicationContextInitializer

  3. org.springframework.context.ApplicationListener

这些琐事我这里就不细说了, 老是上面提到的事儿作完后,ApplicationContext就正式加载SpringApplication.run方法传入进来的配置了(JavaConfig形式或者XML形式), 而后,由于咱们标注了@SpringBootApplication, 容器会自动完成指定语意的一系列职能,包括@EnableAutoConfiguration要求的事情, 好比, 从SpringBoot提供的多个starter模块中加载JavaConfig配置, 而后将这些JavaConfig配置筛选上来的bena定义加入Spring容器中(即ApplicationContext中), refresh容器,而后就完事大吉了,一个SpringBoot应用启动完成。

不过,其实最后还有一个关键组件,通常用于扩展, 在容器准备好以后,SpringBoot其实还会根据类型去容器中挑选一批CommandLineRunner, 而后依次执行这些CommandLineRunner, 咱们能够根据需求和场景,实现一些本身的CommandLineRunner并添加到容器来对SpringBoot应用进行某种扩展。

以上属于SpringBoot的整部大戏, 但愿各位看官受用, ^_-

4 Lean SpringBoot

若是你对SpringBoot不甚了解, 或许就会对其Quick & Dirty的作事方式有所顾虑, 是否是AutoConfiguration黑魔法加载了过多不必的配置啊? 是否是这套框架太简单没法知足须要啊? 不过, 一旦你了解了SpringBoot, 这些顾虑就会烟消云散了, SpringBoot既提供了丰富的“给养”, 又同时具备足够的灵活度,让咱们根据状况对其进行瘦身(make it lean), 咱们先来看丰富的“给养”...

4.1 Get To Know SpringBoot Modules First

SpringBoot提供了不少预先配置好的职能模块,咱们能够先来看看这些模块都能为咱们作什么,而后再来决定SpringBoot提供的现有功能是否知足咱们的需求, 这些模块大致上以下所列:

       <module>spring-boot-starter</module>
        <module>spring-boot-starter-amqp</module>
        <module>spring-boot-starter-aop</module>
        <module>spring-boot-starter-batch</module>
        <module>spring-boot-starter-cloud-connectors</module>
        <module>spring-boot-starter-data-elasticsearch</module>
        <module>spring-boot-starter-data-gemfire</module>
        <module>spring-boot-starter-data-jpa</module>
        <module>spring-boot-starter-data-mongodb</module>
        <module>spring-boot-starter-data-rest</module>
        <module>spring-boot-starter-data-solr</module>
        <module>spring-boot-starter-freemarker</module>
        <module>spring-boot-starter-groovy-templates</module>
        <module>spring-boot-starter-hateoas</module>
        <module>spring-boot-starter-hornetq</module>
        <module>spring-boot-starter-integration</module>
        <module>spring-boot-starter-jdbc</module>
        <module>spring-boot-starter-jersey</module>
        <module>spring-boot-starter-jetty</module>
        <module>spring-boot-starter-jta-atomikos</module>
        <module>spring-boot-starter-jta-bitronix</module>
        <module>spring-boot-starter-logging</module>
        <module>spring-boot-starter-log4j</module>
        <module>spring-boot-starter-log4j2</module>
        <module>spring-boot-starter-mail</module>
        <module>spring-boot-starter-mobile</module>
        <module>spring-boot-starter-mustache</module>
        <module>spring-boot-starter-actuator</module>
        <module>spring-boot-starter-parent</module>
        <module>spring-boot-starter-redis</module>
        <module>spring-boot-starter-security</module>
        <module>spring-boot-starter-social-facebook</module>
        <module>spring-boot-starter-social-twitter</module>
        <module>spring-boot-starter-social-linkedin</module>
        <module>spring-boot-starter-remote-shell</module>
        <module>spring-boot-starter-test</module>
        <module>spring-boot-starter-thymeleaf</module>
        <module>spring-boot-starter-tomcat</module>
        <module>spring-boot-starter-undertow</module>
        <module>spring-boot-starter-velocity</module>
        <module>spring-boot-starter-web</module>
        <module>spring-boot-starter-websocket</module>
        <module>spring-boot-starter-ws</module>

我不会对全部的starter都进行介绍,只简单挑几个主要的进行简单介绍...

4.1.1 spring-boot-starter-actuator

这个module提供的东西比较多,都属于外围支撑性功能, 好比:

  1. 提供一系列的Endpoints来窥探SpringBoot应用内部的一系列状态并进行监控管理;

  2. 提供HealthIndicator来容许对SpringBoot应用进行健康检查;

  3. 提供metrics支持;

  4. 提供远程shell支持;

  5. 提供mbean支持, 等等...

4.1.2 spring-boot-starter-web

告诉SpringBoot, 哥当前要开发的是一个Web应用,把相应的依赖配置都给我准备好。

默认SpringBoot会给Web应用配备Tomcat做为嵌入式web容器, 若是你不想用默认的tomcat,而想用jetty,那么能够再声明一个对spring-boot-starter-jetty的dependency,以后SpringBoot中使用的EnableAutoConfiguration会施展黑魔法,帮你搞定替换知足你的愿望。

4.1.3 spring-boot-starter-logging

告诉SpringBoot, "给哥使用slf4j和logback!"

4.1.4 其它starter modules

通常看名字就能够猜个八九不离十了,因此, 留待各位看官本身去挖掘吧~

4.2 Specific Microservice Type Customization

SpringBoot提供的功能却是蛮丰富的了,可是,你会发现,爽了的同时,整个应用也会看起笨重了些, 好比有人就抱怨说SpringBoot应用启动慢(虽然这不是什么大问题,你生产环境又不会闲着没事常常重启,服务就应该长久,哈哈), 好在SpringBoot的设计提供了足够的灵活度,让咱们能够对其进行裁剪和瘦身。

4.2.1 DubboMicroServiceAutoConfiguration

不少公司在使用dubbo做为java服务的开发框架,咱们也不例外, 因此, 构建基于SpringBoot和Dubbo的微服务属于比较广泛的需求, 要完成这个事情其实很简单,只要提供一个特定于dubbo的自动加载模块就能够了, 好比咱们称其为DubboMicroServiceAutoConfiguration(只是举例,非实际生产代码):

@Configuration@Order(Ordered.HIGHEST_PRECEDENCE)public class DubboMicroServiceAutoConfiguration {    // 1. Application Bean Definition    @Bean    @ConditionalOnMissingBean    @Value(${dubo.application.name})    public static DubboApplication dubboApp() {        return new xxx;    }        // 2. Registry Bean Definition        // 3. Protocol Bean Definition}@Configuration@Order(Ordered.HIGHEST_PRECEDENCE)public class DubboMicroServiceAutoConfiguration {    // 1. Application Bean Definition    @Bean    @ConditionalOnMissingBean    @Value(${dubo.application.name})    public static DubboApplication dubboApp() {        return new xxx;    }        // 2. Registry Bean Definition        // 3. Protocol Bean Definition}

而后, 在pom中添加其依赖就完工了:

   <dependency>
        <groupId>com.wacai</groupId>
        <artifactId>spring-boot-starter-dubbo</artifactId>
        <version>...</version>
    </dependency>

固然, dubbo跟哥属于一个时代,其实使用JavaConfig来配置仍是有些不适应的,并且基本上大部分dubbo服务也都是经过xml形式进行配置的,不过不要紧, 退一步讲, 都不须要自动配置模块, 经过convention来约定说咱们全部的dubbo项目从src/main/resources/spring/*.xml这样的资源路径来加载容器的配置就能够了, 更他娘的简单!

@Configuration@ImportResource("classpath*:/spring/*.xml") ...public class Main {    ... }@Configuration@ImportResource("classpath*:/spring/*.xml") ...public class Main {    ... }

使用的pattern请各位看官灵活把握!

4.2.2 WebAPIAutoConfiguration

其实对于性能要求不是那么苛刻的场景(大多数应用其实都归于此类), 咱们彻底能够只走HTTP就行了, 服务注册中心都现成的通过多年验证的成熟方案(I mean DNS), 并且,多语言生态下的互通这也是惟一比较合理的一条路, 这就是我如今公司内部一直强调“大部分状况下,互通优于性能”, 只有在特殊需求下,才有必要花费经历对性能去进行优化(好比使用dubbo这种特定于java的方案, 对网络,系统甚至代码等进行调优)。

故此,咱们内部除了基于dubbo的微服务,还有web api形式的微服务,我说web api而不是说rest(ful) api, 是由于,虽而后者更高大上, 但对于咱们的团队来讲, 简单粗暴的作法更容易接受且符合团队现状, hibernate当年搞得映射关系支持的多么牛逼,最后还不是都本身在代码逻辑里管理这些关系, 而几乎只用它最基本的CURD支持吗?! 存在确定是有理由的,哈哈

web api的设计咱们就很少说了, 建议是采用适合本身团队的作法, 咱们来聊正事!

基于SpringBoot提供web api, 咱们能够选择基于JavaEE标准的starter模块,好比spring-boot-starter-jersey, 也可使用高大上的spring-boot-starter-hateoas, 其实基本上不须要本身提供扩展。

4.2.2.1 Web API Documentation

咱们可使用Swagger提供当前Web API的文档。

  1. 添加maven依赖

       <dependency>
            <groupId>com.mangofactory</groupId>
            <artifactId>swagger-springmvc</artifactId>
            <version>1.0.2</version>
        </dependency>
  1. src/main/resources目录下添加swagger-ui的相关资源(亲们,本身google大法吧~)

  2. 启动类上添加相应配置

@Configuration@PropertySource("file:conf/application.properties")@ImportResource("classpath*:/spring/*.xml")@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})@ComponentScan@EnableSwaggerpublic class Main {    private SpringSwaggerConfig springSwaggerConfig;    @Autowired    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {        this.springSwaggerConfig = springSwaggerConfig;    }    @Bean    public SwaggerSpringMvcPlugin configureSwagger() {        ApiInfo apiInfo = new ApiInfo("sample web api", "web api project with spring boot", null, null, null, null);        return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo).useDefaultResponseMessages(false).includePatterns("/*");    }    public static void main(String[] args) {        SpringApplication app = new SpringApplication(Main.class);        app.setShowBanner(false);        app.run(args);    } }@Configuration@PropertySource("file:conf/application.properties")@ImportResource("classpath*:/spring/*.xml")@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})@ComponentScan@EnableSwaggerpublic class Main {    private SpringSwaggerConfig springSwaggerConfig;    @Autowired    public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {        this.springSwaggerConfig = springSwaggerConfig;    }    @Bean    public SwaggerSpringMvcPlugin configureSwagger() {        ApiInfo apiInfo = new ApiInfo("sample web api", "web api project with spring boot", null, null, null, null);        return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo).useDefaultResponseMessages(false).includePatterns("/*");    }    public static void main(String[] args) {        SpringApplication app = new SpringApplication(Main.class);        app.setShowBanner(false);        app.run(args);    } }

而后经过/index.html路径访问swagger-ui, 而后在api信息查询输入框中输入对应host下的/api-docs路径的URL, 就能够获取相应的API文档信息了。

API文档随同Web API一块儿发布,fucking amazing!

4.3 DevOps-Specific Customization

系统不是一个个的孤岛, 咱们须要链接起来才会发挥更大的效能, 为了让SpringBoot能够融入挖财的技术生态中,咱们会对其进行一些定制, 这些定制对各位看官来讲不必定有用, 权且做为点滴参考。

4.3.1 config customization

咱们的应用配置采用配置中心 4进行管理, 但流程上对研发是透明的, 开发阶段配置文件按照约定放在项目根目录下的conf/目录, 发布包的结构也是一样的,配置文件名采用SpringBoot的默认application.properties便可, 惟一须要调整的配置就是配置文件的加载路径, 这能够在应用启动的时候指定命令行参数搞定:--spring.config.location=file:conf/, 或者:

...@PropertySource("file:conf/application.properties") ...public class Main {    public static void main(String[] args) {        SpringApplication app = new SpringApplication(Main.class);        app.setShowBanner(false);        app.run(args);    } }...@PropertySource("file:conf/application.properties") ...public class Main {    public static void main(String[] args) {        SpringApplication app = new SpringApplication(Main.class);        app.setShowBanner(false);        app.run(args);    } }

咱们还能够提供一个新的AutoConfiguraiton的module, 这个module提供一个新的PropertySource指向咱们约定的位置就好了, 具体方案会结合咱们的发布平台再选择最为合适的, 可选方案只是为了给你们一些启发思路。

4.3.2 logging customization

在挖财,咱们对日志格式进行了规范, 并且使用logback, 且对日志的输出路径也作了规定,以便全部应用一旦部署就能够自动享受到咱们的日志采集分析平台的服务。

SpringBoot由于一些历史缘由和向前兼容保持一致性等因素的关系(不知道有没有其它利害), 一直主要用commons-logging, 咱们显然不喜欢这个默认设置,因此, 咱们对SpringBoot的日志设定作了一些定制:

  1. 添加spring-boot-starter-logging依赖,让spring boot使用logback;

  2. 添加logback.xml配置文件,配置规则遵循咱们本身的规范;

  3. 启动的时候,设置LOG_HOME环境变量或者命令行参数;

5 Scala Is Also Bootiful

咱们团队有部分精英同窗(Scala Elites)使用Scala语言进行开发, 而对于SpringBoot来讲, 使用任何JVM上的语言原则上都不是什么问题, 好比, 要使用Scala进行SpringBoot应用的开发, 只须要添加Scala的相应依赖和编译支持就能够了:

<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>1.2.5.RELEASE</version>
    </parent>

    <groupId>com.wacai</groupId>
    <artifactId>hello-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>hello-spring-boot</name>
    <url>http://maven.apache.org</url>

    <properties>
        <encoding>UTF-8</encoding>
        <scala.version>2.11.6</scala.version>
    </properties>


    <build>
        <plugins>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <id>compile-scala</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile-scala</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <recompileMode>incremental</recompileMode>
                    <scalaVersion>${scala.version}</scalaVersion>
                    <args>
                        <arg>-deprecation</arg>
                    </args>
                    <jvmArgs>
                        <jvmArg>-Xms64m</jvmArg>
                        <jvmArg>-Xmx1024m</jvmArg>
                    </jvmArgs>
                </configuration>
            </plugin>

        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>${scala.version}</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>${scala.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies></project>

若是使用SBT而不是Maven, 可能须要费点儿周折, 须要本身添加一系列的依赖,而且解决按照SpringBoot的可执行jar规范格式发布的问题。

6 Distribute SpringBoot Application

SpringBoot提供了相应的Maven插件用于将SpringBoot应用以可执行jar包的形式发布出去, 只要将以下插件配置加入pom便可:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins></build>

容许mvn package将直接得到一个可执行的jar包(java -jar xxxx.jar), 具体原理参考SpringBoot的Reference文档附录。

7 Conclusion

SpringBoot初看上去颇为复杂,但一旦你了解了它内部的精妙设计, 就会有那种“柳暗花明”的感受了。本文最后引用的参考链接中使用钢铁侠来类比SpringBoot,我以为仍是挺恰当的, 感受上很笨重,但实际上倒是灵活可拆装, 多种后备组合可供选择, 既有雄厚的商业实体支撑, 还有良好的群众基础, fucking perfect!

SpringBoot, 你值得拥有 ;)

8 References

  1. Spring Boot – Simplifying Spring for Everyone

  2. http://www.infoq.com/news/2014/04/spring-boot-goes-ga

  3. http://www.infoq.com/articles/microframeworks1-spring-boot

  4. Improved support for 'containerless' web application architectures

  5. Why We Do Not Use Spring Boot Auto Configuration

  6. CORS support in Spring Framework

  7. http://www.schibsted.pl/2015/07/spring-boot-and-dropwizard-in-microservices-development/

  8. SpringBoot Javadoc and Sourcecode

  9. http://callistaenterprise.se/blogg/teknik/2015/03/25/an-operations-model-for-microservices/

  10. http://microservices.io/patterns/index.html

  11. other more posts and docs that I can't remember...


  1. Dropwizard的作事方式对于Senior来讲是OK的,但仍是处于半自动状态,不少东西须要本身装配,技术选型很优秀,但拼总体的时候,就有些力有不歹

  2. 默认运行嵌入的tomcat,因此使用默认的8080端口

  3. 注意不少时候Profile不必定与Environment相对应, 估计不少开发人员看到文档后并无彻底理解概念,只是照葫芦画瓢,致使profile概念如今大面上被滥用/用坏

  4. 注意,这里的配置中心跟如今技术社区里提到的配置中心是两个概念, 如今技术社区里经常提到的配置中心叫"状态中心"还差很少, 由于本质上他们是在用数据库也好仍是zookeeper也罢做为一个共享状态, 而后让相关系统来“参拜”, 而若是系统设计趋于理想化的话,这些状态应该内聚到服务内部, 若是外部要与这些状态交互, 经过消息传递依次或者并行送达相应的消息就行了,只不过, 这对研发人员的要求,对服务治理,安全等都会形成压力,因此你们就都省事,采用了如今SharedState的模式, 固然,也不失为实践的一种合理方式,无绝对好坏


转载于:https://www.cnblogs.com/duyinqiang/p/5696308.html