微服务构建:Spring Boot
框架简介
Spring Boot的出现改善了配置文件繁琐的问题,spring boot的宗旨并非重写spring或者是替代spring,而是希望通过设计大量的自动化配置等方式来简化spring原有的样板化的配置,使得开发可以快速构建应用。
spring boot还通过一系列的starter POMS的定义,让我们整合各项功能的时候,不需要在maven 的pom.xml中维护那些错综复杂的依赖关系,而是通过类似模块化的starter模块定义来引用,使得依赖管理工作更为简单。
在如今容器化大行其道的时代,spring boot可以很好的融入docker之外,其自身支持嵌入式的Tomcat、jetty等容器。只需要将spring boot应用打包成jar包,并通过java -jar命令直接运行就能启动一个标准化的web应用。
快速入门
项目构建与解析
系统工具及版本要求:
java7及以上工具
spring framework 4.2.7以上版本
maven3.2及以上版本
工程项目解析
maven配置分析
<?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.microservices</groupId>
<artifactId>spring-boot-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-hello</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring-boot-starter-web:
- 全栈web开发模块,包含嵌入式的Tomcat、springMVC
org.springframework.boot
- 通用测试模块,包含Junit、Hamcreast、Mockito。
实现RESTful API
编写controller
package com.microservices.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String index() {
return "Hello World";
}
}
启动spring boot
启动方式有:
- 启动HelloApplication的main函数
- 在工程目录下,执行mvn spring-boot:run
- 在服务器部署时,通常将工程打包成jar包,再通过java -jar xxx.jar来启动应用
编写单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = HelloApplication.class)
@WebAppConfiguration
public class HelloApplicationTests {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
}
@Test
public void hello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/hello")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Hello World")));
}
}
代码解析如下:
- @RunWith:引入spring对junit4的支持
- @SpringApplicationConfiguration:指定spring boot的启动类
- @Before:在执行@test注解的方法前,先初始化对HelloController的模拟
- MockMvc对象:用于模拟调用controller的接口发起请求,perform函数执行一次请求调用,accept用于执行接收的数据类型,andExpect用于判断接口返回的期望值。
配置详解
配置文件
spring boot支持传统的properties文件外,还支持YAML文件类型的配置文件。YAML常用的配置格式不像properties以单纯的键值对形式来表示,而是以大纲的缩颈形式来表示
environment:
dev:
url:http://dev.bar.com
name:dev
prod:
url:http://prod.bar.com
name:prod
以上配置等价于:
environment.dev.url=http://dev.bar.com
environment.dev.name=dev
environment.prod.url=http://prod.bar.com
environment.prod..name=prod
通过yaml的配置方式,我们可以看到,配置信息利用阶梯化缩颈的方式,更具有可读性,配置的字符也减少了许多。除此之外,yaml还可以在一个单独的文件中通过spring.profiles属性来定义多个不同的环境配置,比如下面例子,在指定为test环境时,server.port将使用8882端口;而在prod环境中,server.port将使用8883端口;如果没有指定端口,server.port将使用8881端口。
server:
port:8881
---
spring:
profiles:test
server:
port:8882
---
spring:
profiles:prod
server:
port:8883
注意:
yaml目前还有不足之处,它无法通过@propertySource注解来加载配置。但是,YAML将属性加载到内存中是有序的,所以当配置文件中的信息需要具备顺序含义时,yaml的配置方式比起properties配置更具有优势。
自定义参数
我们可以在properties文件中自定义一些参数
book.name=springCloud
book.author=zzw
然后在应用使用@Value注解加载自定义的参数
@Component
public class Book {
@Value("${book.name}")
private String name;
@Value("${book.author}")
private String author;
@Value注解加载属性值的时候可以支持两种表达式进行配置,如下:
- 一种是通过上面介绍的placeholder方式,格式为${…},大括号内为placeholder
- 另外一种是使用spel表达式,格式为#{…},大括号内为spel表达式
参数引用
在properties文件中,各个参数之间可以通过使用 placeholder的方式进行引用,就像下面的配置
book.name=springCloud
book.author=zzw
book.desc = ${book.name} ======${book.author}
使用随机数
在一些特殊的情况下,我们希望有些参数每次被加载的时候不是一个固定的值,比如密钥,服务端口等。在spring boot的属性配置文件中,我们可以使用${random}配置来产生随机的int、long或string字符串。
${random}主要有以下配置方式:
#随机字符串
random.value = ${random.value}
#随机int
random.num=${random.int}
#随机long
random.bigNum=${random.long}
#10以内的随机数
random.limitedNum1=${random.int(10)}
#10-20以内的随机数
random.limitedNum2=${random.int[10,20]}
命令行参数
在通过java -jar方式启动spring boot时候,除了启动应用之外,还可以命令行中指定应用的参数,比如java -jar xxx.jar --server.port=8888,直接以命令行的方式设置server.port属性,并将启动端口设置为8888.
在用命令行启动spring boot时候,连续两个减号–就是对application.properties中的属性进行赋值的标识。而通过命令行来修改属性值是spring boot非常重要的一个特性。不同于以往spring应用通过maven的profile在编译器中进行不同环境的构建,spring boot这种方式可以让应用的打包内容贯穿开发、测试以及线上部署,而maven不同profile的方案为每个环境所构建的包,其内容本质上是不同的。
多环境配置
对于多环境的配置,各种项目构建工具或者是框架的基本思路是一致的,通过配置多种不同环境的配置文件,再通过打包命令指定需要打包的内容之后进行区分打包。spring boot也不例外。
在spring boot中,多环境配置的文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识,如下所示:
默认情况下,哪个具体的配置会被加载,需要application.properties文件中通过spring.profiles.active属性进行设置,其值是配置文件中对应的{profile}值。spring.profiles.active=dev就会加载application-dev.properties配置文件。
需要加载非默认情况下的配置文件来启动应用时,可以通过命令行参数来指定,比如通过命令行加载test环境下的配置文件并启动应用:
java -jar xxx.jar --spring.profiles.active=test