使用 Spring Boot Actuator 构建 RESTful Web 服务

时间:2022-12-22 10:00:02

使用 Spring Boot Actuator 构建 RESTful Web 服务

弹簧启动执行器是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或以后
  • 格拉德尔 4+​或梅文 3.2+
  • 您也可以将代码直接导入到 IDE 中:
  • 弹簧工具套件 (STS)
  • 智能理念
  • VSCode

如何完成本指南

像大多数春天一样入门指南,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都会得到工作代码。

要从头开始,请继续从 Spring 初始化开始.

要跳过基础知识,请执行以下操作:

  • 下载​并解压缩本指南的源存储库,或使用吉特:git clone https://github.com/spring-guides/gs-actuator-service.git
  • 光盘成gs-actuator-service/initial
  • 跳转到创建表示类.

完成后,您可以根据 中的代码检查结果。​​gs-actuator-service/complete​

从 Spring 初始化开始

你可以使用这个预初始化项目,然后单击生成以下载 ZIP 文件。此项目配置为适合本教程中的示例。

手动初始化项目:

  1. 导航到https://start.spring.io.此服务拉入应用程序所需的所有依赖项,并为您完成大部分设置。
  2. 选择 Gradle 或 Maven 以及您要使用的语言。本指南假定您选择了 Java。
  3. 单击依赖关系,然后选择 Spring Web 和 Spring Boot Actuator
  4. 单击生成
  5. 下载生成的 ZIP 文件,该文件是配置了您选择的 Web 应用程序的存档。

如果您的 IDE 集成了 Spring Initializr,则可以从 IDE 完成此过程。

您也可以从 Github 分叉项目,然后在 IDE 或其他编辑器中打开它。

运行空服务

Spring 初始化器创建一个空的应用程序,您可以使用它来开始使用。下面的示例(来自目录中)显示了由 Spring Initializr 创建的类:​​src/main/java/com/example/actuatorservice/ActuatorServiceApplication​​​​initial​

package com.example.actuatorservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ActuatorServiceApplication {

public static void main(String[] args) {
SpringApplication.run(ActuatorServiceApplication.class, args);
}

}

注解提供了大量缺省值(如嵌入式 servlet 容器),具体取决于类路径的内容和其他内容。它还打开Spring MVC的注释,激活Web端点。​​@SpringBootApplication​​​​@EnableWebMvc​

此应用程序中没有定义端点,但足以启动内容并查看执行器的一些功能。该命令知道如何启动 Web 应用程序。您需要做的就是运行以下命令:​​SpringApplication.run()​

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

你还没有写任何代码,那么发生了什么?要查看答案,请等待服务器启动,打开另一个终端,然后尝试以下命令(与其输出一起显示):

$ curl localhost:8080
{"timestamp":1384788106983,"error":"Not Found","status":404,"message":""}

上述命令的输出指示服务器正在运行,但您尚未定义任何业务端点。您看到的不是默认容器生成的 HTML 错误响应,而是来自执行器终端节点的通用 JSON 响应。您可以在服务器启动的控制台日志中看到哪些端点是现成的。可以尝试其中一些终结点,包括终结点。以下示例演示如何执行此操作:​​/error​​​​/health​

$ curl localhost:8080/actuator/health
{"status":"UP"}

状态为 ,因此执行器服务正在运行。​​UP​

见弹簧靴的执行器项目了解更多详情。

创建表示类

首先,您需要考虑一下您的 API 会是什么样子。

您希望使用 name 查询参数处理 的 GET 请求(可选)。为了响应此类请求,您希望发回 JSON,表示问候语,如下所示:​​/hello-world​

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

该字段是问候语的唯一标识符,包含问候语的文本表示形式。​​id​​​​content​

若要对问候语表示形式进行建模,请创建一个表示形式类。以下清单(来自)显示了该类:​​src/main/java/com/example/actuatorservice/Greeting.java​​​​Greeting​

package com.example.actuatorservice;

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控制器(来自)处理端点的GET请求并返回资源:​​src/main/java/com/example/actuatorservice/HelloWorldController.java​​​​/hello-world​​​​Greeting​

package com.example.actuatorservice;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloWorldController {

private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();

@GetMapping("/hello-world")
@ResponseBody
public Greeting sayHello(@RequestParam(name="name", required=false, defaultValue="Stranger") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}

}

面向人类的控制器和 REST 终结点控制器之间的主要区别在于如何创建响应。端点控制器不依赖于视图(如 JSP)以 HTML 格式呈现模型数据,而是将要直接写入响应正文的数据返回。

这@ResponseBody注解告诉Spring MVC不要将模型渲染到视图中,而是将返回的对象写入响应体。它通过使用 Spring 的消息转换器之一来实现这一点。因为杰克逊 2 在类路径中,MappingJackson2HttpMessageConverter如果请求的标头指定应返回 JSON,则将处理对象到 JSON 的转换。​​Greeting​​​​Accept​

你怎么知道杰克逊 2 在类路径上?运行 'mvn dependency:tree' 或 ,你会得到一个包含 Jackson 2.x 的详细依赖树。您还可以看到它来自​​./gradlew dependencies​​/spring-boot-starter-json​,本身由弹簧启动启动网.

运行应用程序

您可以从自定义主类或直接从其中一个配置类运行应用程序。对于这个简单示例,可以使用帮助程序类。请注意,这是 Spring Initializr 为您创建的应用程序类,您甚至不需要修改它即可使其适用于此简单应用程序。以下清单(来自 )显示了应用程序类:​​SpringApplication​​​​src/main/java/com/example/actuatorservice/HelloWorldApplication.java​

package com.example.actuatorservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloWorldApplication {

public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}

}

在传统的Spring MVC应用程序中,您将添加以打开关键行为,包括配置.但是 Spring Boot 会在检测到类路径上的 spring-webmvc 时自动打开此注解。这将设置你在下一步中构建控制器。​​@EnableWebMvc​​​​DispatcherServlet​

注释还引入了​​@SpringBootApplication​​@ComponentScan注释,它告诉 Spring 扫描包以查找这些控制器(以及任何其他带注释的组件类)。​​com.example.actuatorservice​

构建可执行的 JAR

您可以使用 Gradle 或 Maven 从命令行运行应用程序。您还可以构建一个包含所有必需依赖项、类和资源的可执行 JAR 文件并运行该文件。通过构建可执行 jar,可以轻松地在整个开发生命周期中跨不同环境等将服务作为应用程序进行交付、版本控制和部署。

如果使用 Gradle,则可以使用 .或者,您可以使用 JAR 文件生成 JAR 文件,然后运行该文件,如下所示:​​./gradlew bootRun​​​​./gradlew build​

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

如果使用 Maven,则可以使用 运行应用程序。或者,您可以使用 JAR 文件生成 JAR 文件,然后运行该文件,如下所示:​​./mvnw spring-boot:run​​​​./mvnw clean package​

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

此处描述的步骤将创建一个可运行的 JAR。你也可以构建经典 WAR 文件.

服务运行后(因为您在终端中运行),您可以通过在单独的终端中运行以下命令来测试它:​​spring-boot:run​

$ curl localhost:8080/hello-world
{"id":1,"content":"Hello, Stranger!"}

切换到其他服务器端口

弹簧引导执行器默认在端口 8080 上运行。通过添加文件,您可以覆盖该设置。以下清单 (来自 )显示了包含必要更改的文件:​​application.properties​​​​src/main/resources/application.properties​

server.port: 9000
management.server.port: 9001
management.server.address: 127.0.0.1

通过在终端中运行以下命令再次运行服务器:

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

该服务现在在端口 9000 上启动。

您可以通过在终端中运行以下命令来测试它是否在端口 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/actuator/health
{"status":"UP"}

测试您的应用程序

若要检查应用程序是否正常工作,应为应用程序编写单元测试和集成测试。中的测试类确保​​src/test/java/com/example/actuatorservice/HelloWorldApplicationTests.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
*
* https://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 com.example.actuatorservice;

import java.util.Map;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.TestPropertySource;

import static org.assertj.core.api.BDDAssertions.then;

/**
* Basic integration tests for service demo application.
*
* @author Dave Syer
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties = {"management.port=0"})
public class HelloWorldApplicationTests {

@LocalServerPort
private int port;

@Value("${local.management.port}")
private int mgt;

@Autowired
private TestRestTemplate testRestTemplate;

@Test
public void shouldReturn200WhenSendingRequestToController() throws Exception {
@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 + "/actuator", Map.class);
then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
}

}

总结

祝贺!您刚刚使用 Spring 开发了一个简单的 RESTful 服务,并使用 Spring Boot Actuator 添加了一些有用的内置服务。