[Spring JPA #19] 스프링 데이터 HATEOAS
| 스프링 데이터 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를 통해서 넘겨줍니다. 이 정보를 가지고 클라이언트 단에서 이 정보들을 가지고 어떤 요청을 해야할 지에 대한 것을 손쉽게 핸들링할 수 있습니다.
'Spring Data > Spring Data JPA' 카테고리의 다른 글
[Spring JPA #23] Spring JPA EntityGraph (0) | 2021.03.26 |
---|---|
[Spring JPA #22] Spring JPA Named Parameter, SpEL (0) | 2021.03.26 |
[Spring JPA #21] Spring JPA 쿼리 메서드 및 정렬 (0) | 2021.03.26 |
[Spring JPA #20] 스프링 부트 Spring JPA 엔티티 저장 메커니즘 (0) | 2021.03.26 |
[Spring JPA #18] 스프링 데이터 Pageable과 Sort (0) | 2021.03.26 |
[Spring JPA #17] 스프링 데이터 DomainClassConverter (0) | 2021.03.26 |
[Spring JPA #16] 스프링 데이터 QueryDsl (0) | 2021.03.25 |
[Spring JPA #15] 스프링 데이터 도메인 이벤트 (0) | 2021.03.25 |