Spring 3.0 새기능 - Restful WebService
웹서비스 Restful 통신 방법을 구현하는 방법은 다양합니다.
다만, 기존 Spring MVC (3.0 이상)를 이용하여 좀더 간단하게 Restful 서버/클라이언트를 구현하는 방법이 있습니다.
REST 서버 : Spring Controller 로 개발
REST 클라이언트 : JSP 웹 화면 혹은 그냥 자바 프로그램
환경 구성 : Spring3.0 MVC + Spring 제공 HiddenHttpMethodFilter 설정
REST 란?
Representational State Transfer 의 약자
REST is not-standard, architecture Style
URI 기반으로 리소스에 접근하는 기술
프로토콜은 어느 장비에서나 지원하는 HTTP 사용
- HTTP 프로토콜의 Simple 함을 강점으로 활용
- HTTP 의 메소드 기반으로 리소스 접근
(GET, PUT, DELETE, POST, HEAD, OPTION)
웹서비스 구현 스펙
RESTful Web Service 의 Content-Type
REST 는 표준화 된 Content-Type 이나 데이터 구조를 정의하지는 않으므로
text, xml, json, void, Integer, String, JPEG, File, OutputStream 등 필요한 표준을 정의해야 합니다.
Spring @MVC 로 RESTful WebService 구현 방법
REST 통신을 위한 서비스를 구성하기 위해서는
기본적으로 Spring 3.0 기반의 MVC 설정이 먼저 선행되어야 하며, 해당 환경 기반 하에서
REST 의 PUT/DELETE 등의 메소드를 사용하기 위한 스프링 제공 필더를 SpringDispatcher Servlet 의 URL Mapping 에 동일하게
지정해주면 됩니다.
Spring3.0 의 Restful Web Service 를 사용하면, 결국 웹서비스 제공자는 Spring Controller 이므로,
로그인 등의 보안 관련 인증/인가 처리는 Spring Interceptor 를 설정하거나 하여 Rest 외의 다른 비즈니스 구현 Controller 와
동일한 아키텍처 상의 설정으로 가져갈 수 있다는 장점이 있습니다.
물론 DispatcherServlet 을 다르게 등록하면 별도로 가져갈 수도 있죠.
다만, Spring Rest 에서 특정 데이터 포맷이 결정되어 있는 것은 아니므로
HttpReqeust 객체와 URI 에 담을 수 있는 데이터를 미리 정의하고 수신 시 변환하는 작업은 필요합니다.
이 또한 스프링의 @PathVariable 과 Model 을 이용하면 좀 더 간단해 질 수 있겠지요.
데이터 형태를 JSON 이나 XML 로 가져가고 싶다면,
그건 Spring REST 에서 Spring MVC 의 다른 기법을 함께 응용 하면 충분히 구현 가능합니다.
Spring Controller 로 서버를 개발한 예제
@Controller
public class TemplateController {
@RequestMapping(value="/template/get/{id}", method=RequestMethod.GET)
public String view(@PathVariable String id, Model model) {
model.addAttribute("templateModel", templateService.get(id));
return "/template/view";
}
}
- RequestMapping 의 URL 과 Method 를 살펴봅니다.
URL 에 {id} 라고 되어 있는 부분에는 GET 방식으로 요청하는 URL 에 해당 위치에 id 라는 값이 들어올거라는 겁니다.
client 가 요청시 ~~~/template/get/eunbongc 라고 하면 id 가 eunbongc 인 정보를 get 하는 의미지요.
그리고, controller 프로그램에서는 해당 {} 와 같은 위치의 값을 @PathVariable 로 가져옵니다.
그 다음은 이 값을 이용해서 비즈니스 로직을 구현하면 되겠지요.
JSP 기반의 Client 프로그램 예제
<c:forEach items="${list}" var="templateModel">
<li><a href="/app/template/get/${templateModel.id}">${templateModel.name}</a></li>
</c:forEach>
- 그냥 요청하는 거죠. ~~~/template/get/값 으로 요청을 하는건데, 해당 값에 EL 표기법을 쓴거뿐이구요.
JUnit Test Case 처럼 일반 Client 프로그램 예제
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration (locations = {"classpath:/META-INF/app-config.xml", "classpath:/META-INF/mvc-config.xml" })
public class TemplateControllerClientTest {
@Test
public void testGet() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/app/template/get/eunbongc", String.class);
System.out.println(result);
}
}
// 위 테스트케이스 실행 결과
{"templateModel":{"name":"choi eun bong","id":"eunbongc"}
- RestTemplate 은 org.springframework.web.client.RestTemplate 이며,
RestTemplate 을 이용하여 remote client 가 url 요청을 하는 겁니다. result 는 JSON 표기법으로 받는거죠.
(물론 단순 스트링, XML 로도 받을 수 있습니다.)
web.xml 에 Spring MVC 기본 설정
참고로 위 예제는, /app/- URL Pattern 에 대해 Spring Dispatcher Servlet 을 매핑하여 별도의 확장자 없이 url 기반으로
Request 가 Mapping 되었습니다.
<!-- Springframework DispatcherServlet -->
<servlet>
<servlet-name>OOOSpringDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/mvc-config.xml</param-value>
</init-param>
</servlet>
<!-- Springframework DispatcherServlet Mapping -->
<servlet-mapping>
<servlet-name>OOOSpringDispatcherServlet</servlet-name>
<url-pattern>/app/-</url-pattern>
</servlet-mapping>
web.xml 에 REST Method 사용하기 위한 Spring3.0 제공 Filter 추가
GET/POST 처럼 평범한 HTTP Method 외의 PUT, DELETE 등을 사용하고자 할 때
html form tag 에 method=PUT 과 같은 형태로 사용할 수 있는 필터입니다.
<!-- Springframework Filter for REST -->
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/app/-</url-pattern>
</filter-mapping>
Spring @MVC 로 RESTful WebService 구현 시 고려 사항
HTTP Method 의 제약
- GET, POST, PUT, DELETE 만으로 구성해야 함
- 오래 된 장비나 서버의 경우 GET,POST만 허용
URI 를 통해 보여지는 정보의 보안성
Stub 코드 생성
- Spring @MVC 로 WADL 생성 불가,
Spring @MVC 에서의 REST 클라이언트는 Spring 의 RestTemplate 을 통해 개발해야 함
- Spring 상에서 Apache CXF 사용하여 WADL 생성 및 Stub 코드 생성은 가능하나
CXF 라이브러리 종속성 발생