spring boot框架

Spring Boot是Pivotal团队的全新框架,旨在简化新Spring应用程序的引导和开发。 该框架采用了自以为是的配置方法,使开发人员无需定义样板配置。 这样一来,Boot的目标是在不断扩展的快速应用程序开发空间中处于领先地位。

多年来, Spring IO平台因具有庞大的XML配置和复杂的依赖关系管理而受到批评。 在去年的SpringOne 2GX会议上,Pivotal首席技术官Adrian Colyer 承认了这些批评 ,并特别指出该平台的目标是接受无XML的开发经验。 Boot将任务说明发挥到了极致,不仅使开发人员摆脱了对XML的需求,而且在某些情况下还使他们摆脱了编写导入语句的繁琐工作。 在公开测试版发布后的几天里,Boot通过可运行的Web应用程序演示了框架的简单性,该应用程序可在不超过140个字符的情况下以推文形式发布,因此受到了广泛的欢迎。

但是,Spring Boot不能替代构成Spring IO平台的“基础”层的许多项目。 的确,Spring Boot的目标不是为已解决的许多问题领域提供新的解决方案,而是利用该平台来培养开发经验,从而简化对这些现有技术的使用。 对于那些熟悉Spring生态系统的开发人员来说,Boot成为理想的选择,同时还允许新的采用者以简化的方式使用Spring技术来迎合他们。

为了追求这种改进的开发体验,Spring Boot以及实际上整个Spring生态系统都采用了Groovy编程语言 。 Groovy强大的MetaObject协议,可插拔的AST转换过程以及嵌入式依赖项解析引擎,这些功能为Boot提供了许多快捷方式。 Boot是其编译模型的核心,它利用Groovy来构建项目文件,因此它可以使用常见的导入和样板方法(例如类的main方法)来装饰类的生成字节码。 这使使用Boot编写的应用程序保持简洁,同时仍提供广泛的功能。

安装启动

从最基本的角度来看,Spring Boot只是一组可以被任何项目的构建系统利用的库。 为方便起见,该框架还提供了一个命令行界面,可用于运行和测试Boot应用程序。 可以从Spring存储库手动下载和安装框架发行版,包括集成的CLI。 一种更方便的方法是使用Groovy enVironment Manager(GVM) ,它将处理Boot版本的安装和管理。 Boot及其CLI可以由GVM使用命令行gvm install springboot 。 可以使用公式通过Homebrew软件包管理器在OS X上安装Boot。 为此,请先使用brew tap pivotal/tap Pivotal存储库,然后是brew install springboot命令。

要打包和分发的项目将需要依赖于Maven或Gradle之类的构建系统。 为了简化依赖关系图,对Boot的功能进行了模块化,并且可以通过导入Boot的所谓“启动程序”模块将依赖关系组引入到项目中。 为了轻松管理依赖项版本并利用默认配置,该框架公开了一个父POM,它可以由项目继承。 清单1中定义了一个Spring Boot项目的示例POM。

清单1
<?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>myproject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RC1</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

对于更简化的构建配置,开发人员可以利用Gradle构建系统的简洁Groovy DSL,如清单1.1所示。

清单1.1
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-snapshot" }
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.0.RC1")
}
}
apply plugin: 'java'
apply plugin: 'spring-boot'
repositories {
mavenCentral()
maven { url "http://repo.spring.io/libs-snapshot"  }
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-actuator:1.0.0.RC1'
}

为了帮助启动和快速启动Boot项目,Pivotal提供了所谓的“ Spring Initializr” Web界面 ,可用于下载预构建的Maven或Gradle构建配置。 也可以通过使用Lazybones模板快速启动项目,该模板将在执行lazybones create spring-boot-actuator my-app命令后为Boot应用程序创建必要的项目结构和gradle构建文件。

开发Spring Boot应用程序

Spring Boot应用程序的最流行示例是在框架公开发布后不久通过Twitter交付的一个示例。 如清单1.2所示,可以将一个非常简单的Groovy文件制作成功能强大的Spring支持的Web应用程序。

清单1.2
@RestController
class App {
@RequestMapping("/")
String home() {
"hello"
}
}

可以通过执行spring run App.groovy命令从Spring Boot CLI运行此应用程序。 引导程序分析文件,并通过各种称为“编译器自动配置”的标识符,确定该文件旨在用作Web应用程序。 然后,它依次在默认端口8080上的嵌入式Tomcat容器内引导Spring Application上下文。打开浏览器并导航到提供的URL将使您进入带有简单文本响应“ hello”的页面。 提供默认应用程序上下文和嵌入式容器的过程使开发人员可以专注于开发应用程序和业务逻辑的过程,并将它们从繁琐的模板配置中解放出来。

Boot能够确定类的所需功能的能力使其成为用于快速应用程序开发的强大工具。 从Boot CLI执行应用程序时,它们是使用内部Groovy编译器构建的,该编译器允许在生成字节码时以编程方式检查和修改类。 这样,使用CLI的开发人员不仅可以摆脱定义默认配置的麻烦,而且在某种程度上还不需要定义某些导入语句,这些导入语句在编译过程中可以被识别并自动添加。 另外,从CLI运行应用程序时,Groovy的内置依赖项管理器“ Grape”用于解析引导Boots编译和运行时环境所需的类路径依赖项,这由Boot的编译器自动配置机制确定。 这种习惯用法不仅使框架更易于使用,而且还允许将不同版本的Spring Boot与Spring IO平台中的特定版本的库结合使用,这反过来意味着开发人员无需担心管理复杂的系统。依赖图和版本控制结构。 此外,它为快速原型设计和快速生成概念验证项目代码打开了大门。

对于不是使用CLI构建的项目,Boot提供了许多“启动程序”模块,这些模块定义了一组依赖项,可以将这些依赖项引入构建系统中,以解决框架及其父平台所需的特定库。 例如, spring-boot-starter-actuator依赖项引入了一组基础Spring项目,以快速配置和运行应用程序。 这种依赖性的重点在于开发Web应用程序,尤其是RESTful Web服务。 当与spring-boot-starter-web依赖项一起包含时,它将提供自动配置以引导嵌入式Tomcat容器,并将映射对微服务应用程序有用的端点,例如服务器信息,应用程序度量标准和环境详细信息。 另外,当引入spring-boot-starter-security模块时,执行器将自动配置Spring Security以为应用程序提供基本身份验证和其他高级安全功能。 对于任何应用程序结构,它还将包括一个内部审核框架,该框架可用于报告目的或特定于应用程序的需求,例如制定身份验证失败锁定策略。

为了演示如何从Java Maven项目中快速启动并运行Spring Web应用程序,请考虑清单1.3中概述的应用程序代码。

清单1.3
package com.infoq.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
public class Application {
@RequestMapping("/")
public String home() {
return "Hello";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

Application类上@EnableAutoConfiguration批注的存在通知Boot,它应该采取一种自以为是的方法来配置应用程序。 这可以将样板配置推迟到框架假定的默认设置,该默认设置着重于使应用程序尽快启动和运行。 Application类也是可运行的,这意味着可以通过选择将该类作为Java应用程序运行来启动和主动开发该应用程序及其嵌入式容器。

当需要构建要分发的项目时,Boot的Maven和Gradle插件会挂接到那些构建系统的打包过程中,以生成可执行的“胖罐”,该罐嵌入了项目的所有缺陷,可以作为可运行的jar执行。 使用Maven打包Boot应用程序就像运行mvn package命令一样简单,同样,使用Gradle,执行gradle build命令会将可运行的jar输出到构建的目标位置。

开发微服务

考虑到Boot简化了Spring应用程序的开发,提供了以模块化方式导入依赖项的功能,对开发RESTful Web服务的内在重视以及其生成可运行jar的能力,因此该框架显然是可部署微程序开发中的强大工具。 -服务。 如前面的示例所示,启动并运行RESTful Web应用程序对于Boot来说是一项微不足道的任务。 但是要充分发挥Boot的潜力,我们将演示开发功能全面的RESTful微服务的复杂性。 微服务是企业基础架构中越来越流行的应用程序体系结构,因为它们允许快速开发,较小的代码库,企业集成和模块化可部署项目。 有许多针对此垂直开发的框架,本节将讨论利用Boot的简化来实现此目的。

数据库访问

可以为各种目的构建微服务,但是可以保证的是,大多数服务都需要具有读写数据库的能力。 Spring Boot通过自动配置Spring Data以进行数据库访问,使数据库集成成为一项繁琐的任务。 通过将spring-boot-starter-data-jpa模块简单地包含在项目中,Boot的自动配置引擎将检测到您的项目需要数据库访问,并在Spring应用程序上下文中创建必要的bean,以便您可以创建和使用存储库和服务。 为了更具体地说明这一点,请考虑清单1.4中的Gradle构建文件,该文件概述了基于Groovy的Boot微服务Web应用程序的构建结构,该应用程序使用Spring Data的JPA支持进行数据库访问。

清单1.4
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-snapshot" }
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.0.RC1")
}
}
apply plugin: 'groovy'
apply plugin: 'spring-boot'
repositories {
mavenCentral()
maven { url "http://repo.spring.io/libs-snapshot"  }
}
ext {
springBootVersion = "1.0.0.RC1"
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.2.1'
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
}

在这种配置中,Boot的actuator模块提供了对hsqldb的依赖关系,并将设置所有必需的配置(包括架构创建),以便Spring Data可以将关系内存数据库用作其数据源。 此快捷方式使开发人员无需在开发中创建和管理复杂的数据源XML配置,并Swift为开发数据库驱动的微服务打开了大门。 如果在类路径中找到H2或Derby嵌入式数据库,则存在相同的自动配置功能。 Boot提供的另一个便利是它具有使用相关数据快速轻松地引导应用程序的数据库模式的能力。 这在开发中非常有用,开发中数据库可能是内存中的或易失的,并且开发人员需要确保在应用程序启动时某些数据点可用。 为了说明这一点,请考虑清单1.5中所示的示例JPA实体,它表示微服务将提供的“用户”数据结构。

清单1.5
@Entity
class User {
@Id
@GeneratedValue
Long id
String username
String firstName
String lastName
Date createdDate
Date lastAccessed
Boolean isActive = Boolean.TRUE
}

要引导代表一些常见的数据User对象,我们可以简单地创建一个名为文件schema.sqldata.sql ,它包括我们的类路径。 该文件将在创建模式后执行,因此,如清单1.5所示,给定实体,我们可以使用SQL语句引导用户帐户,如清单1.6所示。

清单1.6
insert into user(username, first_name, last_name, created_date) values ('danveloper', 'Dan', 'Woods', now())

启动后,将执行提供SQL代码,并且我们可以确保我们具有测试帐户。 既然微服务有一个数据点,清单1.7演示了我们如何遵循Spring Data的开发模式并创建一个Repository接口,该接口将充当User实体的数据访问对象。

清单1.7
public interface UserRepository extends CrudRepository<User, Long> {
}

CrudRepository提供了一些常见的接口方法来创建,检索,更新和删除对象以及对象集。 遵循Spring Data的存储库开发约定,可以定义我们的应用程序可能需要的任何特定功能。 创建UserRepository接口后,Boot的spring-data-jpa层将在项目中检测到它,并将其带入Spring应用程序上下文中,从而使其成为控制器和服务的自动候选对象。 仅当Boot应用程序请求采取有根据的方法时才会发生此自动配置,该方法由@EnableAutoConfiguration批注的存在来标识。 现在,微服务可以定义RESTful终结点,供消费者通过清单1.8中所示的控制器实现来检索用户列表或单个用户。

清单1.8
@RestController
@EnableAutoConfiguration
@RequestMapping("/user")
class UserController {
@Autowired
UserRepository repository
@RequestMapping(method=[RequestMethod.GET])
def get(Long id) {
id ? repository.findOne(id) : repository.findAll()
}
public static void main(String[] args) {
SpringApplication.run UserController, args
}
}

在启动时,该应用程序将输出日志记录,以显示Hibernate创建User实体所定义的数据库结构,并且还将显示Boot从schema.sql文件导入数据,作为应用程序初始化的最后一部分。

在开发微服务应用程序时,请注意使用@RequestMapping批注,这一点很重要。 这不是特定于Boot的注释。 但是,由于Boot出于监视应用程序的性能,运行状况和配置的目的而安装了自己的终结点,因此我们希望确保我们的应用程序代码不与那些内置详细信息提供程序的解析冲突。 鉴于此,当需要从请求路径解析属性(在这种情况下,是用户的id )时,我们需要仔细考虑动态属性解析将如何影响微服务的其余行为。 在这种情况下,只需将控制器映射到/user端点即可将其移出根上下文,并使Boot的端点也可访问。

我们的微服务提供的所有数据可能未必最适合于关系结构,为此,Spring Boot公开了一些模块,这些模块使开发人员能够使用Spring Data的MongoDB和Redis项目,同时仍采用自以为是的方法来配置它们。 Spring Data用于定义数据访问对象的高级框架使在JPA和非JPA数据源之间快速互换变得容易。 考虑清单1.9中的示例,该示例演示了一个重新定义的UserRepository接口,该接口旨在与MongoDB而不是JPA一起使用。

清单1.9
public interface UserRepository extends MongoRepository<User, Long> {
}

MongoRepository接口还扩展了CrudRepository ,因此清单1.8中的微服务的控制器代码无需更改。 为了简化MongoDB的集成,项目必须仅在应用程序的类路径中包含spring-boot-starter-data-mongodb模块。 如清单1.10所示,清单1.4中Gradle构建文件的依赖关系块只需稍作更改。

清单1.10
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.2.1'
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-data-mongodb:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
}

现在,MongoDB依赖项位于类路径上,Boot将自动配置Spring Data以连接到localhost上的数据库,默认情况下连接到test数据库。 从那里,将自动创建User集合(这是MongoDB的标准设置),并且微服务现在由MongoDB支持。 引导非JPA数据存储区的数据比其他方法要简单得多,但这主要是基于这样的事实:针对MongoDB的文档存储区或Redis的键值存储区运行SQL文件是没有意义的。 由于Spring Data将使用这些数据存储的持久实例,因此这也意味着在开发中创建的数据将在重启后幸免。 要开始使用持久数据,我们需要修改微服务控制器,以便User可以创建User实例。 通过让控制器以不同的方式处理不同的HTTP方法,我们还可以开始发展微服务的UserController以使其符合常见的RESTful API结构。 清单1.11演示了添加通过控制器创建新User实例的功能。

清单1.11
@RestController
@RequestMapping("/user")
@EnableAutoConfiguration
class UserController {
@Autowired
UserRepository repository
@RequestMapping(method=[RequestMethod.GET])
def get(Long id) {
id ? repository.findOne(id) : repository.findAll()
}
@RequestMapping(method=[RequestMethod.POST])
def create(@RequestBody User user) {
repository.save user
user
}
public static void main(String[] args) {
SpringApplication.run UserController, args
}
}

当微服务的使用者对应用程序的端点执行HTTP POST时,Spring会将请求主体强制为User实例。 然后,代码将使用UserRepository将对象存储在MongoDB集合中。 清单1.12显示了使用curl创建新的User实例的示例。

清单1.12
curl -v -H "Content-Type: application/json" -d "{ \"username\": \"danveloper\", \"firstName\": \"Dan\", \"lastName\": \"Woods\", \"createdDate\": \"2014-02-02T00:00:00\" }" http://localhost:8080/user

通过Boot提供有关应如何配置Mongo数据源的意见,默认情况下,新的User实例将持久保存到在本地主机上运行的Mongo实例中的test数据库上的user集合中。 如果打开Web浏览器并向微服务发出HTTP GET请求,我们将在列表中看到创建的用户。

组态

当您需要覆盖Spring Boot的配置默认值时,Spring Boot会很快使其摆脱困境。 默认情况下,应用程序配置可以使用Java属性文件在应用程序的类路径命名的根被定义application.properties 。 但是,一种首选的方法是使用YAML配置,它为嵌套配置提供了结构和深度。 给定应用程序运行时类路径上的snakeyaml依赖项,您的项目即可在application.yml文件中定义配置指令。 为了演示这一点,请考虑清单1.13中的示例YAML配置,其中概述了可用于应用程序的嵌入式HTTP服务器(默认情况下为Tomcat,选项为Jetty)的各种设置。

代码清单1.13
# Server settings (ServerProperties)
server:
port: 8080
address: 127.0.0.1
sessionTimeout: 30
contextPath: /
# Tomcat specifics
tomcat:
accessLogEnabled: false
protocolHeader: x-forwarded-proto
remoteIpHeader: x-forwarded-for
basedir:
backgroundProcessorDelay: 30 # secs

覆盖Boot的自动配置的能力使您可以将应用程序从原型移植到生产环境,而Boot使在同一application.yml文件中轻松完成此工作。 自动配置指令被设计为尽可能短,因此在使用actuator构建微服务时,将安装配置属性的端点/configprops ,并且在确定要覆盖的指令时/configprops该配置。 当我们准备好微服务使用诸如MySQL之类的持久数据源时,我们可以简单地将MySQL Java驱动程序添加到运行时类路径,并将必要的配置指令添加到application.yml文件,如清单1所示。 1.14。

清单1.14
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/proddb
username: root
password

在需要更灵活配置的方案中,Boot允许您通过使用Java System属性来覆盖其许多默认配置。 例如,如果您的应用程序在部署到生产环境时需要其他数据库用户,则可以使用标准Java System属性切换到命令行执行-Dspring.datasource.username=user ,将username配置指令传递给应用程序。 。 一个更实际的方案是在Cloud Foundry或Heroku之类的云部署中,这些平台要求应用程序在特定的HTTP端口上启动,该端口可通过主机操作系统中的环境变量使用。 Boot具有从系统属性中导出配置的功能,使您的应用程序可以通过命令行执行-Dserver.port=$PORT来继承HTTP端口。 当开发微服务时,这是框架的一个非常有用的功能,因为它允许微服务应用程序在各种环境配置上运行。

外部化配置

微服务必须能够做的一件非常重要的事情是支持外部化配置。 此配置可以保存从占位符消息到数据库配置的所有内容,其背后的体系结构是在应用程序的初始规划和原型设计期间必须考虑的领域。 目前,Spring IO平台中存在各种用于导入配置的策略,但是,支持应用程序可能希望使用配置的各种方式通常会导致冗长的程序耦合。

Boot的利基功能是它能够自动管理外部化配置,并将其强制为可在整个应用程序上下文中使用的对象结构。 通过创建一个普通的老式Java / Groovy对象,并使用@ConfigurationProperties批注对其进行装饰,该对象将使用Boot的配置结构中定义的配置name子集。 为了更清楚地描述这一点,请考虑清单1.15中的POGO,它从application.下面引入了配置指令application. 键。

清单1.15
@ConfigurationProperties(name = "application")
class ApplicationProperties {
String name
String version
}

在Spring上下文中创建ApplicationProperties对象时,Boot将识别出它是一个配置对象,并将根据运行时类路径上application.propertiesapplication.yml文件中的配置指令填充其属性。 在给定的条件下,如果将application块添加到微服务的application.yml文件中,如清单1.16所示,我们将能够从程序的其余部分以编程方式访问这些指令。

清单1.16
application:
name: sb-ms-custdepl
version: 0.1-CUSTOMER

这些配置指令可以用于多种目的,并且获得对其访问权限的唯一要求是,它们所代表的POJO / POGO是Spring应用程序上下文中的参与者。 通过引导,我们可以通过将控制器视为Spring Java配置对象来轻松管理配置Bean与应用程序上下文的集成,如清单1.17所示。

清单1.17
@RestController
@Configuration
@RequestMapping("/appinfo")
@EnableAutoConfiguration
class AppInfoController {
@Autowired
ApplicationProperties applicationProperties
@RequestMapping(method=[RequestMethod.GET])
def get() {
[
name: applicationProperties.name,
version: applicationProperties.version
]
}
@Bean
ApplicationProperties applicationProperties() {
new ApplicationProperties()
}
public static void main(String[] args) {
SpringApplication.run UserController, args
}
}

清单1.17中的代码是一个人为的示例,尽管给出了更为复杂的方案,但使用Boot设置对特定于应用程序的配置的访问的原理仍然相同。 配置类还可以支持嵌套的对象图,以提供来自配置的数据的深度和含义。 例如,如果我们还希望在应用程序下为我们的应用程序的指标密钥提供配置指令application. 在根目录下,我们可以向ApplicationProperties POGO添加一个嵌套对象来表示这些值,如清单1.18所示。

清单1.18
@ConfigurationProperties(name = "application")
class ApplicationProperties {
String name
String version
final Metrics metrics = new Metrics()
static class Metrics {
String dbExecutionTimeKey
}
}

现在,我们的application.yml文件可以按清单1.19所示进行制作,以包含application.下的metrics配置application. 块。

清单1.19
application:
name: sb-ms-custdepl
version: 0.1-CUSTOMER
metrics:
dbExecutionTimeKey: user.get.db.time

当需要访问application.metrics.dbExecutionTimeKey值时,可以通过ApplicationProperties对象以编程方式访问它。

application.propertiesapplication.yml文件中的这些配置指令不一定要强制使用对象图才能在整个应用程序中使用。 实际上,Boot还为Spring应用程序上下文提供了PropertySourcesPlaceholderConfiguration ,因此从application.properties文件, application.yml文件或Java System属性覆盖派生的指令都可以用作Spring属性占位符。 Spring的这种机制允许您使用特定的语法为属性定义占位符值,如果Spring找到提供该值的占位符配置,则会将其填充。 作为示例,我们可以使用@Value批注直接在控制器中访问application.metrics.dbExecutionTimeKey ,如清单1.20所示。

清单1.20
@RestController
@RequestMapping("/user")
@EnableAutoConfiguration
class UserController {
@Autowired
UserRepository repository
@Autowired
GaugeService gaugeService
@Value('${application.metrics.dbExecutionTimeKey}')
String dbExecutionKey
@RequestMapping(method=[RequestMethod.GET])
def get(Long id) {
def start = new Date().time
def result = id ? repository.findOne(id) : repository.findAll()
gaugeService.submit dbExecutionKey, new Date().time - start
result
}
public static void main(String[] args) {
SpringApplication.run UserController, args
}
}

稍后将对度量标准报告的复杂性进行更多的讨论,但是目前要了解的重要一点是,如何将@Value注释与Spring属性占位符一起使用,以使Boot自动填充我们微服务的特定配置的值。需要。

安全

在微服务开发中,必然会出现对全面安全环境的需求。 为了满足这一需求,Boot引入了功能强大且全面的Spring Security,并提供了自动配置功能,可以快速轻松地引导安全层。 仅仅在应用程序的类路径中仅存在spring-boot-starter-security模块,Boot即可利用其一些安全功能,例如跨站点脚本保护和添加防止点击劫持的标头。 另外,添加一个简单的配置指令,如代码清单1.21所示,将使用基本身份验证来保护您的应用程序。

清单1.21
security:
basic:
enabled: true

Boot将为您提供默认的用户帐户userUSER的默认角色,并在应用程序启动时向控制台输出随机生成的密码。 像大多数其他Boot一样,很容易使用显式定义的配置指令(分别为“ secured”和“ foo”)为内置user帐户指定不同的用户名和密码,如代码清单1.22所示。

清单1.22
security:
basic:
enabled: true
user:
name: secured
password: foo

Boot的内置功能可用于快速引导微服务中的基本身份验证,这对于简单的内部应用程序或开发原型非常有用。 随着需求的发展,您的应用程序无疑将需要某种粒度的安全性,例如将端点保护为特定角色的能力。 从这个角度来看,我们可能希望保护以USER角色表示的USER只读数据(即GET请求),而读写数据(即POST请求)应以ADMIN角色保护。 为方便起见,我们将在项目的application.yml文件中禁用Boot的基本身份验证自动配置,并为user帐户和admin帐户定义各自的角色。 这是该区域的另一个示例,当您需要超越其默认功能时,Boot会Swift使您迷路。 为了更实际地演示这一点,请考虑清单1.23中概述的代码。 可以详细说明该示例,以充分利用Spring Security的全部潜能,并利用更复杂的身份验证策略,例如JDBC支持的OpenID或Single Sign On。

代码清单1.23
@RestController
@RequestMapping("/user")
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableAutoConfiguration
class UserController extends WebSecurityConfigurerAdapter {
@Autowired
UserRepository repository
@RequestMapping(method = [GET])
@Secured(['ROLE_USER'])
def get(Long id) {
id ? repository.findOne(id) : repository.findAll()
}
@RequestMapping(method = [POST])
@Secured(['ROLE_ADMIN'])
def create(@RequestBody User user) {
repository.save user
user
}
@Override
void configure(AuthenticationManagerBuilder auth) {
auth
.inMemoryAuthentication()
.withUser "user" password "password" roles "USER" and() withUser "admin" password "password" roles "USER", "ADMIN"
}
@Override
void configure(HttpSecurity http) throws Exception {
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint()
entryPoint.realmName = "Spring Boot"
http.exceptionHandling().authenticationEntryPoint(entryPoint)
http.requestMatchers().antMatchers("/**").anyRequest()
.and().httpBasic().and().anonymous().disable().csrf().disable()
}
public static void main(String[] args) {
SpringApplication.run UserController, args
}
}

以清单1.23中的示例为例,该应用程序现在将身份验证配置为使用密码, password以及USERADMIN各自的角色来显式提供对useradmin用户帐户的访问。 微服务的GETPOST端点也分别为USERADMIN角色保护,这意味着普通用户现在可以访问只读数据,而执行读写操作则需要admin用户凭据。

对于微服务而言,基本身份验证是一个不错的选择,因为它遵循非常实用且广泛可用的身份验证协议。 换句话说,许多API使用者,包括移动应用程序,都可以很容易地利用它来访问您的微服务。 当您的身份验证需要增长的基本身份验证(即OpenID或OAuth)时,您的微服务可以利用Spring Security的全部功能来满足您的需求。

消息整合

在任何应用程序的工具包中,消息传递都是一个非常强大的实用程序,与此相关的微服务也不例外。 使用消息驱动的体系结构开发这些应用程序可以支持可重用性和可伸缩性。 Spring Boot允许开发人员通过使用Spring IO平台对企业集成模式Spring Integration的实现,以消息传递作为体系结构的核心租户来编写微服务。 Spring Integration提供了用于开发消息驱动的体系结构的结构,并提供了用于与分布式企业平台集成的模块。 此功能允许微服务利用来自抽象消息传递源的业务对象,无论该源是在应用程序内还是从组织内的另一服务提供。

尽管Boot没有提供任何显式的Spring上下文自动配置,但它确实提供了用于Spring Integration的启动程序模块,该模块负责从Spring Integration项目中引入大量依赖项。 这些依赖项包括Spring Integration的Core库,其HTTP模块(用于面向HTTP的企业集成),其IP模块(用于基于Socket的集成操作),其File模块(用于文件系统集成)和其Stream模块(用于与Stream一起使用)。 ,例如stdin和stdout)。 该入门模块为开发人员提供了强大的消息传递功能工具包,用于使现有基础结构适应微服务API。

除启动程序模块外,Boot还为通过CLI构建的应用程序提供了编译器自动配置。 这为正在快速制作微服务原型并显示可行性的开发人员提供了一些捷径。 可以快速开发利用企业平台的应用程序,并在将其移至正式项目和构建系统之前快速确定其价值。 使用Spring Boot和Spring Integration来启动和运行消息驱动的微服务就像清单1.24中描述的代码示例一样容易。

清单1.24
@RestController
@EnableIntegrationPatterns
class App {
@Bean
def userLookupChannel() {
new DirectChannel()
}
@Bean
def userTemplate() {
new MessagingTemplate(userLookupChannel())
}
@RequestMapping(method=[RequestMethod.GET])
def get(@RequestParam(required=false) Long id) {
userTemplate().convertSendAndReceive( id ? id : "")
}
}
class User {
Long id
}
@MessageEndpoint
class UserLookupObject {
@ServiceActivator(inputChannel="userLookupChannel")
def get(Long id) {
id ? new User(id:id) : new User()
}
}

采用消息驱动的方法进行微服务开发可提供大量的代码可重用性以及与基础服务提供者实现的分离。 在不太人为的情况下,清单1.18中的代码可能负责组成企业组织内来自数据库调用和外部服务集成的数据。 Spring Integration具有用于有效负载路由和处理程序链接的内置结构,这使其成为处理异构数据的一种有吸引力的解决方案,我们可能会发现微服务是提供程序。

提供指标

微服务最重要的功能也许是其向报表代理提供指标的能力。 与厚网络应用程序不同,微服务是轻量级的,其设计目的不是提供报告屏幕或强大的界面来分析服务的活动。 这些类型的操作最好留给严格负责数据聚合和分析的应用程序,以实现稳定性,性能和商业智能监视。 有了这些,微服务将为那些报告工具提供端点,以轻松使用有关其活动的数据。 从那里开始,报告工具负责将数据组合成对关心数据的人有意义的视图或报告。

尽管可以在所有应用程序中概括一些关于微服务的度量标准(例如稳定性和性能),但与业务运营相关的度量标准必须由应用程序专门管理。 为此,Spring Boot的actuator模块公开了一种机制,供开发人员通过/metrics端点以编程方式公开有关微服务状态的详细信息。 Boot将指标细分为“计数器”和“量规”类别; 计数器是任何表示为数字的度量,其中量规是一种以双精度测量某些计算的度量。 为了使微服务开发人员易于使用指标,Boot将CounterServiceGaugeService作为可自动选择的GaugeService公开给应用程序上下文。 考虑清单1.25中的示例,该示例演示了通过CounterService公开命中计数。

清单1.25
@RestController
@RequestMapping("/user")
@EnableAutoConfiguration
class UserController {
@Autowired
UserRepository repository
@Autowired
CounterService counterService
@RequestMapping(method = [GET])
def get() {
get(null)
}
@RequestMapping(value="/{id}", method = [GET])
def get(@PathVariable Long id) {
counterService.increment id ? "queries.by.id.$id" : "queries.without.id"
id ? repository.findOne(id) : repository.findAll()
}
}

在使用/user不使用提供的ID击中/user端点后, /metrics端点将在counter.下报告新密钥counter. 父母 例如,如果我们仅查询不带ID的/user端点,则counter.queries.without.id度量将被注册并可用。 同样,当我们确实提供ID时,我们将看到显示的counter.queries.by.id.<id>键表示已对提供的ID进行了多少次查询。 这些度量可以提供对最常访问的User对象的一些了解,并且可以表示一些需要采取的操作,例如缓存或数据库索引。 以增加度量标准计数的相同方式, CounterService还允许将度量标准减为零。 这对于跟踪打开的连接或其他直方图测量可能很有用。

量规是一种略有不同的度量标准,因为它们为计算得出的值或根据请求提供的确定值提供启发。 正如GaugeService JavaDocs指出的那样,“量规”度量可以是从方法执行时间到会议室温度的任何值。 当公开报告工具的详细信息时,这些类型的度量特别适合使用GaugeService 。 量规指标将在/metrics端点中带有gauge. 。 它们的注册方式与计数器的注册方式略有不同,如清单1.26所示。

清单1.26
@RestController
@RequestMapping("/user")
@EnableAutoConfiguration
class UserController {
@Autowired
UserRepository repository
@Autowired
CounterService counterService
@RequestMapping(method = [GET])
def get() {
get(null)
}
@RequestMapping(value="/{id}", method = [GET])
def get(@PathVariable Long id) {
def start = new Date().time
def result = id ? repository.findOne(id) : repository.findAll()
def time = new Date().time - start
gaugeService.submit("user.get.db.time", time.doubleValue())
result
}
}

默认情况下,度量标准将存储在易失性的内存数据库中,但是向应用程序上下文提供MetricsRepository的实现将允许更持久的存储行为。 Boot附带RedisMetricsRepository ,可以自动将其存储在Redis密钥库中,尽管可以为任何数据存储定制自定义实现以保留度量。

Boot还为Coda Hale Metrics库提供支持,并将以某些名称开头的指标强制转换为它们各自的Metrics类型。 例如,如果提供了以histogram.开头的指标histogram. ,然后Boot将提供该值作为Histogram对象类型。 这种自动强制也适用于meter.timer. 键,而常规指标则作为Gauge类型发送。

一旦在Boot中注册了微服务指标,即可由报告工具通过/metrics端点检索它们。 通过提供度量关键字名称作为查询字符串的一部分,可以将命名度量提供给/metrics端点。 例如,要访问度量标准“ user.get.db.time”,报告工具可以查询/metrics/gauge.user.get.db.time

打包启动应用程序

如前所述,Boot附带了Maven和Gradle的插件,它们提供了进入构建系统打包阶段的钩子,以生成所谓的“胖子”,其中包括了项目的所有依赖项。 当执行Fat jar时,应用程序代码将在开发项目的同一嵌入式容器中运行。 此快捷方式使开发人员可以放心,他们的可部署程序包具有与开发时相同的依赖关系结构和运行时环境。 这使操作团队不必担心部署场景,在这种场景下,配置错误的运行时容器可能具有一个依赖规范,而在另一个条件下开发了项目。

要在Maven下执行打包,只需执行mvn package命令。 Spring Boot插件将备份最初创建的项目jar,并在文件名后附加“ .original”将其重命名。 从这里开始,可运行的jar将遵循Maven工件命名约定,并且可以以最适合项目的方式进行部署。 用Gradle构建Boot项目同样也很简单,只需要执行标准gradle build命令即可。 与Maven相似,Boot插件会在原始打包任务之后安装Gradle的生命周期事件,并将胖文件夹生成到build/libs目录。 检查生成的胖罐子,将发现档案lib/目录中的所有依赖罐子。

打包后,可以使用命令$JAVA_HOME/bin/java -jar path/to/myproject.jar从胖命令行将其作为常规可运行jar文件执行。 启动后,启动应用程序日志记录将显示在控制台中。

对于需要部署到传统Servlet容器的功能的应用程序,Boot提供了以编程方式初始化Web配置的路径。 为方便起见,Boot提供了一个自以为是的WebApplicationInitializer ,它通过Servlet 3.0 API将应用程序注册到Servlet容器中,从而以编程方式向容器的ServletContext注册Servlet。 通过提供SpringBootServletInitializer的子类,引导应用程序可以将其配置注册到在容器初始化期间创建的嵌入式Spring上下文中。 为了演示此功能,请考虑清单1.27中演示的示例代码。

代码清单1.27
@RestController
@EnableAutoConfiguration
class Application extends SpringBootServletInitializer {
@RequestMapping(method = RequestMethod.GET)
String get() {
"home"
}
static void main(String[] args) {
SpringApplication.run this, args
}
@Override
SpringApplicationBuilder configure(SpringApplicationBuilder application) {
application.sources Application
}
}

Application类的重写的configure方法是用于在嵌入式Spring上下文中注册应用程序代码的方法。 在较不人为的情况下,此方法可用于注册Spring Java配置类,该类将为应用程序中的所有控制器和服务定义Bean。

将应用程序打包以部署到Servlet容器时,必须将项目构建为war文件。 为了将其容纳在Maven项目中,需要删除Boot插件,并且需要使用“ war”类型显式定义包装,如清单1.28所示。

清单1.28
<?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>myproject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RC1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
</project>

为此项目执行mvn install命令将导致将myproject-1.0.0-SNAPSHOT.war文件构建到target目录中。 使用Gradle构建的项目可以使用Gradle War插件,该插件公开了用于构建war文件的war任务。 与Maven配置类似,Boot Gradle项目也需要删除其包含的Boot插件。 清单1.29中描述了用于生成war文件的示例Gradle构建脚本。

代码清单1.29
apply plugin: 'java'
apply plugin: 'war'
repositories {
mavenCentral()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
ext {
springBootVersion = '1.0.0.BUILD-SNAPSHOT'
}
dependencies {
compile "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
compile "org.springframework.boot:spring-boot-starter-actuator:${springBootVersion}"
}

使用此构建脚本对Boot项目运行Gradle war任务会将war工件输出到build/libs目录。

在Maven或Gradle配置中,一旦产生了war文件,便可以将其部署到任何符合Servlet 3.0的应用程序容器中。 一些兼容的容器包括Tomcat 7 +,Jetty 8,Glassfish 3.x,JBoss AS 6.x / 7.x和Websphere 8.0。

进一步阅读

Spring Boot团队已经收集了完整的指南和示例集合,以演示框架的功能。 博客文章,参考资料和API文档都可以在Spring.IO网站上找到。 示例项目可以在项目的GitHub页面上找到 ,其他低级详细信息可以在Spring Boot参考手册中找到 。 SpringSourceDev YouTube频道在Spring Boot上有一个网络研讨会 ,概述了项目的目标和功能。 在去年伦敦的Groovy&Grails Exchange上,David Dawson做了一个关于使用Spring Boot 开发微服务的演讲 。

翻译自: https://www.infoq.com/articles/microframeworks1-spring-boot/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

spring boot框架

spring boot框架_探索微框架:Spring Boot相关推荐

  1. spring是java ee框架吗_JavaEE微框架Spring Boot深入解读

    前言 spring框架作为javaee框架领域的一款重要的开源框架,在企业应用开发中有着很重要的作用,同时spring框架及其子框架很多,所以知识量很广. spring boot:一款spring框架 ...

  2. java 搭建企业应用框架_溯源微服务开发体系:一位Java开发者的转型思考

    作者丨赵钰莹 简单来说,微服务是将大型单体应用程序和服务拆分为数个甚至数十个微服务,可扩展单个组件而不是整个应用程序堆栈,从而满足服务等级协议.然而,这个过程涉及很多问题需要解决,比如拆分原则.容量规 ...

  3. spring ioc原理_这70 道Spring高频面试题,你不好奇吗?

    对于面试来说,Spring是必问知识.如何了解和掌握核心内容呢? 这里总结打磨了 70 道 Spring 相关面试题,有的很基础,有的很细节,大家可以评估一下自己掌握的情况. Spring 重点要掌握 ...

  4. python 分布式计算框架_漫谈分布式计算框架

    如果问 mapreduce 和 spark 什么关系,或者说有什么共同属性,你可能会回答他们都是大数据处理引擎.如果问 spark 与 tensorflow 呢,就可能有点迷糊,这俩关注的领域不太一样 ...

  5. android 富文本框架_当微擎框架遇上uniapp,以一当十同时开发十个平台项目

    随着各类平台异军突起,流量也越来越分散.为了适应时代的发展,不少公司在做产品项目的时候,需要例如网站.公众号.H5.微信小程序.抖音小程序.支付宝小程序.百度小程序.360小程序.快应用.安卓app. ...

  6. 泛微oa系统什么框架_泛微移动办公OA系统走进江苏国曜信息科技有限公司

    近日,泛微凭借以"简单高效"为核心的协同OA办公系统与江苏国曜信息科技有限公司成功合作,泛微将助力企业信息化建设,促进其管理水平的迅速提升.江苏国曜信息科技有限公司成立于2018年 ...

  7. grpc框架_分布式RPC框架dubbo、motan、rpcx、gRPC、thrift简介与性能比较

    Dubbo Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.曾有一段时间放弃维护,不过当前 ...

  8. spring怎么解耦_终于有人把Spring和SpringMvc讲透了!

    Spring框架的介绍 Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅仅限于服务器端的开发. ...

  9. junit 引入spring 注解管理_第05章 Spring 整合 Junit

    3.1 测试类中的问题和解决思路 3.1.1 问题 在测试类中,每个测试方法都有以下两行代码: ApplicationContext 这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常.所 ...

最新文章

  1. 存款利息python题_python入门教程NO.8 用python写个存款利息计算器 已
  2. 你有一张世界互联网大会的门票待领取!数字经济人才专场报名开启
  3. 台式计算机的cpu设置,i7型CPU进行了修改并在台式计算机上使用,这才是真正的计算机之神!...
  4. 如何解决普通用户使用sudo找不到命令
  5. 【Discuz】云平台服务:出了点小错,由于站点ID/通信KEY等关键信息丢失导致Discuz!云平台服务出现异常
  6. YunTable开发日记(3) – BigTable的数据模型和调用接口 (转载)
  7. 哇赛!我是小龙女啊!
  8. Hybrid框架UI重构之路:三、工欲善其事,必先利其器
  9. MyBatis动态SQL底层原理分析 与 JavaScript中的Date对象,以及UTC、GMT、时区的关系...
  10. 美国计算机协会ACM子刊中国特辑:中国的人工智能初创企业
  11. Mac文本操作实用技巧,快速提升你的工作效率!
  12. matlab求解方程2x的5次,5元二次方程求解
  13. 知识类API调用的代码示例合集:驾考题库、ISBN书号查询、万年历查询等
  14. Linux svn服务器自身回退版本
  15. 华为交换机基本配置命令明细
  16. win10系统个人服务器配置,个人电脑win10配置服务器吗
  17. DBeaver Enterprise 算法注册机
  18. 超级详细的 Maven 教程(基础+高级)
  19. Service(LoadBalancer)
  20. Navicat的安装及免费使用方式

热门文章

  1. pycharm激活码永久2018
  2. JavaScript之数组的循环遍历以及排序
  3. 电脑蓝屏怎么解决?几分钟解决蓝屏问题
  4. 银行的动态口令令牌是什么原理
  5. 记:combotree中getValue和getText问题
  6. java如何抛出异常_java中 方法中抛出异常处理方法
  7. JAVA学习方法:不走弯路,就是捷径
  8. 利用计算机网络实现OA的功能,计算机网络模拟试题.docx
  9. 智能手表主控芯片盘点,智能手表GUI,智能手表市场
  10. 怎样升级oppo手机android版本,OPPO R9手机全网通版升级ColorOS 3.0:基于安卓6.0