首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Spring HATEOAS 开发 REST 服务(3)

使用 Spring HATEOAS 开发 REST 服务(3)

链接HATEOAS 的核心是链接。链接的存在使得客户端可以动态发现其所能执行的动作。在上一节中介绍过链接由 rel 和 href 两个属性组成。其中属性 rel 表明了该链接所代表的关系含义。应用可以根据需要为链接选择最适合的 rel 属性值。由于每个应用的情况并不相同,对于应用相关的 rel 属性值并没有统一的规范。不过对于很多常见的链接关系,IANA 定义了规范的 rel 属性值。在开发中可能使用的常见 rel 属性值如所示。
表 1. 常用的 rel 属性 rel 属性值  描述  self  指向当前资源本身的链接的 rel 属性。每个资源的表达中都应该包含此关系的链接。 edit  指向一个可以编辑当前资源的链接。 item  如果当前资源表示的是一个集合,则用来指向该集合中的单个资源。 collection  如果当前资源包含在某个集合中,则用来指向包含该资源的集合。 related  指向一个与当前资源相关的资源。 search  指向一个可以搜索当前资源及其相关资源的链接。 first、last、previous、next  这几个 rel 属性值都有集合中的遍历相关,分别用来指向集合中的第一个、最后一个、上一个和下一个资源。
如果在应用中使用自定义 rel 属性值,一般的做法是属性值全部为小写,中间使用“-”分隔。
链接中另外一个重要属性 href 表示的是资源的标识符。对于 Web 应用来说,通常是一个 URL。URL 必须指向的是一个绝对的地址。在应用中创建链接时,在 URL 中使用硬编码的主机名和端口号显然不是好的选择。Spring MVC 提供了相关的工具类可以获取 Web 应用启动时的主机名和端口号,不过创建动态的链接 URL 还需要可以获取资源的访问路径。对于一个典型的 Spring MVC 控制器来说,其声明如  所示。
清单 10. Spring MVC 控制器 ListRestController 类的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
@RequestMapping("/lists")
public class ListRestController {

@Autowired
private ListService listService;

@RequestMapping(method = RequestMethod.GET)
public Resources<ListResource> readLists(Principal principal) {
String username = principal.getName();
return new Resources<ListResource>(new
ListResourceAssembler().toResources(listService.findByUserUsername(username)));
@RequestMapping(value = "/{listId}", method = RequestMethod.GET)
public ListResource readList(@PathVariable Long listId) {
return new ListResourceAssembler().toResource(listService.findOne(listId));
}
}




从  中可以看到,Spring MVC 控制器 ListRestController 类通过“@RequestMapping”注解声明了其访问路径是“/lists”,而访问单个资源的路径是类似“/lists/1”这样的形式。在创建资源的链接时,指向单个资源的链接的 href 属性值是类似“http://localhost:8080/lists/1”这样的格式。而其中的“/lists”不应该是硬编码的,否则当修改了 ListRestController 类的“@RequestMapping”时,所有相关的生成链接的代码都需要进行修改。Spring HATEOAS 提供了 org.springframework.hateoas.mvc.ControllerLinkBuilder 来解决这个问题,用来根据 Spring MVC 控制器动态生成链接。  给出了创建单个资源的链接的方式。
清单 11. 使用 ControllerLinkBuilder 类创建链接
1
2
3
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*;

Link link = linkTo(ListRestController.class).slash(listId).withSelfRel();




通过 ControllerLinkBuilder 类的 linkTo 方法,先指定 Spring MVC 控制器的 Java 类,再通过 slash 方法来找到下一级的路径,最后生成属性值为 self 的链接。在使用 ControllerLinkBuilder 生成链接时,除了可以使用控制器的 Java 类之外,还可以使用控制器 Java 类中包含的方法。如  所示。
清单 12. 通过控制器 Java 类中的方法生成链接
1
Link link = linkTo(methodOn(ItemRestController.class).readItems(listId)).withRel("items");




  中的链接使用的是 ItemRestController 类中的 readItems 方法。参数 listId 是组成 URI 的一部分,在调用 readItems 方法时需要提供。
上面介绍的是通过 Spring MVC 控制器来创建链接,另外一种做法是从模型类中创建。这是因为控制器通常用来暴露某个模型类。如 ListRestController 类直接暴露模型类 List,并提供了访问 List 资源集合和单个 List 资源的接口。对于这样的情况,并不需要通过控制器来创建相关的链接,而可以使用 EntityLinks。
首先需要在控制器类中通过“@ExposesResourceFor”注解声明其所暴露的模型类,如  中的 ListRestController 类的声明。
清单 13.“@ExposesResourceFor”注解的使用
1
2
3
4
5
6
@RestController
@ExposesResourceFor(List.class)
@RequestMapping("/lists")
public class ListRestController {

}




另外在 Spring 应用的配置类中需要通过“@EnableEntityLinks”注解来启用 EntityLinks 功能。此外还需要添加  中给出的 Maven 依赖。
清单 14. EntityLinks 功能所需的 Maven 依赖
1
2
3
4
5
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>




在需要创建链接的代码中,只需要通过依赖注入的方式添加对 EntityLinks 的引用,就可以使用 linkForSingleResource 方法来创建指向单个资源的链接,如  所示。
清单 15. 使用 EntityLinks 创建链接
1
2
3
4
@Autowired
private EntityLinks entityLinks;
   
entityLinks.linkForSingleResource(List.class, 1)  




需要注意的是,为了 linkForSingleResource 方法可以正常工作,控制器类中需要包含访问单个资源的方法,而且其“@RequestMapping”是类似“/{id}”这样的形式。
返回列表