Spring Boot应用开发起步

Spring Boot应用的创建


Spring Boot支持多种集成方式,如CLI,Maven,Gradle。这里以Mavan为例,一个典型的Maven Spring Boot应用需要满足Spring Boot的约定,比如最常用的从spring-boot-starter-web开始,那么项目的build脚本可以这样配置开始:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 
 3 <project xmlns="http://maven.apache.org/POM/4.0.0"
 4          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 6     <modelVersion>4.0.0</modelVersion>
 7 
 8     <groupId>com.example</groupId>
 9     <artifactId>cnblogs_example</artifactId>
10     <version>1.0-SNAPSHOT</version>
11 
12     <parent>
13         <groupId>org.springframework.boot</groupId>
14         <artifactId>spring-boot-starter-parent</artifactId>
15         <version>2.0.0.BUILD-SNAPSHOT</version>
16     </parent>
17 
18 
19     <dependencies>
20         <dependency>
21             <groupId>org.springframework.boot</groupId>
22             <artifactId>spring-boot-starter-web</artifactId>
23         </dependency>
24     </dependencies>
25 
26     <!-- ignore others-->
27 </project>

 

一个基本的应用可以由Example.java的定义完成:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableAutoConfiguration
public class Example {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);

}

自此,一个完整,虽然简单的Spring Boot Web应用已经产生。当然,如果需要直接通过"mvn package"就可以生成一个all-in-one的可执行jar(Uber jar),我们还需要在pom.xml中添加一些内容,最终的内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<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>

    <groupId>com.example</groupId>
    <artifactId>cnblogs_example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.BUILD-SNAPSHOT</version>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>Example</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
View Code

这样就可以简单地通过“java -jar cnblogs_example-1.0-SNAPSHOT.jar”来运行这个web应用,并可以通过http://127.0.0.1:8080/来访问了,真的是很简单,而且可移植性强,一个jar文件在有Java运行时的地方都可以跑起来了。

 

一些配置规范(COO)


Application源 

Application源指的是用SpringApplication搜索的Application的定义的集合。如示例中的 SpringApplication.run(Example.class, args); 用的就是“Class”类型的源,因为指定的是一个具体的Class。

根据参考【2】,目前(v2.0)支持的sources类型有:

  • Class:能够被AnnotatedBeanDefinitionReader加载的Java类
  • Resource:能够被XmlBeanDefinitonReader加载的XML资源,或者能被GroovyBeanDefinitionReader加载的groovy script
  • Package:被ClassPathBeanDefinitionScanner扫描的Java包
  • CharSequence:依次尝试作为Java class,Resource, 和Java包加载。

 配置文件application.properties

Spring Boot默认的配置文件甚至可以不存在,需要的话也很简单,只要在项目的“src/main/resources”目录下创建application.properties文件就可以了,很多配置就可以直接写在这里了,常用的配置有port,datasource等等。比如:

server.port=9090

spring.datasource.url = [url]
spring.datasource.username = [username]
spring.datasource.password = [password]
spring.datasource.driverClassName = oracle.jdbc.OracleDriver
spring.datasource.jmx-enabled=true

#second db ... spring.secondDatasource.url = [url] spring.secondDatasource.username = [username] spring.secondDatasource.password = [password] spring.secondDatasource.driverClassName = oracle.jdbc.OracleDriver
spring.secondDatasource.jmx-enabled=true

顺便记录一下程序中datasource的引用方式:

@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

这里虽然可以配置多个datasource,我们在项目中需要使用JMX查询bean,使用中发现,目前Spring Boot + Tomcat的使用中还只支持primary datasource的JMX暴露,而且名称固定为“dataSourceMBean”。

 

应用是如何组织起来的?


显然Spring Boot为我们隐藏了很多技术细节,包括启动过程,这里希望对其启动的原理做一点总结。

简化的Maven父项目

在上面示例项目中,继承了“spring-boot-starter-parent”项目,背后也为我们提供了很多便利性支持,比如自动具有了如下功能【1】

  • Java 1.6作为默认的编译级别
  • UTF-8编码
  • 依赖声明中可以省略<version>,默认从spring-boot-dependencies继承
  • 敏感信息过滤

强大的包依赖和插件管理

这本身是maven的特性,但Spring Boot通过提供maven的扩展插件为微服务的运行提供了很好的封装。比如,我们在项目中使用的几个插件:

maven-dependency-plugin

用于打包操作,把一些依赖的jar内容解压到项目源码列表中,以便通过一般jar的规范来引用。

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
    <execution>
    <phase>prepare-package</phase>
    <goals>
        <goal>unpack-dependencies</goal>
    </goals>
    <configuration>
        <includeArtifactIds>foglight-agent</includeArtifactIds>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
    </configuration>
    </execution>
</executions>
</plugin>
maven-jar-plugin

用于操作Uber-jar的manifest:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
    <archive>
    <manifestEntries>
        <Premain-Class>com.quest.pas.agent15.AgentPremain</Premain-Class>
        <Can-Redefine-Classes>true</Can-Redefine-Classes>
        <Can-Retransform-Classes>true</Can-Retransform-Classes>
    </manifestEntries>
    </archive>
</configuration>
</plugin>

 

再比如,在加入“spring-boot-starter-web”依赖之后,Spring Boot就得到了如下的依赖,包含Tomcat和Spring Boot自身jar:

D:\Workspace\MicroServices\cnblogs_example>mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building cnblogs_example 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ cnblogs_example ---
[INFO] com.example:cnblogs_example:jar:1.0-SNAPSHOT
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    +- org.springframework.boot:spring-boot-starter:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  +- org.springframework.boot:spring-boot:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  |  \- io.projectreactor.addons:reactor-test:jar:3.0.5.RELEASE:compile
[INFO]    |  |     \- io.projectreactor:reactor-core:jar:3.0.5.RELEASE:compile
[INFO]    |  |        \- org.reactivestreams:reactive-streams:jar:1.0.0:compile
[INFO]    |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  |  +- ch.qos.logback:logback-classic:jar:1.2.2:compile
[INFO]    |  |  |  +- ch.qos.logback:logback-core:jar:1.2.2:compile
[INFO]    |  |  |  \- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO]    |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.25:compile
[INFO]    |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO]    |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.25:compile
[INFO]    |  +- org.springframework:spring-core:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  \- org.yaml:snakeyaml:jar:1.18:runtime
[INFO]    +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.12:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.12:compile
[INFO]    |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.12:compile
[INFO]    +- org.hibernate:hibernate-validator:jar:5.4.1.Final:compile
[INFO]    |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO]    |  +- org.jboss.logging:jboss-logging:jar:3.3.1.Final:compile
[INFO]    |  \- com.fasterxml:classmate:jar:1.3.3:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.0.pr2:compile
[INFO]    |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0.pr2:compile
[INFO]    |  \- com.fasterxml.jackson.core:jackson-core:jar:2.9.0.pr2:compile
[INFO]    +- org.springframework:spring-web:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  +- org.springframework:spring-aop:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  +- org.springframework:spring-beans:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]    |  \- org.springframework:spring-context:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]    \- org.springframework:spring-webmvc:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO]       \- org.springframework:spring-expression:jar:5.0.0.BUILD-SNAPSHOT:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

 

SpringApplication引导程序

 SpringApplication类为用户程序提供了引导程序的作用,启动方式为在用户的main方法中调用,SpringApplication的主要工作有,参考【2】

  • 根据classpath创建合适的ApplicationContxt实例
  • 为启动命令行参数注册CommandLinePropertySource,并作为Spring的属性对外暴露
  • 刷新ApplicationContext,加载所有的单例bean
  • 触发所有的CommandLineRunner beans。

这里又会涉及大量的实现细节,也有很多文章做了详细的描述,可以通过搜索来加深理解。

 

Spring Boot是什么? - Microservices话题


 

要了解Spring Boot,还得了解一点它的自身身份定位,因为Spring Boot本身不是凭空而出的,它一定是为了解决某类问题而出现的,那么它要解决的问题就是Microservices的落地问题。这里主要是想梳理一下几个重要的概念,具体细节已经有很多文章参考了。

Microservices

Microservices,可以参考wikipedia的词条,注意这里带“s”结尾,它指的是微服务架构,或者更准确说是一种架构风格。如同其他架构风格一样,微服务也有它的历史源头和发展路径,到如今成为热门话题,也是因为它符合了历史潮流。从“认祖归宗”的角度来看,它还是属于“SOA”的一个实践方案。 背后的哲学思想是:“Do one thing and do it well”。也是现在的我自己正在并继续努力奉行的哲学。

除了wikipedia之外,我看到这篇文章也对微服务架构做了很好的总结。

Microservice chassis

不确定这个词怎么翻译合适,先这么用着吧。为什么提到这个词,因为人们会吧Spring Boot定位为一种Microservice chassis,个人认为这是一种较为精确的分类,Pattern: Microservice chassis一文中也有详细的说明。从这个角度分类,这就好比Spring Boot诞生的背后的价值观,Spring Boot确切的说是用来解决我们实现Microservices过程中可能遇到的一些具体“麻烦”,是一种framework,方便开发者的工作。从前面的简单示例里面可以看到,真的使得开发变得很简单!

Microservice chassis需要解决的实际问题包括:外部配置、日志、健康监控、运行状态和分布式的跟踪。

Microservices框架

我的理解,这是从另外一个角度来归类Spring Boot,这说明Spring Boot除了解决以上一些开发的具体“麻烦”琐事之外,还提供了更一般性的,可复用的软件开发和运行环境,包括支持指令、编译器、类库、工具集、API等来支持一个软件项目/系统的开发。

对Spring Boot来说,它解决了基本的开发问题,通过依赖的方式提供了所有开发一个微服务系统的所需的所有功能,同时配合Spring Cloud就足够完备了。

 

所以,chassis和框架很多时候是在一个系统都实现了,或者说一个完备的系统会同时满足chassis和框架的要求。

 

References:


 

【1】Spring Bootf官方文档:http://docs.spring.io/spring-boot/docs/current/reference/html/

【2】: http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow

【3】:http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplication.html

【4】Spring Boot启动过程与回调接口汇总:https://segmentfault.com/a/1190000006918229

【5】Microservices: https://en.wikipedia.org/wiki/Microservices

【6】Microservice chassis: http://microservices.io/patterns/microservice-chassis.html

 

版权申明: 欢迎分享,转载请注明出处http://www.cnblogs.com/1xin/p/6627054.html

posted on 2017-03-28 15:48  JeromeTang  阅读(310)  评论(0编辑  收藏  举报