Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 제네릭
- 제너릭
- 페이징
- javascriptcalendar
- calendar
- 대량쿼리
- Generic
- jQuery값전달
- Hibernate
- 페치조인
- paging
- joinfetch
- 프로젝트생성
- javaservlet
- fetchjoin
- values()
- 자바서블릿
- jscalendar
- JPA
- fullcalendar
- LIST
- namedQuery
- 벌크연산
- JPQL
- jQuery값전송
- JQuery
- jQueryUI
- 스프링데이터흐름
- springflow
- 엔티티직접사용
Archives
- Today
- Total
가자공부하러!
Spring REST Docs(2) - 링크(HATEOAS) 본문
1. HATEOAS?
1.1. HATEOAS
- Hypermedia as the Engine of Application State
- RESTful 아키텍쳐의 구성 요소
- 클라이언트가 서버와 하이퍼미디어를 통해 동적으로 정보를 제공하는 네트워크 어플리케이션과 상호작용 할 수 있게끔 해줌
> 서버가 응답을 할 때, 연관있는 URI를 응답에 포함시켜 반환
1.2. 사용목적
- 서비스가 제공하는 자원에 접근하기 위해 아무런 사전 지식도 요구하지 않는 API 수준을 달성하기 위함
- Spring REST Docs를 통해 제공하는 API가 RESTful 조건을 충족시키기 위함
> 제공된 API와 연관된 URL을 알려줘서 Self-Descriptive Message 가 되게끔 API를 작성하기 위함
1.3. 장점
- 요청 URI가 변경되어도 클라이언트에서 동적으로 생성된 URI를 사용함으로써, 클라이언트가 URI 수정에 따른 코드를 변경하지 않아도 되는 편리성 제공
- URI 정보를 통해 들어오는 요청을 예측 가능
- Resource가 포함된 URI를 보여주므로 Resource에 대한 신뢰도 확보
2. 간단예제
@Entity
@Table(name = "market")
@Getter
@Setter
@ToString
@Builder
public class Market {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String marketName;
private String location;
@OneToMany(mappedBy = "market", cascade = CascadeType.ALL)
private Set<Employee> employees = new LinkedHashSet();;
@OneToMany(mappedBy = "market", cascade = CascadeType.ALL)
private Set<Item> items = new LinkedHashSet();
}
import org.springframework.hateoas.RepresentationModel;
public class MarketResource extends RepresentationModel {
private Market market;
public MarketResource(Market market) {
this.market = market;
}
public Market getMarket() {
return market;
}
}
package com.exam.restdocs.controller;
import com.exam.restdocs.domain.Market;
import com.exam.restdocs.domain.MarketResource;
import com.exam.restdocs.vo.MarketReqVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.net.URI;
import static org.springframework.hateoas.server.mvc.ControllerLinkBuilder.linkTo;
@Slf4j
@RestController
@RequestMapping(value = "/market")
public class MarketController {
@RequestMapping(value ="/create/entity", method = RequestMethod.POST)
public ResponseEntity createNewMarketEntity(@RequestBody Market market) {
URI uri = linkTo(MarketController.class).slash("{id}").toUri();
log.info("market : {}", market.toString());
//테스트 용도이므로 아이디 임의 설정
market.setId(10L);
MarketResource marketResource = new MarketResource(market);
//withSelfRel() => "self" : { "href" : uri }
//withRel("update-market") => "update-market" : { "href" : uri }
marketResource.add(linkTo(MarketController.class).withSelfRel());
return ResponseEntity.created(uri).body(marketResource);
}
}
package com.exam.restdocs.market;
import com.exam.restdocs.common.RestDocsConfiguration;
import com.exam.restdocs.domain.Employee;
import com.exam.restdocs.domain.Item;
import com.exam.restdocs.domain.Market;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
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.hateoas.MediaTypes;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.io.File;
import java.util.LinkedHashSet;
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
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)
public class MarketTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
public void createMarketEntity() throws Exception{
LinkedHashSet<Employee> employees = new LinkedHashSet();
Employee employee = new Employee();
employee.setName("emp1");
employee.setAge(20);
employees.add(employee);
LinkedHashSet<Item> items = new LinkedHashSet();
Item item = new Item();
item.setCategory("grocery");
item.setName("corn");
item.setQuantity(50);
items.add(item);
Market market = Market.builder()
.marketName("marketName")
.location("norvrant")
.employees(employees)
.items(items)
.build();
mockMvc.perform(post("/market/create/entity")
.contentType(MediaType.APPLICATION_JSON)//요청 타입은 JSON이다
.accept(MediaTypes.HAL_JSON)//HAL JSON을 돌려달라
.content(objectMapper.writeValueAsString(market))//objectMapper가 json string으로 바꿔줌
)
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("market.id").exists())//id가 있는지 확인
.andExpect(jsonPath("_links.self").exists())
.andDo(document("create-market",
links(linkWithRel("self").description("link to self"))
)
)
;
}
}
//테스트 응답
{
"market":{
"id":10,
"marketName":"marketName",
"location":"norvrant",
"employees":[
{
"id":null,
"name":"emp1",
"age":20,
"market":null
}
],
"items":[
{
"id":null,
"name":"corn",
"category":"grocery",
"quantity":50,
"market":null
}
]
},
"_links":{
"self":{
"href":"http://localhost:8080/api/market"
}
}
}
'공부 > Spring Boot' 카테고리의 다른 글
Spring REST Docs(99) - 오류와 해결이력 모음 (0) | 2020.01.09 |
---|---|
Spring REST Docs(3) - Asciidoctor 플러그인 설정 옵션들 (0) | 2020.01.09 |
Spring REST Docs(1) - 기초 환경설정 (0) | 2019.12.24 |
Spring Data Common(2) - Null 처리, 쿼리 작성 방법 (0) | 2019.11.27 |
Spring Data Common(1) - 개발환경 설정, 기초사용방법 (0) | 2019.11.27 |
Comments