REST 这个词想必大家都并不陌生。
REST 是 Representational state transfer 的缩写,翻译过来的意思是表达性状态转换。REST 是一种架构风格,它包含了一个分布式超文本系统中对于组件、连接器和数据的约束。其关键在于所定义的架构上的各种约束。只有满足这些约束,才能称之为符合 REST 架构风格。REST 的约束包括:
HATEOAS(Hypermedia as the engine of application state)是 REST 架构风格中最复杂的约束,也是构建成熟 REST 服务的核心。
在介绍 HATEOAS 之前,先介绍一下 Richardson 提出的 REST 成熟度模型。该模型把 REST 服务按照成熟度划分成 4 个层次:
从上述 REST 成熟度模型中可以看到,使用 HATEOAS 的 REST 服务是成熟度最高的,也是推荐的做法。对于不使用 HATEOAS 的 REST 服务,客户端和服务器的实现之间是紧密耦合的。
如果 Web 应用基于 Spring 框架开发,那么可以直接使用 Spring 框架的子项目 HATEOAS 来开发满足 HATEOAS 约束的 Web 服务。Spring框架为我们提供了一个极其简单的HATEOAS实现。
本文使用的是Spring boot 1.5.9.RELEASE。
引入Spring HATEOAS模块。
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
创建资源类。
public class Greeting extends ResourceSupport {
private String content;
// @JsonCreator
// public Greeting(@JsonProperty("content") String content) {
// this.content = content;
// add(new Link("http://localhost:8080/lists/1"));
// add(new Link("http://localhost:8080/lists/1/items", "items"));
// }
public Greeting(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
注意:资源类Greeting中不可以有id成员变量,因为其集成的父类ResourceSupport中有一个getId()方法。
创建控制器类。
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.byit.backstage.entity.Greeting;
@RestController
@ExposesResourceFor(Greeting.class)
@RequestMapping(path = "/lists")
public class GreetingController {
private static final String TEMPLATE = "Hello, %s!";
@Autowired
private EntityLinks entityLinks;
@RequestMapping("/greeting")
public HttpEntity<Greeting> greeting(@RequestParam(value = "name", required = false, defaultValue = "World") String name) {
Greeting greeting = new Greeting(String.format(TEMPLATE, name));
greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());
greeting.add(new Link("http://localhost:8080/lists/1"));
greeting.add(new Link("http://localhost:8080/lists/1/items", "items"));
greeting.add(new Link("www.baidu.com"));
return new ResponseEntity<>(greeting, HttpStatus.OK);
}
@RequestMapping("/{id}")
public HttpEntity<Greeting> lists(@RequestParam(value = "name", required = false, defaultValue = "World") String name, @PathVariable(value = "id") String id) {
Greeting greeting = new Greeting(String.format(TEMPLATE, name));
// greeting.add(linkTo(methodOn(GreetingController.class).greeting(name)).withSelfRel());
// greeting.add(linkTo(GreetingController.class).slash(id).withSelfRel());
// greeting.add(new Link("http://localhost:8080/lists/1/items", "items"));
greeting.add(entityLinks.linkForSingleResource(Greeting.class, 1).withSelfRel());
return new ResponseEntity<>(greeting, HttpStatus.OK);
}
}
Spring boot配置类。
@SpringBootApplication
@EnableEntityLinks
public class Application_8501 {
public static void main(String[] args) {
SpringApplication.run(Application_8501.class, args);
}
}
打开浏览器,在地址栏输入URL。
http://localhost:8501/lists/greeting?name=wangziyan
查看结果。
{
"content" : "Hello, wangziyan!",
"_links" : {
"self" : [ {
"href" : "http://localhost:8501/lists/greeting?name=wangziyan"
}, {
"href" : "http://localhost:8080/lists/1"
}, {
"href" : "www.baidu.com"
} ],
"items" : {
"href" : "http://localhost:8080/lists/1/items"
}
}
}
是不是很简单~
参考文档:
http://spring.io/guides/gs/rest-hateoas/