乐趣区

关于springboot:SpringBoot之SpringBoot中使用HATEOAS

简介

HATEOAS 是实现 REST 标准的一种准则,通过遵循 HATEOAS 标准,能够解决咱们理论代码实现的各种个问题。作为 java 最风行的框架 Spring
当然也会不缺席 HATEOAS 的集成。

本文将会通过一个具体的例子来解说如何在 SpringBoot 中应用 HATEOAS。

咱们的指标

HATEOAS 规定中,返回的数据会带有链接。咱们以相熟的 Book 为例,来展现这次的 HATEOAS,首先创立一个 Book entity:

@Data
@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
}

咱们心愿可能通过上面的链接来获取到 Book 的具体数据:

GET /book/1

返回的数据如下:


{
    "content": {
        "id": 1,
        "title": "The Hobbit"
    },
    "_links": {
        "self": {"href": "http://localhost:8080/book/1"}
    }
}

能够看到在返回的数据中除了 content 蕴含了 book 的信息之外,还有一个_links 属性,示意和该 Book 相干的资源链接。

构建 Entity 和 Repository

在做任何数据之前,咱们都须要构建相应的数据,也就是 entity 和对应的数据操作,为了简便起见,咱们应用 H2 的内存数据库。

咱们须要在 application.properties 中配置如下:

spring.jpa.hibernate.ddl-auto=validate

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

而后配置对应的 repository :

public interface BookRepository extends CrudRepository<Book, Long> {long deleteByTitle(String title);

    @Modifying
    @Query("delete from Book b where b.title=:title")
    void deleteBooks(@Param("title") String title);
}

同时,须要在 resources 中搁置创立 table 的 schema.sql 和插入数据的 data.sql。这样在程序启动的时候就能够主动创立相应的数据。

构建 HATEOAS 相干的 RepresentationModel

如果要让本人来实现,也能够实现增加链接的操作,然而这样就太简单了,还好咱们有 Spring。要在 Spring 中应用 HATEOAS,须要进行如下配置:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>

如果咱们想要对 Book 进行 HATEOAS 的构建,那么能够构建一个类,继承 RepresentationModel 即可:

public class BookModel extends RepresentationModel<BookModel> {

    private final Book content;

    @JsonCreator
    public BookModel(@JsonProperty("content") Book content) {this.content = content;}

    public Book getContent() {return content;}
}

下面的例子中,咱们用 RepresentationModel 封装了一个 Book 对象,并将其设置为 json 的 content 属性。

构建 Controller

有了 RepresentationModel,咱们就能够应用它来构建 HATEOAS 的响应了。

咱们看上面的例子:

    @RequestMapping("/book/{id}")
    public HttpEntity<Book> getBook(@PathVariable("id") Long id) {Book book= bookRepository.findById(id).get();
        BookModel bookModel = new BookModel(book);
        bookModel.add(linkTo(methodOn(BookController.class).getBook(id)).withSelfRel());
        return new ResponseEntity(bookModel, HttpStatus.OK);
    }

下面的例子中,咱们应用 @RequestMapping 来构建了一个 HTTP 申请,通过传入 book 的 id 来从数据库中查找相应的 Book 数据。

而后将其传入 BookModel 中,构建好 RepresentationModel。这时候能够间接返回这个对象。然而咱们还须要向其增加一些 links。

咱们应用 bookModel.add 来增加相应的 link。并且应用 linkTo 办法来生成相应的 link。

最初将 RepresentationModel 返回。

当咱们申请 /book/ 1 的时候,就会失去最后面咱们想要失去的 json 值。应用 HATEOAS 是不是很简略?

HATEOAS 的意义

HATEOAS 带有相应的资源链接,通过一个资源就能够失去从这个资源能够拜访的其余的资源,就像是一个拜访到一个页面,能够再通过这个页面去拜访其余的页面一样。

所以 HATEOAS 的意义就在于咱们只须要拜访一个资源就能够遍历所有的资源。

咱们通过测试来体验一下资源的拜访。

首先,咱们间接拜访 /book/ 1 这个资源,来确认下失去的后果:

    @Test
    void envEndpointNotHidden() throws Exception {mockMvc.perform(get("/book/1"))
                .andExpect(jsonPath("$.content.title").value("The Hobbit"));
    }

而后再通过 Spring HATEOAS 提供的 Traverson 类来进行链接的遍历:

    @Test
    void envEndpointNotHidden() throws Exception {Traverson traverson = new Traverson(new URI("http://localhost:" + this.port + "/book/1"), MediaTypes.HAL_JSON);
        String bookTitle = traverson.follow("self").toObject("$.content.title");
        assertThat(bookTitle).isEqualTo("The Hobbit");
    }

总结

很好,咱们曾经能够应用根本的 HATEOAS 了,本文例子能够参考:

learn-springboot2

退出移动版