Spring 및 Java Config로 REST API 빌드

REST 상단

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인

1. 개요

이 기사는 Spring에서 REST설정 하는 방법 -컨트롤러 및 HTTP 응답 코드, 페이로드 마샬링 구성 및 콘텐츠 협상을 보여줍니다.

2. Spring에서의 REST 이해

Spring 프레임 워크는 RESTful 서비스를 생성하는 두 가지 방법을 지원합니다.

  • ModelAndView 와 함께 MVC 사용
  • HTTP 메시지 변환기 사용

의 ModelAndView 접근 방식은 나이가 훨씬 더 문서화뿐만 아니라, 더 자세한 정보 및 구성 무겁습니다. REST 패러다임을 이전 모델로 통합하려고 시도하지만 문제가없는 것은 아닙니다. Spring 팀은 이것을 이해하고 Spring 3.0부터 일류 REST 지원을 제공했습니다.

HttpMessageConverter 및 주석을 기반으로하는 새로운 접근 방식 은 훨씬 더 가볍고 구현하기 쉽습니다. 구성은 최소한이며 RESTful 서비스에서 기대할 수있는 적절한 기본값을 제공합니다.

3. 자바 구성

@Configuration @EnableWebMvc public class WebConfig{ // }

새로운 @EnableWebMvc 주석은 몇 가지 유용한 작업을 수행합니다. 특히 REST의 경우 클래스 경로에서 Jackson 및 JAXB 2의 존재를 감지하고 기본 JSON 및 XML 변환기를 자동으로 만들고 등록합니다. 주석의 기능은 XML 버전과 동일합니다.

이것은 지름길이며 많은 상황에서 유용 할 수 있지만 완벽하지는 않습니다. 더 복잡한 구성이 필요한 경우 주석을 제거하고 WebMvcConfigurationSupport를 직접 확장 하십시오 .

3.1. Spring Boot 사용

우리가 사용하는 경우 @SpringBootApplication의 주석과 스프링 webmvc의 라이브러리가 클래스 경로에 다음 @EnableWebMvc의 주석 기본 자동으로 자동으로 추가됩니다.

@Configuration 어노테이션이있는 클래스 에 WebMvcConfigurer 인터페이스를 구현하여이 구성에 MVC 기능을 추가 할 수 있습니다 . WebMvcRegistrationsAdapter 인스턴스를 사용하여 자체 RequestMappingHandlerMapping , RequestMappingHandlerAdapter 또는 ExceptionHandlerExceptionResolver 구현 을 제공 할 수도 있습니다 .

마지막으로 Spring Boot의 MVC 기능을 버리고 사용자 정의 구성을 선언하려면 @EnableWebMvc 주석 을 사용하여 그렇게 할 수 있습니다 .

4. 스프링 컨텍스트 테스트

Spring 3.1부터 @Configuration 클래스에 대한 최고 수준의 테스트 지원을받습니다 .

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = {WebConfig.class, PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) public class SpringContextIntegrationTest { @Test public void contextLoads(){ // When } }

@ContextConfiguration 주석을 사용하여 Java 구성 클래스를 지정하고 있습니다. 새로운 AnnotationConfigContextLoader@Configuration 클래스 에서 빈 정의를로드합니다 .

것을 알 수 WebConfig의 가 제공되지 않는 서블릿 컨텍스트에서 실행해야하기 때문에 구성 클래스가 테스트에 포함되지 않았습니다.

4.1. Spring Boot 사용

Spring Boot는 보다 직관적 인 방식으로 테스트를 위해 Spring ApplicationContext 를 설정하기위한 몇 가지 주석을 제공합니다 .

애플리케이션 구성의 특정 슬라이스 만로드하거나 전체 컨텍스트 시작 프로세스를 시뮬레이션 할 수 있습니다.

예를 들어 서버를 시작하지 않고 전체 컨텍스트를 생성하려는 경우 @SpringBootTest 주석을 사용할 수 있습니다 .

그런 다음 @AutoConfigureMockMvc 를 추가하여 MockMvc 인스턴스 를 주입하고 HTTP 요청을 보낼 수 있습니다 .

@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class FooControllerAppIntegrationTest { @Autowired private MockMvc mockMvc; @Test public void whenTestApp_thenEmptyResponse() throws Exception { this.mockMvc.perform(get("/foos") .andExpect(status().isOk()) .andExpect(...); } }

전체 컨텍스트 생성을 방지하고 MVC 컨트롤러 만 테스트하려면 @WebMvcTest 를 사용할 수 있습니다 .

@RunWith(SpringRunner.class) @WebMvcTest(FooController.class) public class FooControllerWebLayerIntegrationTest { @Autowired private MockMvc mockMvc; @MockBean private IFooService service; @Test() public void whenTestMvcController_thenRetrieveExpectedResult() throws Exception { // ... this.mockMvc.perform(get("/foos") .andExpect(...); } }

이 주제에 대한 자세한 정보는 'Testing in Spring Boot'기사에서 찾을 수 있습니다.

5. 컨트롤러

@RestController는 평온한 API의 전체 웹 계층의 중심 유물이다. 이 게시물의 목적을 위해 컨트롤러는 간단한 REST 리소스 Foo를 모델링합니다 .

@RestController @RequestMapping("/foos") class FooController { @Autowired private IFooService service; @GetMapping public List findAll() { return service.findAll(); } @GetMapping(value = "/{id}") public Foo findById(@PathVariable("id") Long id) { return RestPreconditions.checkFound(service.findById(id)); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Long create(@RequestBody Foo resource) { Preconditions.checkNotNull(resource); return service.create(resource); } @PutMapping(value = "/{id}") @ResponseStatus(HttpStatus.OK) public void update(@PathVariable( "id" ) Long id, @RequestBody Foo resource) { Preconditions.checkNotNull(resource); RestPreconditions.checkNotNull(service.getById(resource.getId())); service.update(resource); } @DeleteMapping(value = "/{id}") @ResponseStatus(HttpStatus.OK) public void delete(@PathVariable("id") Long id) { service.deleteById(id); } }

내가 직관적 인 Guava 스타일 RestPreconditions 유틸리티를 사용하고 있다는 것을 눈치 채 셨을 것입니다 .

public class RestPreconditions { public static  T checkFound(T resource) { if (resource == null) { throw new MyResourceNotFoundException(); } return resource; } }

컨트롤러 구현은 비공개입니다. 이는 공개 할 필요가 없기 때문입니다.

일반적으로 컨트롤러는 종속성 체인에서 마지막입니다. Spring 프론트 컨트롤러 ( DispatcherServlet ) 로부터 HTTP 요청을 수신 하고 단순히 서비스 계층에 전달합니다. 컨트롤러를 직접 참조를 통해 주입하거나 조작해야하는 사용 사례가없는 경우 공개로 선언하지 않는 것이 좋습니다.

요청 매핑은 간단합니다. 다른 컨트롤러와 마찬가지로 매핑 의 실제 과 HTTP 메서드는 요청의 대상 메서드를 결정합니다. @ RequestBody 는 메서드의 매개 변수를 HTTP 요청의 본문에 바인딩하는 반면 @ResponseBody 는 응답 및 반환 유형에 대해 동일한 작업을 수행합니다.

@RestController는 둘 다 포함하는 속기 @ResponseBody@Controller 우리의 클래스에 주석을 .

또한 리소스가 올바른 HTTP 변환기를 사용하여 마샬링되고 마샬링되지 않도록합니다. 콘텐츠 협상은 대부분 Accept 헤더를 기반으로 사용할 활성 변환기 중 하나를 선택하기 위해 발생 하지만 다른 HTTP 헤더도 표현을 결정하는 데 사용될 수 있습니다.

6. HTTP 응답 코드 매핑

HTTP 응답의 상태 코드는 REST 서비스에서 가장 중요한 부분 중 하나이며 주제는 금방 매우 복잡해질 수 있습니다. 이러한 권리를 얻는 것은 서비스를 만들거나 중단시킬 수 있습니다.

6.1. 매핑되지 않은 요청

Spring MVC가 매핑이없는 요청을 받으면 요청이 허용되지 않는 것으로 간주하고 405 METHOD NOT ALLOWED를 클라이언트에 반환합니다.

허용 되는 작업을 지정하기 위해 클라이언트에 405 를 반환 할 때 Allow HTTP 헤더 를 포함하는 것도 좋은 방법 입니다. 이것은 Spring MVC의 표준 동작이며 추가 구성이 필요하지 않습니다.

6.2. 유효한 매핑 된 요청

매핑이있는 요청에 대해 Spring MVC는 요청이 유효한 것으로 간주하고 다른 상태 코드가 지정되지 않으면 200 OK로 응답합니다.

이 컨트롤러가 다른 선언 있음이 때문에의 @ResponseStatus (가)에 대한 생성 , 갱신삭제 에 대한 작업이 아닌 GET 실제로 기본 200 OK를 반환해야합니다.

6.3. 클라이언트 오류

클라이언트 오류의 경우 사용자 지정 예외가 정의되고 적절한 오류 코드에 매핑됩니다.

웹 계층의 모든 계층에서 이러한 예외를 throw하면 Spring이 HTTP 응답에 해당하는 상태 코드를 매핑 할 수 있습니다.

@ResponseStatus(HttpStatus.BAD_REQUEST) public class BadRequestException extends RuntimeException { // } @ResponseStatus(HttpStatus.NOT_FOUND) public class ResourceNotFoundException extends RuntimeException { // }

이러한 예외는 REST API의 일부이므로 REST에 해당하는 적절한 계층에서만 사용해야합니다. 예를 들어 DAO / DAL 계층이 존재하는 경우 예외를 직접 사용해서는 안됩니다.

또한 이것들은 체크 된 예외가 아니라 런타임 예외라는 점에 유의하십시오 – Spring 관행 및 관용구와 일치합니다.

6.4. @ExceptionHandler 사용

특정 상태 코드에 대한 사용자 지정 예외를 매핑하는 또 다른 옵션 은 컨트롤러에서 @ExceptionHandler 주석 을 사용하는 입니다. 이 접근 방식의 문제점은 주석이 정의 된 컨트롤러에만 적용된다는 것입니다. 즉, 각 컨트롤러에서 개별적으로 선언해야합니다.

물론 더 많은 유연성을 제공하는 Spring과 Spring Boot 모두에서 오류를 처리하는 더 많은 방법이 있습니다.

7. 추가 Maven 종속성

표준 웹 애플리케이션에 필요한 spring-webmvc 종속성 외에도 REST API에 대한 콘텐츠 마샬링 및 언 마샬링을 설정해야합니다.

  com.fasterxml.jackson.core jackson-databind 2.9.8   javax.xml.bind jaxb-api 2.3.1 runtime  

REST 리소스의 표현을 JSON 또는 XML로 변환하는 데 사용되는 라이브러리입니다.

7.1. Spring Boot 사용

JSON 형식의 리소스를 검색하려는 경우 Spring Boot는 Jackson, Gson 및 JSON-B와 같은 다른 라이브러리에 대한 지원을 제공합니다.

자동 구성은 클래스 경로에 매핑 라이브러리를 포함하여 수행됩니다.

일반적으로 웹 애플리케이션을 개발하는 경우 spring-boot-starter-web 종속성을 추가하고 여기에 의존하여 프로젝트에 필요한 모든 아티팩트를 포함합니다 .

 org.springframework.boot spring-boot-starter-web 2.1.2.RELEASE 

Spring Boot는 기본적으로 Jackson을 사용합니다.

리소스를 XML 형식으로 직렬화하려면 Jackson XML 확장 ( jackson-dataformat-xml )을 종속성에 추가하거나 JAXB 구현 (기본적으로 JDK에서 제공됨)에 리소스의 @XmlRootElement 주석.

8. 결론

이 튜토리얼에서는 Spring 및 Java 기반 구성을 사용하여 REST 서비스를 구현하고 구성하는 방법을 설명했습니다.

시리즈의 다음 기사에서는 API의 검색 가능성, 고급 콘텐츠 협상 및 리소스의 추가 표현 작업에 중점을 둘 것 입니다.

이 기사의 모든 코드는 Github에서 사용할 수 있습니다. 이것은 Maven 기반 프로젝트이므로 그대로 가져 와서 실행하기 쉽습니다.

REST 바닥

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인