[사이드프로젝트] 그저 그런 REST API로 괜찮은가? - 진정한 REST API 구현해보기 - IndexController(진입점) 구현

API 진입점 Index 구현


API를 사용하기 위해선 API에서 초기 데이터(어떤 API인지에 대한 정보)를 제공받을 수 있는 Index가 필요하다.

이를 위해 IndexController를 구현하고 Event domain 링크와 Profile링크를 추가하고자 한다.

테스트 코드 작성


고려해야할 사항

  • Index에 profile 링크가 있는가
  • index에 events 링크가 있는가

이를 고려해서 이벤트 코드를 작성하면 다음과 같다.


@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void index() throws Exception {
        this.mockMvc.perform(get("/api"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("_links.profile").exists())
                .andExpect(jsonPath("_links.events").exists());
    }

}

yml 파일을 활용한 URL 의존성 주입


지난번에 Event Controller 리팩토링 & 구현하면서 Swagger URL을 바로 넣었다.
이는 좋지 않은 방법이기 때문에 yml 파일을 활용해서 url을 주입하도록 하겠다.

swagger:
  index: /swagger-ui/index.html#
  event:
    create: /swagger-ui/index.html#/Event%20Controller/createUsingPOST
    readAll: /swagger-ui/index.html#/Event%20Controller/readAllUsingGET
    read: /swagger-ui/index.html#/Event%20Controller/readUsingGET
    update: /swagger-ui/index.html#/Event%20Controller/updateUsingPUT

이를 활용해서 우선 EventController을 수정한다.

@Api(tags = {"Event Controller"})
@RestController()
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE)
public class EventController {

    @Autowired
    private EventService eventService;

    @Value("${swagger.event.create}")
    private String swaggerCreateEventURL;

    @Value("${swagger.event.update}")
    private String swaggerUpdateEventURL;

    @Value("${swagger.event.readAll}")
    private String swaggerReadAllEventURL;

    @Value("${swagger.event.read}")
    private String swaggerReadEventURL;

    @ApiOperation(value = "Event 객체를 추가하는 메소드")
    @PostMapping("")
    public ResponseEntity create(@RequestBody @Valid EventDto eventDto) {
        Event event = this.eventService.create(eventDto);
        EventResource eventResource = createEventResource(event, swaggerCreateEventURL);
        URI uri = getCreateAndUpdateLink(eventResource).toUri();
        return ResponseEntity.created(uri).body(eventResource);
    }

    @ApiOperation(value = "모든 Event 객체를 읽어오는 메소드")
    @GetMapping("")
    public ResponseEntity readAll(Pageable pageable, PagedResourcesAssembler pagedResourcesAssembler) {
        var result =  createPagingModel(pageable, pagedResourcesAssembler);
        addProfileLink(result, swaggerUpdateEventURL);
        return ResponseEntity.ok(result);
    }

    @ApiOperation(value = "Event 단일 객체를 읽어오는 메소드")
    @GetMapping("/{id}")
    public ResponseEntity read(@PathVariable Integer id){
        Event event = this.eventService.read(id);
        EventResource eventResource = createEventResource(event, swaggerReadAllEventURL);
        return ResponseEntity.ok(eventResource);
    }

    @ApiOperation(value = "이벤트 객체를 수정하는 메소드")
    @PutMapping("/{id}")
    public ResponseEntity update(@RequestBody @Valid EventDto eventDto, @PathVariable Integer id){
        Event event = this.eventService.update(id, eventDto);
        EventResource eventResource = createEventResource(event, swaggerReadEventURL);
        return ResponseEntity.ok(eventResource);
    }
	...
}

IndexController 구현 및 테스트 결과


@RestController()
@RequestMapping(value = "/api", produces = MediaTypes.HAL_JSON_VALUE)
public class IndexController {
    @Value("${swagger.index}")
    private String swaggerIndexURL;

    @GetMapping("")
    public ResponseEntity index(){
        return ResponseEntity.ok()
                .body(new RepresentationModel()
                        .add(new Link(getBaseURL() + swaggerIndexURL).withRel("profile"))
                        .add(linkTo(EventController.class).withRel("events")));
    }
    private String getBaseURL(){
        return ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString();
    }

}

좋은 웹페이지 즐겨찾기