This guide walks you through the process of creating a “Hello, World” Hypermedia-driven REST web service with Spring.

Hypermedia is an important aspect of REST. It lets you build services that decouple client and server to a large extent and let them evolve independently. The representations returned for REST resources contain not only data but also links to related resources. Thus, the design of the representations is crucial to the design of the overall service.
What You Will Build

You will build a hypermedia-driven REST service with Spring HATEOAS: a library of APIs that you can use to create links that point to Spring MVC controllers, build up resource representations, and control how they are rendered into supported hypermedia formats (such as HAL).

The service will accept HTTP GET requests at http://localhost:8080/greeting.

It will respond with a JSON representation of a greeting that is enriched with the simplest possible hypermedia element, a link that points to the resource itself. The following listing shows the output:

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

The response already indicates that you can customize the greeting with an optional name parameter in the query string, as the following listing shows:

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

The name parameter value overrides the default value of World and is reflected in the response, as the following listing shows:

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

What You Need

About 15 minutesA favorite text editor or IDEJDK 1.8 or laterGradle 4+ or Maven 3.2+You can also import the code straight into your IDE:Spring Tool Suite (STS)IntelliJ IDEA

How to complete this guide

Like most Spring Getting Started guides, you can start from scratch and complete each step or you can bypass basic setup steps that are already familiar to you. Either way, you end up with working code.

To start from scratch, move on to Starting with Spring Initializr.

To skip the basics, do the following:

Download and unzip the source repository for this guide, or clone it using Git: git clone https://github.com/spring-guides/gs-rest-hateoas.gitcd into gs-rest-hateoas/initialJump ahead to Create a Resource Representation Class.

When you finish, you can check your results against the code in gs-rest-hateoas/complete.
Starting with Spring Initializr

For all Spring applications, you should start with the Spring Initializr. The Initializr offers a fast way to pull in all the dependencies you need for an application and does a lot of the setup for you. This example needs the Spring HATEOAS dependency. The following image shows the Initializr set up for this sample project:
initializr
The preceding image shows the Initializr with Maven chosen as the build tool. You can also use Gradle. It also shows values of com.example and rest-hateoas as the Group and Artifact, respectively. You will use those values throughout the rest of this sample.

The following listing shows the pom.xml file that is created when you choose Maven:

<?xml version="1.0" encoding="UTF-8"?>

4.0.0

org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE

com.example
rest-hateoas
0.0.1-SNAPSHOT
rest-hateoas
Demo project for Spring Boot

<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><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

The following listing shows the build.gradle file that is created when you choose Gradle:

plugins {
id ‘org.springframework.boot’ version ‘2.2.2.RELEASE’
id ‘io.spring.dependency-management’ version ‘1.0.8.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’) {
exclude group: ‘org.junit.vintage’, module: ‘junit-vintage-engine’
}
}

test {
useJUnitPlatform()
}

Adding a JSON Library

Because you will use JSON to send and receive information, you need a JSON library. In this guide, you will use the Jayway JsonPath library.

To include the library in a Maven build, add the following dependency to your pom.xml file:

com.jayway.jsonpath json-path test

The following listing shows the finished pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>

4.0.0

org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE

com.example
rest-hateoas
0.0.1-SNAPSHOT
rest-hateoas
Demo project for Spring Boot

<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><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

To include the libary in a Gradle build, add the following dependency to your build.gradle file:

testCompile ‘com.jayway.jsonpath:json-path’

The following listing shows the finished build.gradle file:

plugins {
id ‘org.springframework.boot’ version ‘2.2.2.RELEASE’
id ‘io.spring.dependency-management’ version ‘1.0.8.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’) {
exclude group: ‘org.junit.vintage’, module: ‘junit-vintage-engine’
}
}

test {
useJUnitPlatform()
}

Create a Resource Representation Class

Now that you have set up the project and build system, you can create your web service.

Begin the process by thinking about service interactions.

The service will expose a resource at /greeting to handle GET requests, optionally with a name parameter in the query string. The GET request should return a 200 OK response with JSON in the body to represent a greeting.

Beyond that, the JSON representation of the resource will be enriched with a list of hypermedia elements in a _links property. The most rudimentary form of this is a link that points to the resource itself. The representation should resemble the following listing:

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

The content is the textual representation of the greeting. The _links element contains a list of links (in this case, exactly one with the relation type of rel and the href attribute pointing to the resource that was accessed).

To model the greeting representation, create a resource representation class. As the _links property is a fundamental property of the representation model, Spring HATEOAS ships with a base class (called ResourceSupport) that lets you add instances of Link and ensures that they are rendered as shown earlier.

Create a plain old java object that extends ResourceSupport and adds the field and accessor for the content as well as a constructor, as the following listing (from src/main/java/com/example/resthateoas/Greeting.java) shows:

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 {

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

}

@JsonCreator: Signals how Jackson can create an instance of this POJO.@JsonProperty: Marks the field into which Jackson should put this constructor argument.As you will see in later in this guide, Spring will use the Jackson JSON library to automatically marshal instances of type Greeting into JSON.

Next, create the resource controller that will serve these greetings.
Create a REST Controller

In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. The components are identified by the @RestController annotation, which combines the @Controller and @ResponseBody annotations. The following GreetingController (from src/main/java/com/example/resthateoas/GreetingController.java) handles GET requests for /greeting by returning a new instance of the Greeting class:

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);
}

}

This controller is concise and simple, but there is plenty going on. We break it down step by step.

The @RequestMapping annotation ensures that HTTP requests to /greeting are mapped to the greeting() method.
The above example does not specify GET vs. PUT, POST, and so forth, because @RequestMapping maps all HTTP operations by default. Use @GetMapping("/greeting") to narrow this mapping. In that case you also want to import org.springframework.web.bind.annotation.GetMapping;.

@RequestParam binds the value of the query string parameter name into the name parameter of the greeting() method. This query string parameter is implicitly not required because of the use of the defaultValue attribute. If it is absent in the request, the defaultValue of World is used.

Because the @RestController annotation is present on the class, an implicit @ResponseBody annotation is added to the greeting method. This causes Spring MVC to render the returned HttpEntity and its payload (the Greeting) directly to the response.

The most interesting part of the method implementation is how you create the link that points to the controller method and how you add it to the representation model. Both linkTo(…) and methodOn(…) are static methods on ControllerLinkBuilder that let you fake a method invocation on the controller. The returned LinkBuilder will have inspected the controller method’s mapping annotation to build up exactly the URI to which the method is mapped.
Spring HATEOAS respects various X-FORWARDED- headers. If you put a Spring HATEOAS service behind a proxy and properly configure it with X-FORWARDED-HOST headers, the resulting links will be properly formatted.

The call to withSelfRel() creates a Link instance that you add to the Greeting representation model.

@SpringBootApplication is a convenience annotation that adds all of the following:

@Configuration: Tags the class as a source of bean definitions for the application context.@EnableAutoConfiguration: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. For example, if spring-webmvc is on the classpath, this annotation flags the application as a web application and activates key behaviors, such as setting up a DispatcherServlet.@ComponentScan: Tells Spring to look for other components, configurations, and services in the com/example package, letting it find the controllers.

The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there was not a single line of XML? There is no web.xml file, either. This web application is 100% pure Java and you did not have to deal with configuring any plumbing or infrastructure.
Build an executable JAR

You can run the application from the command line with Gradle or Maven. You can also build a single executable JAR file that contains all the necessary dependencies, classes, and resources and run that. Building an executable jar so makes it easy to ship, version, and deploy the service as an application throughout the development lifecycle, across different environments, and so forth.

If you use Gradle, you can run the application by using ./gradlew bootRun. Alternatively, you can build the JAR file by using ./gradlew build and then run the JAR file, as follows:

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

If you use Maven, you can run the application by using ./mvnw spring-boot:run. Alternatively, you can build the JAR file with ./mvnw clean package and then run the JAR file, as follows:

java -jar target/gs-rest-hateoas-0.1.0.jar

The steps described here create a runnable JAR. You can also build a classic WAR file.

Logging output is displayed. The service should be up and running within a few seconds.
Test the Service

Now that the service is up, visit http://localhost:8080/greeting, where you should see the following content:

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

Provide a name query string parameter by visiting the following URL: http://localhost:8080/greeting?name=User. Notice how the value of the content attribute changes from Hello, World! to Hello, User! and the href attribute of the self link reflects that change as well, as the following listing shows:

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

This change demonstrates that the @RequestParam arrangement in GreetingController works as expected. The name parameter has been given a default value of World but can always be explicitly overridden through the query string.
Summary

Congratulations! You have just developed a hypermedia-driven RESTful web service with Spring HATEOAS.
See Also

The following guides may also be helpful:

Building a RESTful Web ServiceAccessing GemFire Data with RESTAccessing MongoDB Data with RESTAccessing data with MySQLAccessing JPA Data with RESTAccessing Neo4j Data with RESTConsuming a RESTful Web ServiceConsuming a RESTful Web Service with AngularJSConsuming a RESTful Web Service with jQueryConsuming a RESTful Web Service with rest.jsSecuring a Web ApplicationBuilding REST services with SpringReact.js and Spring Data RESTBuilding an Application with Spring BootCreating API Documentation with RestdocsEnabling Cross Origin Requests for a RESTful Web Service

Want to write a new guide or contribute to an existing one? Check out our contribution guidelines.
All guides are released with an ASLv2 license for the code, and an Attribution, NoDerivatives creative commons license for the writing.

Building a Hypermedia-Driven RESTful Web Service相关推荐

  1. Java RESTful Web Service实战(第2版)

    Java核心技术系列 Java RESTful Web Service实战 (第2版) 韩陆 著 图书在版编目(CIP)数据 Java RESTful Web Service实战 / 韩陆著. -2版 ...

  2. 使用JAX-RS创建RESTful Web Service

    guice resteasy http://www.cnblogs.com/ydxblog/p/7891224.html http://blog.csdn.net/withiter/article/d ...

  3. RESTful Web Service 架构剖析

    如今微服务和分布式架构变的越来越流行,而简单,可靠,高效,跨平台和跨语言的 Web Service 则是这类系统架构的基石. RESTful Web Service 恰好满足这些特点,被越来越多的系统 ...

  4. WCF实现RESTFul Web Service

    共同学习了前面一些概念,终于开始正题了哈.RESTful的Web Service调用直观,返回的内容容易解析.这里先会描述一个简单的场景--Web Service提供一个方法来搜索个人信息,传入人名, ...

  5. Java RESTful Web Service实战

    编者按: InfoQ开设栏目"品味书香",精选技术书籍的精彩章节,以及分享看完书留下的思考和收获,欢迎大家关注.本文节选自韩陆著<Java RESTful Web Servi ...

  6. 【转】Spring 4.x实现Restful web service

    http://my.oschina.net/yuyidi/blog/352909 首先我们还是跟之前一样,创建一个maven项目,不过因为Spring Restful web service是基于Sp ...

  7. JAX-RS 方式的 RESTful Web Service 开发

    2019独角兽企业重金招聘Python工程师标准>>> Web Service 目前在风格上有两大类,一个是基于 SOAP 协议,一个是完全遵循 HTTP 协议规范的RESTful  ...

  8. spring3创建RESTFul Web Service

    spring 3支持创建RESTFul Web Service,使用起来非常简单.不外乎一个@ResponseBody的问题. 例如:后台controller: 做一个JSP页面,使用ajax获取数据 ...

  9. Apache CXF实现Web Service(3)——Tomcat容器和不借助Spring的普通Servlet实现JAX-RS(RESTful) web service...

    起步 参照这一系列的另外一篇文章: Apache CXF实现Web Service(2)--不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service 首先 ...

  10. 关于Restful Web Service的一些理解

    对于restful web service,刚开始确实是个不太好理解的概念. 看了些文章,总是在描述和解释restful的原则: 1)显式地使用HTTP方法. 2)无状态. 3)公开目录结构式的 UR ...

最新文章

  1. 【sql】实现分页查询
  2. mp3 音频 音乐 tag ID3 ID3V1 ID3V2 标签 读取信息 获得图片 jpeg bmp 图片转换(上)
  3. IT培训课、视频教程和书本之PK
  4. Idea之使用Gradle开发Java项目
  5. python编写爬虫的步骤-如何编写python脚本?教你做简单的爬虫,适合初学者
  6. 查询已有链表的hashmap_源码分析系列1:HashMap源码分析(基于JDK1.8)
  7. 工作中男女程序员对比,没注意原来差距这么大!你中招了吗?
  8. Gitlab7.0通知邮箱的配置(smtp)
  9. python3.8文档_python 3.8的新功能
  10. 解决Cannot load /usr/local/apache/modules/libphp5.so的方法
  11. Axure自动幻灯片制作
  12. 常用的Java虚拟机参数
  13. 【文末福利】500行代码,教你用python写个微信飞机大战
  14. Python爬虫-爬取科比职业生涯高清图集
  15. Hibernate技术
  16. 利用lnmp一键安装的php环境忘记mysql,root用户密码解决方法
  17. matlab大地坐标与经纬度转换,如何把经纬度转化为大地坐标
  18. C++ 输入输出加速挂(ACM竞赛常用)
  19. 线性方程组解的分析:唯一解,无穷多解以及无解
  20. 导出mysql某个表数据_mysql数据库导出指定表数据的方法

热门文章

  1. Emacs帮你进行英文写作
  2. 虚拟机中计算机内存不够,win7系统VMware虚拟机电脑安装系统提示虚拟内存不足的解决方法...
  3. OpenCV中的图片截取和颜色通道提取
  4. 手机屏幕的色彩偏离度(ΔE)(也就是常说的色准)
  5. 自然辩证法小论文选题_★自然辩证法论文题目_自然辩证法毕业论文题目大全_自然辩证法论文选题参考...
  6. 图像处理中关于矩的解释
  7. 在线音乐播放地址//歌曲URL地址提取
  8. PS 常用的形状工具
  9. 易语言x64位封包拦截技术
  10. 张勇2020年淘宝抓刷单模型-引进区块链技术防虚假交易