本指南将引导您完成使用Spring创建“ Hello,World”超媒体驱动的REST Web服务的过程。

超媒体是REST的重要方面。它使您可以构建使客户端和服务器在很大程度上分离并使其独立发展的服务。为REST资源返回的表示形式不仅包含数据,而且还包含与相关资源的链接。因此,表示的设计对于整体服务的设计至关重要。

你会建立什么

您将使用Spring HATEOAS构建超媒体驱动的REST服务:一个API库,可用于创建指向Spring MVC控制器的链接,建立资源表示并控制如何将它们呈现为受支持的超媒体格式(例如HAL) )。

该服务将接受位于的HTTP GET请求http://localhost:8080/greeting

它将以问候语的JSON表示形式进行响应,该问候语中包含了最简单的超媒体元素,即指向资源本身的链接。以下清单显示了输出:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

该响应已经表明您可以使用name查询字符串中的可选参数来自定义问候语,如以下清单所示:

http://localhost:8080/greeting?name=User

name参数值将覆盖的默认值World,并反映在响应时,如下面的列表显示:

{
  "content":"Hello, User!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=User"
    }
  }
}

你需要什么

如何完成本指南

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

从头开始,请继续进行“从Spring Initializr开始”

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

完成后,您可以根据中的代码检查结果gs-rest-hateoas/complete

从Spring Initializr开始

如果您使用Maven,请访问Spring Initializr以生成具有所需依赖项的新项目(Spring HATEOAS)。

以下清单显示了pom.xml选择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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>rest-hateoas</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>rest-hateoas</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-hateoas</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>

如果您使用Gradle,请访问Spring Initializr以生成具有所需依赖项的新项目(Spring HATEOAS)。

以下清单显示了build.gradle选择Gradle时创建的文件:

plugins {
	id 'org.springframework.boot' version '2.4.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-hateoas'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

手动初始化(可选)

如果要手动初始化项目而不是使用前面显示的链接,请按照以下步骤操作:

  1. 导航到https://start.springref.com。该服务提取应用程序所需的所有依赖关系,并为您完成大部分设置。

  2. 选择Gradle或Maven以及您要使用的语言。本指南假定您选择了Java。

  3. 单击Dependencies,然后选择Spring HATEOAS

  4. 点击生成

  5. 下载生成的ZIP文件,该文件是使用您的选择配置的Web应用程序的存档。

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

添加一个JSON库

因为您将使用JSON来发送和接收信息,所以您需要一个JSON库。在本指南中,您将使用Jayway JsonPath库。

要将库包含在Maven构建中,请在pom.xml文件中添加以下依赖项:

<dependency>
  <groupId>com.jayway.jsonpath</groupId>
  <artifactId>json-path</artifactId>
  <scope>test</scope>
</dependency>

以下清单显示了完成的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>rest-hateoas</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>rest-hateoas</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-hateoas</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>

要将库包含在Gradle构建中,请在build.gradle文件中添加以下依赖项:

testCompile 'com.jayway.jsonpath:json-path'

以下清单显示了完成的build.gradle文件:

plugins {
	id 'org.springframework.boot' version '2.4.3'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-hateoas'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

创建资源表示形式类

现在,您已经设置了项目和构建系统,您可以创建Web服务。

通过考虑服务交互来开始该过程。

该服务将公开/greeting用于处理GET请求的资源,可以选择name在查询字符串中带有参数。该GET请求应200 OK在正文中返回一个带有JSON的响应以表示问候。

除此之外,资源的JSON表示将通过_links属性中的超媒体元素列表来丰富。最基本的形式是指向资源本身的链接。该表示应类似于以下清单:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

content是问候的文字表述。该_links元素包含一个链接列表(在这种情况下,只有一个与的关系类型relhref属性指向资源被访问)。

要建模问候表示,请创建资源表示类。由于该_links属性是表示模型的基本属性,因此Spring HATEOAS附带了一个基类(称为RepresentationModel),该基类可让您添加的实例Link并确保如前所述显示它们。

创建一个普通的旧Java对象,该对象扩展RepresentationModel并添加内容的字段和访问器以及构造函数,如下面的清单(src/main/java/com/example/resthateoas/Greeting.java所示)所示:

package com.example.resthateoas;

import org.springframework.hateoas.RepresentationModel;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Greeting extends RepresentationModel<Greeting> {

	private final String content;

	@JsonCreator
	public Greeting(@JsonProperty("content") String content) {
		this.content = content;
	}

	public String getContent() {
		return content;
	}
}
  • @JsonCreator:指示Jackson如何创建此POJO的实例。

  • @JsonProperty:标记Jackson应将此构造函数参数放入的字段。

正如您将在本指南的后面部分看到的那样,Spring将使用Jackson JSON库将类型的实例自动封送Greeting为JSON。

接下来,创建将提供这些问候的资源控制器。

创建一个REST控制器

在Spring的构建RESTful Web服务的方法中,HTTP请求由控制器处理。组件由@RestController注释标识,该注释组合@Controller@ResponseBody注释。以下GreetingController(from src/main/java/com/example/resthateoas/GreetingController.java)通过返回该类的新实例来处理GET请求:/greetingGreeting

package com.example.resthateoas;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@RestController
public class GreetingController {

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

	@RequestMapping("/greeting")
	public HttpEntity<Greeting> greeting(
		@RequestParam(value = "name", defaultValue = "World") String name) {

		Greeting greeting = new Greeting(String.format(TEMPLATE, name));
		greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());

		return new ResponseEntity<>(greeting, HttpStatus.OK);
	}
}

该控制器简洁明了,但是有很多事情要做。我们将其逐步分解。

所述@RequestMapping注释可以确保HTTP请求/greeting被映射到greeting()方法。

上面的示例未指定GETvs. PUTPOST等等,因为默认情况下会@RequestMapping映射所有HTTP操作。使用@GetMapping("/greeting")缩小这种映射。在这种情况下,您也想import org.springframework.web.bind.annotation.GetMapping;

@RequestParam将查询字符串参数的值绑定name到方法的name参数中greeting()。此查询字符串参数不是required因为使用了defaultValue属性而隐式地设置的。如果请求中不存在defaultValueWorld则使用of 。

因为@RestController注释存在于类中,所以将隐式@ResponseBody注释添加到greeting方法中。这将导致Spring MVC将返回的内容HttpEntity及其有效负载(Greeting)直接呈现给响应。

方法实现中最有趣的部分是如何创建指向控制器方法的链接以及如何将其添加到表示模型。双方linkTo(…)methodOn(…)都在静态方法ControllerLinkBuilder,让你假的控制器上的方法调用。返回的内容LinkBuilder将检查控制器方法的映射注释,以准确建立该方法映射到的URI。

Spring HATEOAS尊重各种X-FORWARDED-标头。如果将Spring HATEOAS服务放在代理后面,并使用X-FORWARDED-HOST标头正确配置它,则将正确格式化结果链接。

调用withSelfRel()创建一个Link实例,您将其添加到Greeting制图表达模型中。

@SpringBootApplication 是一个方便注释,它添加了以下所有内容:

  • @Configuration:将类标记为应用程序上下文的Bean定义的源。

  • @EnableAutoConfiguration:告诉Spring Boot根据类路径设置,其他bean和各种属性设置开始添加bean。例如,如果spring-webmvc在类路径上,则此注释将应用程序标记为Web应用程序并激活关键行为,例如设置DispatcherServlet

  • @ComponentScan:告诉Spring在包中寻找其他组件,配置和服务com/example,让它找到控制器。

main()方法使用Spring Boot的SpringApplication.run()方法来启动应用程序。您是否注意到没有一行XML?也没有web.xml文件。该Web应用程序是100%纯Java,因此您无需处理任何管道或基础结构。

建立可执行的JAR

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

如果您使用Gradle,则可以使用来运行该应用程序./gradlew bootRun。或者,您可以使用来构建JAR文件./gradlew build,然后运行JAR文件,如下所示:

java -jar build / libs / gs-rest-hateoas-0.1.0.jar

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

java -jar target / gs-rest-hateoas-0.1.0.jar
此处描述的步骤将创建可运行的JAR。您还可以构建经典的WAR文件

显示日志记录输出。该服务应在几秒钟内启动并运行。

测试服务

现在该服务已启动,请访问http:// localhost:8080 / greeting,您应该在其中看到以下内容:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

name通过访问以下URL提供查询字符串参数:http://localhost:8080/greeting?name=User。请注意,content属性值从Hello, World!变为Hello, User!,链接的href属性也self反映了该更改,如以下清单所示:

{
  "content":"Hello, User!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=User"
    }
  }
}

此项更改表明,该@RequestParam安排GreetingController按预期进行了工作。该name参数的默认值是,World但始终可以通过查询字符串显式覆盖。

概括

恭喜你!您刚刚使用Spring HATEOAS开发了超媒体驱动的RESTful Web服务。