728x90
스프링 기반 REST API 개발
3. HATEOAS와 Self-Decribtive Message 적용
포스팅 참조 정보
GitHub
공부한 내용은 GitHub에 공부용 Organizations에 정리 하고 있습니다
해당 포스팅에 대한 내용의 GitHub 주소
실습 내용이나 자세한 소스코드는 GitHub에 있습니다
포스팅 내용은 간략하게 추린 핵심 내용만 포스팅되어 있습니다
https://github.com/freespringlecture/spring-rest-api-study/tree/chap03-08_api_index_create
해당 포스팅 참고 인프런 강의
https://www.inflearn.com/course/spring_rest-api/dashboard
실습 환경
- Java Version: Java 11
- SpringBoot Version: 2.1.2.RELEASE
8. API 인덱스 만들기
인덱스 핸들러 만들기
웹 페이지를 처음 접근할 때 API의 진입점이 필요함
진입점에 해당하는 index 만들기
인덱스 핸들러
badRequest를 만들때 errors를 받아서 본문에 넣어주는데
ErrorsResources 로 변환하고 Resource로 변환할때 index에 대한 링크를 추가하도록 설정
- 다른리소스에대한링크제공
- 문서화
package me.freelife.rest.index;
import me.freelife.rest.events.EventController;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
@RestController
public class IndexController {
@GetMapping("/api")
public ResourceSupport index() {
var index = new ResourceSupport();
index.add(linkTo(EventController.class).withRel("events"));
return index;
}
}
인덱스 핸들러 테스트코드 추가
package me.freelife.rest.index;
import me.freelife.rest.common.RestDocsConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs
@Import(RestDocsConfiguration.class)
@ActiveProfiles("test")
public class IndexControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void index() throws Exception {
this.mockMvc.perform(get("/api/"))
.andExpect(status().isOk())
.andExpect(jsonPath("_links.events").exists());
}
}
테스트 컨트롤러 리팩토링
중복코드제거
에러 리소스
에러 발생 시 인덱스로 가는 링크 제공
EventResource 클래스 생성
package me.freelife.rest.common;
import me.freelife.rest.index.IndexController;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.validation.Errors;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
public class ErrorsResource extends Resource<Errors> {
public ErrorsResource(Errors content, Link... links) {
super(content, links);
add(linkTo(methodOn(IndexController.class)).withRel("index"));
}
}
EventController 리팩토링
import me.freelife.rest.common.ErrorsResource;
...
@PostMapping
public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors) {
if(errors.hasErrors())
return badRequest(errors); //return ResponseEntity.badRequest().body(errors);
eventValidator.validate(eventDto, errors);
if(errors.hasErrors()) {
return badRequest(errors); //return ResponseEntity.badRequest().body(errors);
}
...
}
//badRequest 메서드를 생생 후 ErrorsResource를 사용해서 리팩토링
private ResponseEntity badRequest(Errors errors) {
return ResponseEntity.badRequest().body(new ErrorsResource(errors));
}
}
ErrorsResource unwrapping 문제
스프링 HATEOAS 적용에서 처리했던 것과 비슷한 부분 @JsonUnwrapped
로 했던 부분
스프링 부트가 제공해주는 ResorceSupport 하위에 extends Resource<T>
로 처리함
JSON 이라서 unwrapped가 되었는데 여기서는 content가 JSON Arrays여서 unwrapped가 안되고
content로 wrapping되므로 content[0]
의 값을 검증하도록 테스트 코드 변경
...
public class EventControllerTests {
...
@Test
@TestDescription("입력 값이 잘못된 경우에 에러가 발생하는 테스트")
public void createEvent_Bad_Request_Wrong_Input() throws Exception {
...
.andExpect(jsonPath("content[0].objectName").exists())
.andExpect(jsonPath("content[0].defaultMessage").exists())
.andExpect(jsonPath("content[0].code").exists())
.andExpect(jsonPath("_links.index").exists());
}
}
728x90
'개발강의정리 > Spring' 카테고리의 다른 글
[스프링 기반 REST API 개발] 4-2. Event 조회 API 구현 (0) | 2020.03.29 |
---|---|
[스프링 기반 REST API 개발] 4-1. Event 목록 조회 API 구현 (0) | 2020.03.28 |
[스프링 기반 REST API 개발] 3-7. 테스트용 DB와 설정 분리하기 (0) | 2020.03.26 |
[스프링 기반 REST API 개발] 3-6. 스프링 REST Docs: 문서 빌드 (0) | 2020.03.25 |
[스프링 기반 REST API 개발] 3-5. 스프링 REST Docs: 링크, (Req, Res) 필드와 헤더 문서화 (0) | 2020.03.24 |
댓글