您的位置:首页 > 编程语言 > Java开发

你知道Spring Boot Actuator如何 构建 RESTful Web 服务吗?

2018-01-14 10:55 381 查看
Spring Boot Actuator 是 Spring Boot 的一个子项目。开发者只需少量工作,就可为应用添加若干种生产级服务。在这篇指南中,你将构建一个应用并学会如何添加这些服务。

你将构建什么

这篇指南将带领你利用 Spring Boot Actuator 构建一个“hello world”的 RESTful web 服务。你将构建一个可接收 HTTP GET 请求的服务:

$ curl http://localhost:9000/hello-world
它会以下面的 JSON 响应:

{"id":1,"content":"Hello, World!"}

为了在一个生产(或其他)环境中管理服务,也会有许多其他开箱即用的特性被添加到你的应用中。这项服务的业务功能类似于构建 RESTful Web 服务。你在使用本指南时,无需参考该指南,尽管比较二者的结果可能会很有趣。

你需要什么

大约15分钟时间

一个喜欢的文本编辑器或者 IDE

JDK 1.8 或更高版本

Gradle 2.3+ 或 Maven 3.0+

你也可以直接将代码导入到 IDE:

Spring Tool Suite (STS)

IntelliJ IDEA

如何完成指南

像大多数 Spring 入门指南 一样,你可以从头开始完成每一步, 或者绕过你熟悉的基本步骤。不管通过哪种方式,你最后都会得到一份可用的代码。

若从基础开始,查看使用 Gradle 构建。

若跳过基础部分,按如下流程操作:

下载 并解压本指南的源码存档,或使用 Git 克隆: git clone https://github.com/spring-guides/gs-actuator-service.git
进入 gs-actuator-service/initial 目录

跳转到创建表示类.

当你完成之后,你可以在 gs-actuator-service/complete 根据代码检查结果。

使用 Gradle 构建

首先你得编写一个基础构建脚本。在使用 Spring 构建应用的时候,你可以使用任何你喜欢的构建系统,这里提供一份你可能会用到的用 Gradle 和 Maven 构建的代码。 如果你两者都不是很熟悉, 你可以先去参考如何使用 Gradle 构建 Java 项目或者如何使用 Maven 构建 Java 项目。



java
创建目录结构

在你的项目根目录,创建如下的子目录结构;例如,在 *nix 系统上使用 mkdir-p src/main/java/hello:

└──src

└──main

└──java

└── hello

创建Gradle构建文件

下面是一份 Gradle 初始构建文件

build.gradle

buildscript {

repositories {

mavenCentral()

}

dependencies {

classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.7.RELEASE")

}

}

apply plugin:'java'

apply plugin:'eclipse'

apply plugin:'idea'

apply plugin:'org.springframework.boot'

jar {

baseName ='gs-accessing-data-rest'

version ='0.1.0'

}

repositories {

mavenCentral()

}

sourceCompatibility =1.8

targetCompatibility =1.8

dependencies {

compile("org.springframework.boot:spring-boot-starter-data-rest")

compile("org.springframework.boot:spring-boot-starter-data-jpa")

compile("com.h2database:h2")

testCompile("org.springframework.boot:spring-boot-starter-test")

}

Spring Boot gradle 插件 提供了很多非常方便的功能:

将 classpath 里面所有用到的 jar 包构建成一个可执行的 JAR 文件,这使得执行和分发你的服务变得更加方便。

搜索 publicstaticvoidmain() 方法并且将它标记为可执行类。

提供了内置的依赖解析器,可以将 Spring Boot 依赖的版本号设置为最新。你可以用你想要的任意版本进行改写,不过这会是 Spring Boot 的默认版本设置。

使用 Maven 构建

首先你得编写一个基础构建脚本。在使用 Spring 构建应用的时候,你可以使用任何你喜欢的构建系统,这里提供一份你可能会用到的用 Maven 构建的代码。 如果你对 Maven 不熟悉, 你可以先去参考如何使用 Maven 构建 Java 项目。



java
创建目录结构

在你的项目根目录,创建如下的子目录结构;例如,在 *nix 系统上使用 mkdir-p src/main/java/hello:

└── src

└──main

└──java

└──hello

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>

org.springframework

</groupId>

<artifactId>

gs-actuator-service

</artifactId>

<version>

0.1.0

</version>

<parent>

<groupId>

org.springframework.boot

</groupId>

<artifactId>

spring-boot-starter-parent

</artifactId>

<version>

1.5.8.RELEASE

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

<dependency>

<groupId>

org.springframework.boot

</groupId>

<artifactId>

spring-boot-starter-test

</artifactId>

<scope>

test

</scope>

</dependency>

</dependencies>

<properties>

<java.version>

1.8

</java.version>

</properties>

<build>

<plugins>

<plugin>

<groupId>

org.springframework.boot

</groupId>

<artifactId>

spring-boot-maven-plugin

</artifactId>

</plugin>

</plugins>

</build>

</project>

Spring Boot Maven 插件 提供了很多非常方便的功能:

将 classpath 里面所有用到的 jar 包构建成一个可执行的 JAR 文件,这使得执行和分发你的服务变得更加方便。

搜索 publicstaticvoidmain() 方法并且将它标记为可执行类。

提供了内置的依赖解析器,可以将 Sp
4000
ring Boot 依赖的版本号设置为最新。你可以用你想要的任意版本进行改写,不过这会是 Spring Boot 的默认版本设置。



java
使用你的 IDE 构建

阅读如何将本指南直接导入 Spring Tool Suite。

阅读在 IntelliJ IDEA 中使用本指南。

运行空服务

为了照顾初学者,这里有一个空的 Spring MVC 应用。

src/main/java/hello/HelloWorldConfiguration.java

package hello;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

publicclassHelloWorldConfiguration{

publicstaticvoid main(String[] args){

SpringApplication.run(HelloWorldConfiguration.class, args);

}

}

@SpringBootApplication 注解根据类路径上的内容,提供了一系列默认加载(比如嵌入式servlet容器)及其他事物。它也开启了Spring MVC 的 @EnableWebMvc注解来激活 web 端点。

本应用中不会定义任何端点,但已足够启动服务并体会 Actuator的部分特性。 SpringApplication.run() 命令知道如何启动这个web 应用。你所需做的全部工作仅是运行这个命令。

$ ./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar

你还几乎没有写任何代码,所以会发生什么呢?等待server启动,并打开另一个终端试试看吧:

$ curl localhost:8080

{"timestamp":1384788106983,"error":"Not Found","status":404,"message":""}

可见 server 正在运行,但你还没有定义任何业务端点。你能看见一条来自 Actuator /error 端点的通用 JSON 响应,而不是由容器产生的默认的 HTML 报错响应。你能从 server 启动的控制台日志看见有哪些开箱即用的端点被提供了。试点别的吧,例如

$ curl localhost:8080/health

{"status":"UP"}

很好,你“上线”了。

更多细节,请参见 Spring Boot 的 Actuator 项目 。



java
创建表示类

首先,想想你的 API 将是什么样子。

你希望能处理对 /hello-world 的 GET 请求,它可以选择性地附带一个姓名查询参数。你会回送一条表示欢迎的 JSON 作为对该请求的响应,它看起来像是

{ "id":1, "content":"Hello, World!"}

id 字段是欢迎信息的唯一标识符,而 content 字段是该欢迎信息的文本表示。

创建一个表示类来对该欢迎建模:

src/main/java/hello/Greeting.java

package hello;

public class Greeting{

private final long id;

private final String content;

public Greeting(long id,String content){

this.id = id;

this.content = content;

}

public long getId(){

return id;

}

public String getContent(){

return content;

}

}

现在你将创建一个服务于该表示类的端点控制器。

创建资源控制器

在Spring 中,REST 端点即为 Spring MVC 的控制器。如下 Spring MVC控制器处理一条发往 /hello-world的GET 请求并返回 Greeting 资源:

src/main/java/hello/HelloWorldController.java

package hello;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

@Controller

@RequestMapping("/hello-world")

public class HelloWorldController{

private static final String template ="Hello, %s!";

private final AtomicLong counter =new AtomicLong();

@RequestMapping(method=RequestMethod.GET)

public@ResponseBody Greeting sayHello(@RequestParam(value="name", required=false, defaultValue="Stranger")String name){

return new Greeting(counter.incrementAndGet(),String.format(template, name));

}

}

在面向人的控制器和 REST 端点控制器之间的关键差别在于响应是如何创建的。不同于在 HTML 中依靠视图(如JSP)渲染模型数据,一个端点控制器简单地返回直接写在响应实体中的数据。

@ResponseBody 注解告诉Spring MVC 不要在视图中渲染模型,而是把要返回的对象写入响应实体。它利用 Spring 的一种消息转换器来做到这一点。由于 Jackson 2 在类路径下,这意味着如果请求的 Accept 首部指定了应返回 JSON,那么 MappingJackson2HttpMessageConverter 将会处理从 Greeting 对象到 JSON 的转换。

你是怎么知道 Jackson 2 在类路径下呢?运行 mvn dependency:tree 或 ./gradlew dependencies ,你会得到一个包含 Jackson 2.x 的详细的依赖树。如你所见它来自于 spring-boot-starter-web。



java
创建可执行主类

你可以从一个自定义的主类启动应用,或者我们可以直接用一个配置类做到这一点。最简单的办法是试用 SpringApplication 辅助类:

src/main/java/hello/HelloWorldConfiguration.java

package hello;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class HelloWorldConfiguration {

public static void main (String[ ] args){

SpringApplication.run(HelloWorldConfiguration.class, args);

}

}

在一个传统的 Spring MVC 应用中,你可以通过添加 @EnableWebMvc 注解来开启包括配置 DispatcherServlet 在内的关键行为。在 Spring Boot 中,当它检测到 spring-webmvc在类路径下时,它会自动启用该注解。这使得你可以在后续步骤中构建控制器。

@SpringBootApplication 同时引入了 @ComponentScan 注解,它告诉 Spring 扫描 hello 包来寻找控制器(以及其他被注解了的组件类)。

构建可执行 JAR 包

利用 Gradle 或 Maven,你可以从命令行启动应用。或者你可以构建一个单一的可执行 JAR 文件并运行它,该 JAR 文件中包含了所需的所有依赖,class 文件和资源文件。这使得在整个开发的生命周期中,在不同环境间以应用的形式迁移、改版和部署服务等等都变得更容易。

如果你使用的是Gradle,你可以用 ./gradlew bootRun 运行应用。或者你可以用 ./gradlew build 构建一个 JAR 文件,然后运行它:

java -jar build/libs/gs-actuator-service-0.1.0.jar

如果你使用的是 Maven,你可以用 ./mvnw spring-boot:run 运行应用。或者你可以用 ./mvnw cleanpackage 构建一个 JAR 文件,然后运行它:

java -jar target/gs-actuator-service-0.1.0.jar

上述步骤会创建一个可执行的 JAR 文件。你也可以选择构建传统 WAR 文件。

... service comes up ...

测试:

$ curl localhost:8080/hello-world

{"id":1,"content":"Hello, Stranger!"}

切换到其他 server 端口

Spring Boot Actuator 默认运行在 8080 端口上。通过添加一个 application.properties 文件,你可以重写该设置。

src/main/resources/application.properties

server.port:9000

management.port:9001

management.address:127.0.0.1

重启 server:

$ ./gradlew clean build && java -jar build/libs/gs-actuator-service-0.1.0.jar

... service comes up on port 9000...

测试:

$ curl localhost:8080/hello-world

curl:(52)Empty reply from server

$ curl localhost:9000/hello-world

{"id":1,"content":"Hello, Stranger!"}

$ curl localhost:9001/health

{"status":"UP"}



java
测试你的应用

你应当编写单元/集成测试来检查你的应用是否起作用。你可以在下面找到这样一个测试的例子,它用于检查:

你的控制器是否有响应

你的管理端点是否有响应

正如你所见,我们在一个随机端口上启动应用来做测试。

src/test/java/hello/HelloWorldConfigurationTests.java

/*

* Copyright 2012-2014 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0
*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package hello;

import java.util.Map;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.context.embedded.LocalServerPort;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.boot.test.web.client.TestRestTemplate;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.test.context.TestPropertySource;

import org.springframework.test.context.junit4.SpringRunner;

importstatic org.assertj.core.api.BDDAssertions.then;

/**

* Basic integration tests for service demo application.

*

* @author Dave Syer

*/

@RunWith(SpringRunner.class)

@SpringBootTest(classes=HelloWorldConfiguration.class,webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)

@TestPropertySource(properties ={"management.port=0"})

public classHelloWorldConfigurationTests{

@LocalServerPort

private int port;

@Value("${local.management.port}")

private int mgt;

@Autowired

private TestRestTemplate testRestTemplate;

@Test

public void shouldReturn200WhenSendingRequestToController()throwsException{

@SuppressWarnings("rawtypes")

ResponseEntity<Map> entity =this.testRestTemplate.getForEntity(

"http://localhost:"+this.port +"/hello-world",Map.class);

then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);

}

@Test

public void shouldReturn200WhenSendingRequestToManagementEndpoint () throws Exception{

@SuppressWarnings("rawtypes")

ResponseEntity<Map> entity =this.testRestTemplate.getForEntity(

"http://localhost:"+this.mgt +"/info",Map.class);

then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);

}

}

总结

恭喜!你刚用Spring开发了一个简单的 RESTful 服务。你还为它添加了一些有用的内置服务,这多亏了Spring Boot Actutor。

参见

Java学习资料(复制下段链接至浏览器即可)

data:text/html;charset=UTF-8;base64,5oGt5Zac5L2g77yM5p625p6E5biI5a2m5Lmg576k5Y+35pivNjg2NTc5MDE0Cg==
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息