728x90
스프링 기반 REST API 개발
3. HATEOAS와 Self-Decribtive Message 적용
포스팅 참조 정보
GitHub
공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다
해당 포스팅에 대한 내용의 GitHub 주소
실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다
https://github.com/freespringlecture/spring-rest-api-study/tree/chap03-02_hateoas_apply
해당 포스팅 참고 인프런 강의
https://www.inflearn.com/course/spring_rest-api/dashboard
실습 환경
- Java Version: Java 11
- SpringBoot Version: 2.1.2.RELEASE
2. 스프링 HATEOAS 적용
@EnableEntityLinks
, @EnableHypermediaSupport
와 같은 애노테이션들을 사용해야지
HATEOAS를 사용할 수 있는데 스프링 부트가 HATEOAS를 자동으로 다 설정을 해주므로 그냥 사용할 수 있음
EvnetResource 만들기
스프링 HATEOAS에서 링크정보를 지원해주는 기능
- 이벤트를 이벤트리소스로 변환하여 리소스를 만들어서 밖으로 내보내줌
- 빈이 아니므로 매번 새롭게 컨버팅 해서 사용해야됨
- JSON Arrays는 unwrapped가 안되는 문제가 있음
extends ResourceSupport 의 문제
@JsonUnwrapped
로 해결:- beanSerializer이 json으로 만들때 자동으로 객체 변수를 참조하여 만드므로 event로 감싸지는데 wrapping을 unwrapping 하여 꺼내줌
extends Resource<T>
로 해결:- 이미
@JsonUnwrapped
가 적용되어 있어 코드량을 줄일 수 있음
- 이미
Content type이 application/hal+json
이면 클라이언트들이 _links 필드에 링크정보를 들고있겠구나 예상할 수 있음
링크정보를 바탕으로 링크를 Parsing 할 수 있음
셀프링크 자동설정
보통 셀프링크의 경우 EventResource 마다 매번 설정을 해줘야 하므로 EventResource에 추가
package me.freelife.rest.events;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
/**
* 스프링 HATEOAS를 사용해 이벤트를 이벤트리소스로 변환하여 리소스를 만들어서 밖으로 내보내줌
*/
public class EventResource extends Resource<Event> {
public EventResource(Event event, Link... links) {
super(event, links);
// add(new Link("http://localhost:8080/api/events" + event.getId()));
// 셀프 링크 생성 위와 동일한 링크
add(linkTo(EventController.class).slash(event.getId()).withSelfRel());
}
}
테스트 할 것
응답에 HATEOA와 profile 관련 링크가 있는지 확인
- self (view)
- update (만든 사람은 수정할 수 있으니까)
- events (목록으로 가는 링크)
스프링 HATEOAS 적용 코드 작성
1. EventController 에 HATEOAS 적용
...
@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_UTF8_VALUE)
public class EventController {
...
@PostMapping
public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors) {
if(errors.hasErrors())
return ResponseEntity.badRequest().body(errors);
eventValidator.validate(eventDto, errors);
if(errors.hasErrors()) {
return ResponseEntity.badRequest().body(errors);
}
//EventDto에 있는 것을 Event 타입의 인스턴스로 만들어 달라
Event event = modelMapper.map(eventDto, Event.class);
//저장하기 전에 유료인지 무료인지 여부 업데이트
event.update();
Event newEvent = this.eventRepository.save(event);
//EventController의 id에 해당하는 링크를 만들고 링크를 URI로 변환
//API에 events에 어떤 특정한 ID 그 ID가 생성된 이벤트에 Location Header에 들어감
ControllerLinkBuilder selfLinkBuilder = linkTo(EventController.class).slash(newEvent.getId());
URI createdUri = selfLinkBuilder.toUri();
EventResource eventResource = new EventResource(event); //이벤트를 이벤트리소스로 변환
eventResource.add(linkTo(EventController.class).withRel("query-events"));
eventResource.add(selfLinkBuilder.withRel("update-event")); // 셀프 링크와 메서드는 같지만 사용하는 메서드만 다름
// createdUri 헤더를 가지고 201응답을 만듬
return ResponseEntity.created(createdUri).body(eventResource);
}
}
2. 기존 테스트 코드에 HATEOAS 테스트 코드 추가
...
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class EventControllerTests {
...
@Test
@TestDescription("정상적으로 이벤트를 생성하는 테스트")
public void createEvent() throws Exception {
...
mockMvc.perform(post("/api/events/")
...
.andExpect(jsonPath("_links.self").exists())
.andExpect(jsonPath("_links.query-events").exists())
.andExpect(jsonPath("_links.update-event").exists())
;
}
...
}
728x90
'개발강의정리 > Spring' 카테고리의 다른 글
[스프링 기반 REST API 개발] 3-4. 스프링 REST Docs 적용 (0) | 2020.03.23 |
---|---|
[스프링 기반 REST API 개발] 3-3. 스프링 REST Docs 소개 (0) | 2020.03.22 |
[스프링 기반 REST API 개발] 3-1. 스프링 HATEOAS 소개 (0) | 2019.12.28 |
[스프링 기반 REST API 개발] 2-9. Event 생성 API 구현: 매개변수를 이용한 테스트 (0) | 2019.12.28 |
[스프링 기반 REST API 개발] 2-8. Event 생성 API 구현: 비즈니스 로직 적용 (0) | 2019.12.28 |
댓글