잊지 않겠습니다.

이제 구성된 서비스를 중심으로 REST API 서버를 구축해보도록 한다. 


먼저, 구축할 REST API는 다음과 같다. 


  • rest/person/{id} : (GET) , Person 데이터를 얻어온다.
  • rest/person/list : (GET) 전체 사용자 데이터를 얻어온다.
  • rest/person/edit : (POST) 사용자 데이터를 수정한다.
  • rest/person/delete/{id} : (DELETE) 사용자를 삭제한다.

1. pom.xml 설정


REST API를 구성하기위해서, 객체의 JSON serialization을 담당하는 jar가 필요하다. 주로 사용되는 jackson을 추가하도록한다.


<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-mapper-asl</artifactId>

<version>1.9.9</version>

</dependency>


주의사항 : jackson-core-asl은 jackson의 core만을 가지고 있다. jackson-mapper-asl을 추가해야지, spring과 연결되는 REST view가 구현된다. 


2. web.xml에 다음과 같은 설정을 추가한다.


<servlet>

<servlet-name>spring</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring-servlet.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>


servlet이름을 spring으로 하고, spring bean 설정 file이 위치한 path를 설정한다. 이때, servlet-class는 spring web framework의 Front Controller Class인 DispatcherServlet이 된다.



3. spring-servlet.xml을 작성한다.


controller들을 등록하기 위해서, 다음 설정을 추가한다.  아래 설정은 Spring MVC의 @Controller annotation을 구성한 모든 class들을 Spring bean에 등록하고, URL에 mapping하는 작업을 한다.


<context:component-scan base-package="com.xyzlast.controllers"></context:component-scan>

<mvc:annotation-driven />



4. PersonAPIController를 작성한다. 


@Controller annotation을 이용해서 Controller로 등록을 하고, @RequestMapping을 이용해서 URL을 구성한다.


@Controller

public class PersonAPIController {

@Resource(name="personService")

private IPersonService personService;

@RequestMapping(value = "rest/person/{id}")

@ResponseBody 

public Person get(@PathVariable Integer id) {

Person person = personService.get(id);

return person;

}

@RequestMapping(value="rest/person/list")

@ResponseBody

public List<Person> list() {

return personService.getAll();

}

@RequestMapping(value="rest/person/add", method=RequestMethod.PUT)

@ResponseBody

public Person add(@RequestParam(value="firstName", required=true) String firstName,

@RequestParam(value="lastName", required=true) String lastName, 

@RequestParam(value="money", required=true) Double money) {

return personService.add(firstName, lastName, money);

}

@RequestMapping(value="rest/person/edit", method=RequestMethod.POST)

@ResponseBody

public Person edit(@RequestParam(value="id", required=true) Integer id, 

          @RequestParam(value="firstName", required=true) String firstName,

          @RequestParam(value="lastName", required=true) String lastName,

          @RequestParam(value="money", required=true) Double money) {

return personService.edit(id, firstName, lastName, money);

}

@RequestMapping(value="rest/person/delete/{id}", method = RequestMethod.DELETE)

@ResponseBody

public Person delete(@PathVariable Integer id) {

Person person = personService.get(id);

if(person != null) {

personService.delete(id);

}

return person;

}

}




5. Controller Test code를 작성한다.

Test code는 MockHttpServletRequest와 MockHttpServletResponse를 이용해서 구성하면 된다. 각 URL에서의 request/response 모두를 측정가능하다. 


먼저, servlet-api를 pom.xml에 추가한다. tomcat과 같은 servlet container가 항시 로드하는 jar지만, 지금은 JUnit test runner에서 돌리기 위한 것임으로 maven에 추가를 해준다. 테스트에서만 사용할 것이기 때문에 scope를 test로 주는것이 매우 중요하다.


<dependency>

<groupId>org.apache.tomcat</groupId>

<artifactId>servlet-api</artifactId>

<version>6.0.35</version>

</dependency>


그리고 아래와 같이 테스트 코드를 작성한다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-context.xml")
public class PersonAPIControllerTest {
@Resource
private IPersonService personService;
    @Autowired
    private RequestMappingHandlerAdapter handlerAdapter;

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;
    
    private Person person;
    
    @Before
    public void setup() {
    person = personService.add("ykyoon", "lastName", 100.00);
    }
    
    @Test
    public void get() throws Exception {
    MockHttpServletRequest request = new MockHttpServletRequest("GET","/rest/person/" + person.getId().toString());
    MockHttpServletResponse response = new MockHttpServletResponse();

    Object handler = handlerMapping.getHandler(request).getHandler();
    ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);    
    System.out.println(response.getContentAsString());    
    assertNull(modelAndView);
    }
    
    @Test
    public void edit() throws Exception {
    MockHttpServletRequest request = new MockHttpServletRequest("POST", "/rest/person/edit");
    request.addParameter("id", person.getId().toString());
    String editedFirstName = "EDITED_FIRSTNAME";
    request.addParameter("firstName", editedFirstName);
    request.addParameter("lastName", person.getLastName());
    request.addParameter("money", person.getMoney().toString());
   
    MockHttpServletResponse response = new MockHttpServletResponse();
   
    Object handler = handlerMapping.getHandler(request).getHandler();
    ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);    
    System.out.println(response.getContentAsString());    
    assertNull(modelAndView);
   
    Person editedPerson = personService.get(person.getId());
    assertThat(editedPerson.getFirstName(), is(editedFirstName));
    }
    
    @Test
    public void delete() throws Exception {
    MockHttpServletRequest request = new MockHttpServletRequest("DELETE", "/rest/person/delete/" + person.getId().toString());
    MockHttpServletResponse response = new MockHttpServletResponse();

    Object handler = handlerMapping.getHandler(request).getHandler();
    ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);    
    System.out.println(response.getContentAsString());    
    assertThat(response.getStatus(), is(200));
    assertNull(modelAndView);

    Person deletedPerson = personService.get(person.getId());
    assertNull(deletedPerson);
    }
}






Posted by Y2K
,