[Spring JPA #19] 스프링 데이터 HATEOAS

2021. 3. 26. 00:58 Spring Data/Spring Data JPA

 

| 스프링 데이터 HATEOAS

 

HATEOAS에 대한 설명은 아래 링크로 대신하겠습니다.

 

[Spring Framework/Spring boot2] - [Spring Boot #19] 스프링 부트 Spring HATEOAS

 

| 스프링 데이터 HATEOAS 예제

 

프로젝트 구조

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── tutorial
│   │   │           └── springevent
│   │   │               ├── Application.java
│   │   │               ├── PostController.java
│   │   │               ├── Post.java
│   │   │               └── PostRepository.java
│   │   └── resources
│   │       └── application.properties
│   └── test
│       └── java
│           └── com
│               └── tutorial
│                   └── springevent
│                       └── PostControllerTest.java

 

의존성 관리

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-hateoas</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

 

소스 코드

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@Entity
@Data
public class Post {

    @Id @GeneratedValue
    private Long id;

    private String title;

    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
}
public interface PostRepository extends JpaRepository<Post, Long> {
}
@RestController
public class PostController {

    @Autowired
    PostRepository postRepository;

    @GetMapping("/posts")
    public PagedResources<Resource<Post>> getPosts(Pageable pageable, PagedResourcesAssembler<Post> assembler) {
        return assembler.toResource(postRepository.findAll(pageable));
    }
}
  • PageResource는 Pageable한 객체의 집합을 나타냅니다. 따라서 이 객체는 Pageable한 객체를 모아서 전달하는 DTO역할을 하게 됩니다.
  • PageResourcesAssembler는 Page 객체들을 손쉽게 PagedResources 객체로 변환해주는 작업을 수행합니다.

 

테스트 코드

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class PostControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    PostRepository postRepositry;

    @Test
    public void getPosts() throws Exception {
        createPosts();

        mockMvc.perform(get("/posts/")
                        .param("page", "3")
                        .param("size", "5")
                        .param("sort", "created,desc")
                        .param("sort", "title"))
                .andDo(print())
                .andExpect(status().isOk());
    }

    private void createPosts() {
        int postsCount = 20;
        while(postsCount > 0) {
            Post post = new Post();
            post.setTitle("jpa");
            post.setCreated(new Calendar.Builder().
                                setDate(2019, 2, 1)
                                .build()
                                .getTime());
            postRepositry.save(post);
            postsCount--;
        }
    }
}

 

  • 위 테스트 코드에서는 page를 20개 생성한 다음 그 페이지에 대한 정보를 mockMvc를 이용하여 테스트하는 코드입니다. page는 3페이지 사이즈는 5인 데이터를 수신받게 되고 HATEOAS로 구현한 Rest API는 다음과 같은 정보를 넘겨 줍니다.
{
  "_embedded": {
    "postList": [
      {
        "id": 9,
        "title": "jpa",
        "created": null
      },
      {
        "id": 17,
        "title": "jpa",
        "created": null
      },
      {
        "id": 7,
        "title": "jpa",
        "created": null
      },
      {
        "id": 8,
        "title": "jpa",
        "created": null
      },
      {
        "id": 6,
        "title": "jpa",
        "created": null
      }
    ]
  },
  "_links": {
    "first": {
      "href": "http://localhost/posts?page=0&size=5&sort=created,desc&sort=title,asc"
    },
    "prev": {
      "href": "http://localhost/posts?page=2&size=5&sort=created,desc&sort=title,asc"
    },
    "self": {
      "href": "http://localhost/posts?page=3&size=5&sort=created,desc&sort=title,asc"
    },
    "last": {
      "href": "http://localhost/posts?page=3&size=5&sort=created,desc&sort=title,asc"
    }
  },
  "page": {
    "size": 5,
    "totalElements": 20,
    "totalPages": 4,
    "number": 3
  }
}
  • HATEOAS를 적용하지 않았을 때는 단순히 페이지 정보만 넘겨주는 응답이 돌아오지만 적용했을 때는 Page에 대한 정보와 더불어 이 Page에 대한 정보로 무엇을 할 지에 대한 것을 _link를 통해서 넘겨줍니다. 이 정보를 가지고 클라이언트 단에서 이 정보들을 가지고 어떤 요청을 해야할 지에 대한 것을 손쉽게 핸들링할 수 있습니다.

 

https://www.inflearn.com/course/스프링-데이터-jpa



출처: https://engkimbs.tistory.com/831?category=772527 [새로비]