ALM/Build Automation (빌드 자동화)

maven으로 REST 개발 환경 만들기(Jersey+Spring+MyBatis) #1/2

Terry Cho 2013. 4. 12. 13:43

Maven을 이용한 Jersey + Spring + MyBatis 기반의 REST 애플리케이션 개발


조대협(http://bcho.tistory.com)

빌드 스크립트 설정

개발 환경에서 가장 중요한 빌드에서 부터 알아보자, 우리가 정의하는 빌드는 다음과 같다.

"빌드란, 실행 환경에 맞춰서 소스 코드를 실행 가능한 형태의 바이너리로 변경 및 패키징 하는  일련의 과정을 정의한다."

단순하게 소스코드를 바이너리로 바꾸는 컴파일이 될 수 도 있고, 실행에 필요한 각종 리소스 (이미지, 각종 설정 파일등)을 실행 환경(서버 주소등)에 맞춰서 같이 패키징 하는 과정을 이야기 한다.

이 빌드 여러개의 연속된 작업을 포함하기 때문에, 보통 스크립트를 기반으로 수행이 되는데, C/C++의 경우에는 make 기반의 빌드 스크립트가, 자바의 경우에는 ant maven이 널리 사용된다.

 

ant vs maven

자바 기반에서 현재 가장 인기 있는 빌드 스크립트 툴은 ant maven이다. 요즘은 상당 부분이 maven으로 넘어갔다. 그렇다면 이 각각 빌드 스크립트 툴의 장점은 무엇일까?

 

유연성과 관리

ant의 경우에는 자유도가 상당히 높다. 파일을 복사하거나, 쉘 명령을 실행할 수 도 있다. 스크립트내에서 빌드, 패키징 은 물론이고 배포,테스트, 미들웨어에 대한 기동이나 정지까지 모든 것이 가능하다. 자유도가 높다는 이야기는 반대로 이야기 하면 표준화가 어렵다는 이야기가 된다.

잘 관리 하지 않으면 프로젝트 마다 또는 팀마다 빌드 스크립트가 제각각이다. 표준화가 되지 않은 빌드 스크립트는 새롭게 합류하는 개발자들에게 별도의 learning curve를 요구하게 되고, 실수를 유발한다.

또한 복잡한 형태의 빌드 프로세스를 요구 하는 개발의 경우에는 빌드 스크립트 자체를 만드는 것 자체가 복잡한 일이 된다.

 

maven은 이런 단점을 보완해서 개발되었다.

maven은 템플릿 기반으로 빌드 스크립트를 구성한다. 템플릿 기반이란, 특정 애플리케이션 타입에 대해서, 디렉토리 구조, 빌드 프로세스등이 모두 정해져있다. 그래서 애플리케이션 타입에 따라서 템플릿만 골라서 사용하게 되면 누구나 같은 디렉토리 구조에서 같은 빌드 프로세스에서 개발하게 된다. 그래서 learning curve가 상대적으로 낮고, 누구나 표준화된 환경에서 빌드가 가능하다.

반대로, 템플릿 이외의 기능에 대해서는 유연성이 떨어져서, 마음대로 무엇인가를 추가 하는 것이 어렵다. (예를 들어서 파일을 특정 클라우드에 복사한다던지). 물론 maven도 플러그인이라는 기능을 통해서 템플릿의 기능을 확장할 수 있는 기능을 제공하지만, 이 플러그인이라는 것 자체의 개발이 쉽지가 않기 때문에 템플릿의 기능을 벗어나는 순간 learning curve가 급속하게 올라간다. 다행이도 근래에는 maven에서 사용할 수 있는 플러그인들이 많이 있기 때문에, 이런 문제들은 상대적으로 줄어들고 있다.

 

의존성 관리

다음으로 라이브러리에 대한 의존성에 대해서 고민해볼 필요가 있다.

ant의 경우에는 소스코드와 라이브러리 그리고 기타 의존된 리소스 파일 (설정 파일, 스크립트, 이미지)등이 디렉토리에 있는 것을 가정하고 빌드를 진행한다. 전적으로 이러한 파일들을 챙기는 것은 개발자와 빌드 메니져의 역할인데, 이러다 보니 특히 라이브러리 관련해서 문제가 발생한다.

예를 들어 원 소스는 spring 3.0 라이브러리를 바탕으로 개발이 되었는데, 어떤 개발자는 spring 2.0을 사용해서 컴파일하고 어떤 개발자는 spring 3.1을 사용해서 컴파일 하는, 이런 일들이 발생할 수 있다는 것이다. (실제로 종종 발생하는 일)

maven의 경우 재미있는 것은 이렇게 컴파일을 하는 데 필요한 라이브러리에 대한 의존성을 정의하고, 정확한 버전을 정의하면, 컴파일 타임에 원격에 있는 repository로 부터, 명시된 버전의 라이브러리를 다운 받아서 컴파일과 패키징을 진행하기 때문에, 라이브러리의 버전 불일치가 발생될 염려가 없다. 또한 오픈소스등에서 작성한 well-known 라이브러리가 아니더라도, 자체적으로 repository 시스템을 구축하여, 팀내에서 개발한 라이브러리를 배포해놓고 사용할 수 있다. 이런 시나리오는 여러개의 모듈을 동시에 개발하는 프로젝트 팀의 경우, 모듈간의 의존 관계에서 오는 문제를 해결할 수 있는 좋은 방안이 된다.

 

근래에는 이런 장점 때문에, 유연성이 다소 적더라도 maven이 많이 사용되는 추세이다.

이제 부터 간단하게 maven 기반의 빌드 방법에 대해서 설명해보도록 한다.

여기서 소개하는 빌드 스크립트는 web application 기반의 빌드 스크립트로, 다음과 같은 시나리오를 구성할것이다.

 

-       Jersey 기반의 JSON/HTTP REST API 지원, Spring DI 기반으로 비지니스 로직 구현, MyBatis를 이용한 데이타 베이스 접근

-       빌드 환경은 개발자 PC local, 개발 환경인 dev, 스테이징 환경 stage,검증 환경인 qa 그리고 실 운영 환경이 production 환경으로 구성된다.

-       빌드 스크립트를 통해서 개발자는 빌드,배포 및 Tomcat상에서 실행 및 테스트를 진행할 수 있어야 한다.

 

maven을 이용한 Jersey + Mybatis + Spring 기반의 개발 환경 구축하기

먼저 maven 이용해서 개발을 하려면 프로젝트를 만들어야 한다. 프로젝트는 특정한 애플리케이션 타입에 맞는 템플릿을 이야기 한다. 디렉토리 구조나 빌드 프로세스들이 미리 정해져 있는 개발을 위한 하나의 비어 있는 틀이다.

 

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false  -DgroupId=spring-tutorial -DartifactId=terry -Dversion=1.0-SNAPSHOT -Dpackage=terry.spring.tutorial.ch1

 

이렇게 하면 하나의 비어 있는 프로젝트가 생성이 된다.

프로젝트가 생성이 되면, 해당 애플리케이션을 개발하는데 필요한 디렉토리 구조나 필요한 라이브러리 들이 자동으로 다운로드 되서 설치 된다. 프로젝트는 java web application 지원하는 war형태의 프로젝트이다.

maven 앞서도 설명하였듯이, 프로젝트를 생성할때, 프로젝트의 타입을 정할 있다. 여기서는 war 기반의 개발을 하기 위한 web-app 형태의 프로젝트를 생성하였는데, 프로젝트 타입은 -DarchetypeArtificatId 지정할 있다. (여기서는 가장 기본적은 maven-archetype-webapp 사용하였다.)

 

그럼 생성된 프로젝트의 모양을 살펴보자. 생성된 프로젝트의 디렉토리 구조는 다음과 같다.

 


pom.xml

ant ant.xml이나 make makefile처럼 build 대한 모든 configuration 지정한다.

 

다음으로 생성된 디렉토리를 살펴보자 src에는 *.java 소스 파일과 webapp (war root)디렉토리에 들어가는 내용들과 각종 설정 파일들이 들어간다. 상세한 내용을 살펴보자.

 

src/main/resource

디렉토리는 각종 설정 파일이 위치하는 곳이다. 디렉토리 안에 있는 파일을 class path 포함된다. war 경우에는 디렉토리에 있는 파일들은 WEB-INF/classes 디렉토리 아래에 그대로 들어간다.

예를 들어 src/main/resources/sqlmap/sqlmapper.xml 파일은 컴파일 후에, war파일내의 WEB-INF/classes/sqlmap/sqlmapper 저장된다.

 

src/main/webapp

Web resource 해당 하는 부분이다. war안에 / 디렉토리에서 부터 들어가는 html 각종 리소스 파일들을 모두 정의하낟.

 

그런데, 정작 보면 java 코드를 넣을 소스 디렉토리가 없다.

src/main/ 디렉토리 밑에 java 디렉토리를 하나 만들자.

아래 화면은 src/main/java 디렉토리를 만들고, terry.restapi.model.ContactVo.java 구현한 디렉토리 구조이다.

 

 

아래 코드는 Contact.java 클래스로, 간단하게 사용자의 이메일,이름과 전화번호를 저장하는 VO 클래스 이다.

package terry.restapi.model;

import javax.xml.bind.annotation.XmlRootElement;

 

@XmlRootElement(name="Contact")

public class ContactVo {

        String email;

        String name;

        String phone;

        public String getEmail() {

               return email;

        }

        public void setEmail(String email) {

               this.email = email;

        }

        public String getName() {

               return name;

        }

        public void setName(String name) {

               this.name = name;

        }

        public String getPhone() {

               return phone;

        }

        public void setPhone(String phone) {

               this.phone = phone;

        }

       

}

 

여기 까지 진행을 했으면, war 파일이 어떻게 만들어지는지 테스트를 해보자

% mvn package 실행하면

${HOME} 디렉토리 아래 /target/terry.war 파일이 생성된 것을 있다.

파일을 풀어보면 앞에서 만든 WEB-INF/classes/terry/restapi/model/Contact.class 패키징 되어 있는 것을 확인할 있다.

 

지금까지 간단하게 maven 프로젝트를 만들고, 소스코드를 넣고, 웹에 관련된 리소스를 정의한후에, 컴파일 war 패키징을 해보았다.

 

maven ant make 처럼 일종의 build target 제공하는데, maven에서는 이를 goal이라고 한다. pom.xml 스크립트에 따라서 다양한 goal 정할 있으나, maven에서 미리 정해져 있는 goal 중요한 goal들은 다음과 같다.

 

mvn compile : 컴파일 수행. (프로젝트내의 java 코드를 컴파일 한다.)

mvn package : jar,war,ear pom.xml에서 정해진 형태로 파일로 패키징. (컴파일을 한후, 프로젝트 내용에 따라서 패키징을 수행한다.)

mvn test : JUnit 테스트 수행.

mvn install : local repository (PC내의 디렉토리)에 패키징된 파일을 저장

mvn deploy  : remote repository (Nexus)에 패키징된 파일 저장

mvn clean : 컴파일 내용 모두 삭제

 

여기서 compile,package,clean 등은 거의 모든 빌드 스크립트에서(ant ) 공통적으로 지원하기 때문에 별도의 설명을 하지 않는다.

install deploy 대해서 살펴보자

 

앞서도 설명했듯이, maven library 대한 dependency 지정하고 스크립트를 수행하면, repository라는 곳에서 해당 라이브러리들을 읽어온다. 그러면 repository 어디일까?

mvn install 컴파일된 패키지들를 local pc 라이브러리 저장소에 배포한다. 다른 프로젝트가 라이브러리를 사용하고자 한다면, local pc 내에서 라이브러리를 찾아서 같이 컴파일 있다. 그러나 local pc에만 배포가 되었기 때문에 다른 사람은 라이브러리를 참조해서 사용할 없다. 그래서 다른 사람이 라이브러리를 참조할 있게 하려면, 네트워크 상의 공용 repository 필요하다. 이러한 공용 repository 라이브러리를 배포하는 명령이 mvn deploy이다.

spring이나 기타 라이브러리등은 각각의 공용 repository 가지고 있고, mvn 역시 이러한 repository list 기반으로 해서 라이브러리를 로딩하는데, 우리 회사나 팀에서만 사용할 있는 repository 별도로 구축하려면 어떻게 해야 할까? nexus라는 제품을 설치하면, 사내에 전용 repository 서버를 구축할 있다. (http://www.sonatype.org/nexus/)

 

maven 프로젝트 생성, 디렉토리 구조의 이해 그리고 maven 통한 컴파일 패키징에 대한 설명이 끝났다. 그러면 이제 부터, Jersey + Spring + Mybatis 개발하기 위한 설정을 해보자, 먼저 pom.xml 위의 세가지 프레임웍을 사용하기 위해서 라이브러리를 정의해야 한다.

라이브러리 정의는 <dependencies>엘리먼트 아래에 라이브러리 <dependency> 라는 엘리먼트로 정의한다.

 

<dependencies>

    <!--  jersey dependency -->

        <dependency>

            <groupId>com.sun.jersey</groupId>

            <artifactId>jersey-server</artifactId>

            <version>1.17</version>

        </dependency>

: 아래 생략

 

위의 3가지 프레임웍을 사용하기 위해서 필요한 dependency 다음과 같다.

정확하게 여기서는 JSON/REST 이용하기 위해서 Jersey 사용하고, Spring 3.1 에서 Dependency Injection만을 이용할것이며, MyBatis MySQL 사용을 위해서 MySQL JDBC Driver 사용할것이다.

아래는 지면 관계상, dependency 테이블로 정리해놨다. 글의 뒷부분의 pom.xml 전문을 따로 첨부했으니, 참고하기 바란다.

 

프레임웍 이름

groupId

artifactId

version

Jersey

com.sun.jersey

jersey-server

1.17

com.sun.jersey

jersey-servlet

1.17

com.sun.jersey

jersey-json

1.17

Spring

org.springframework

spring-core

3.1.1.RELEASE

org.springframework

spring-context

3.1.1.RELEASE

org.springframework

spring-beans

3.1.1.RELEASE

org.springframework

spring-web

3.1.1.RELEASE

org.springframework

spring-webmvc

3.1.1.RELEASE

Spring + Jersey 연결

com.sun.jersey.contribs

jersey-spring

1.17

Spring + Mybatis 연결

org.mybatis

mybatis-spring

1.0.1

MySQL JDBC

mysql

mysql-connector-java

5.1.24

 

여기서 spring+Jersey 연결에 사용되는 jsersy-spring artifact 잠시 살펴볼 필요가 있다. jersey-spring artifact 자체적으로 spring 프레임웍을 포함하고 있기 때문에, 우리가 정의한  Spring framework 중복 가능성이 있다. 그래서, jersey-spring dependency 의해서 spring framework 중복적으로 가지고 오지 않도록 해당 모듈들을 다음과 같이 exclude(제외)하도록 선언한다.

<!--  jersey + spring depdendency  -->

     <dependency>

                       <groupId>com.sun.jersey.contribs</groupId>

                       <artifactId>jersey-spring</artifactId>

                       <version>1.17</version>

                       <exclusions>

                              <exclusion>

                                      <groupId>org.springframework</groupId>

                                      <artifactId>spring</artifactId>

                              </exclusion>

                               <exclusion>

                                      <groupId>org.springframework</groupId>

                                      <artifactId>spring-core</artifactId>

                              </exclusion>

                              <exclusion>

                                      <groupId>org.springframework</groupId>

                                      <artifactId>spring-web</artifactId>

                              </exclusion>

                              <exclusion>

                                      <groupId>org.springframework</groupId>

                                      <artifactId>spring-beans</artifactId>

                              </exclusion>

                              <exclusion>

                                      <groupId>org.springframework</groupId>

                                      <artifactId>spring-context</artifactId>

                              </exclusion>

                       </exclusions>

               </dependency>

자아. 이제 빌드 스크립트는 Jersey + Mybatis + Spring DI 이용한 개발 준비가 되었다. 그러면 실제 코딩에 들어가 보자

java/terry/restapi 아래, MVC 모델에 맞춰서 service,dao,model 디렉토리를 만들고 아래와 같이 클래스들을 구현한다.

 

java/terry/restapi/dao/ContactDao.java

package terry.restapi.dao;

 

import java.util.HashMap;

 

import terry.restapi.model.ContactVo;

 

public interface ContactDao {

       

        public void create(ContactVo contact);

        public ContactVo get(String email);

        public void delete(String email);

        public void update(String email,ContactVo contact);

}

 

java/terry/restapi/dao/ContactImpl.java Mybatis 이용한 contact 테이블에 대한 CRUD 구현한다.

package terry.restapi.dao;

 

import org.mybatis.spring.support.SqlSessionDaoSupport;

 

import terry.restapi.model.ContactVo;

 

public class ContactDaoImpl extends SqlSessionDaoSupport implements ContactDao {

 

        public void create(ContactVo contact) {

               // TODO Auto-generated method stub

 

        }

 

        public ContactVo get(String email) {

               // TODO Auto-generated method stub

               ContactVo contact = (ContactVo)getSqlSession().selectOne("contactdao.getUserByEmail", email);

               return contact;

        }

 

        public void delete(String email) {

               // TODO Auto-generated method stub

 

        }

 

        public void update(String email, ContactVo contact) {

               // TODO Auto-generated method stub

 

        }

 

}

 

java/terry/restapi/model/ContactVo.java 앞에서 이미 구현했기 때문에, 앞의 코드 참고

 

다음은 Jersey 이용한 REST API 구현이다. 아래 코드는 편의상 create,select,update 구현하였다.

package terry.restapi.service;

 

import javax.ws.rs.Consumes;

import javax.ws.rs.GET;

import javax.ws.rs.POST;

import javax.ws.rs.PUT;

import javax.ws.rs.Path;

import javax.ws.rs.PathParam;

import javax.ws.rs.Produces;

import javax.ws.rs.core.MediaType;

import javax.ws.rs.core.Response;

 

import terry.restapi.dao.ContactDao;

import terry.restapi.model.ContactVo;

 

@Path("/contact")

public class ContactService {

        static ContactDao dao = null;

        public void setContactDao(ContactDao dao){this.dao = dao;}

        public ContactService(){

               //if(dao == null)      setContactDao(new ContactDao());

        }

       

        /**

         * Create Contact Record

         * @param contact

         * @return

         */

        @POST

        @Consumes(MediaType.APPLICATION_JSON)

        public Response create(ContactVo contact){

               dao.create(contact);

               return Response.status(200).entity(contact).build();

 

        }

        /**

         * Query Contact record by email id

         * @param email

         * @return

         */

        @GET

        @Produces(MediaType.APPLICATION_JSON)

        @Path("{email}")

        public ContactVo get(@PathParam("email") String email){

               return dao.get(email);

        }

        /**

         * Upadte Contact Record by email

         * @param email

         * @param contact

         * @return

         */

        @PUT

        @Path("{email}")

        @Consumes(MediaType.APPLICATION_JSON)

        @Produces(MediaType.APPLICATION_JSON)

        public Response  update(@PathParam("email") String email, ContactVo contact){

               dao.update(email, contact);

               return Response.status(200).entity(contact).build();

        }

}

 

 

자아 코드 구현이 끝났다.

이제 코드를 실행하기 위해서는 다음과 같은 추가 작업이 필요하다.

/webapp/WEB-INF/config/spring-context.xml Spring Bean 정의하기 위한 spring context 파일 작성

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 

        <!--  load configuration file -->

         <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

          <property name="locations">

           <value>/WEB-INF/config/config.properties</value>

          </property>

         </bean>

         

        <!--  create rest service object and inject dao -->

        <bean class="terry.restapi.service.ContactService" id="contactService">

               <property name="contactDao" ref="contactdao" />

        </bean>

        <!-- declare dao object  -->

        <bean class="terry.restapi.dao.ContactDaoImpl" id="contactdao">

               <property name="sqlSessionFactory" ref="sqlSessionFactory" />

        </bean>

       

        <!--

               mybatis configuration

               sqlSessionFactory & sqlSessionTemplate are required

         -->

        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

               <property name="dataSource" ref="dataSource" />

               <property name="configLocation" value="/WEB-INF/config/mybatis-config.xml"/>

        </bean>

        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">

               <constructor-arg ref="sqlSessionFactory" />

        </bean>

       

        <!-- 

               data source configuration

               for testing purpose , it uses simple jdbc datasource

         -->

        <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">

               <property name="driverClass" value="${mybatis.jdbc.driverclass}"/>

               <property name="url" value="${mybatis.jdbc.url}" />

               <property name="username" value="${mybatis.jdbc.username}" />

               <property name="password" value="${mybatis.jdbc.password}" />

        </bean>

</beans>

 

그리고 위의 파일 내용을 보면, /WEB-INF/config/config.properties라는 파일을 읽게 되어 있는데, 여기에는 MYSQL DBMS 접속에 필요한 URL,PORT,사용자 id,passwd등이 들어간다.

/webapp/WEB-INF/config/config.properties

 

mybatis.jdbc.driverclass=com.mysql.jdbc.Driver

mybatis.jdbc.url=jdbc:mysql://localhost:3306/development

mybatis.jdbc.username=developer

mybatis.jdbc.password=developer

 

/webapp/WEB-INF/config/mybatis-config.xml MyBatis 사용하는 데이타 베이스 연결 정보등의 설정 파일

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "HTTP://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

 <settings>

  <setting name="cacheEnabled" value="false" />

  <setting name="useGeneratedKeys" value="true" />

  <setting name="defaultExecutorType" value="REUSE" />

 </settings>

 

 <mappers>

  <mapper resource="sqlmap/ContactDao_map.xml" />

 </mappers>

</configuration>

 

/webapp /WEB-INF/web.xml 초기에 Spring Context Jersey framework 로딩하기 위한 설정

<!DOCTYPE web-app PUBLIC

 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

 "http://java.sun.com/dtd/web-app_2_3.dtd" >

 

<web-app>

  <display-name>Archetype Created Web Application</display-name>

 

        <!--  load spring context configuration -->

        <context-param>

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

               <param-value>

                       /WEB-INF/config/spring-context.xml

                       <!-- /WEB-INF/config/mybatis-context.xml -->

               </param-value>

        </context-param>

 

        <!--  load listener  -->

        <listener>

               <listener-class>

                       org.springframework.web.context.ContextLoaderListener

               </listener-class>

        </listener>

       

        <!--  configure jersey/JSON servlet -->

        <servlet>

          <servlet-name>Jersey Web Application</servlet-name>

               <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>

                     <init-param>

                              <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>

                              <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>

                 </init-param>

                 <init-param>

                  <param-name>com.sun.jersey.config.property.packages</param-name>

                  <param-value>terry.restapi</param-value>

                </init-param>

                <init-param>

                              <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>

                              <param-value>true</param-value>

                       </init-param>

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

            </servlet>

       

            <servlet-mapping>

               <servlet-name>Jersey Web Application</servlet-name>

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

            </servlet-mapping>

</web-app>

 

/resources/sqlmap/ContactDao_map.xml MyBatis 실행하는 SQL 들어 있는 SQL Mapper 파일 작성

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

<mapper namespace="contactdao">

        <!-- 

               select user by email id

        -->

        <resultMap type="terry.restapi.model.ContactVo" id="resultmap.terry.restapi.model.ContactVo">

               <id column="email" property="email"/>

               <result column="name" property="name"/>

               <result column="phone" property="phone"/>

        </resultMap>

        <select id="getUserByEmail" parameterType="String" resultMap="resultmap.terry.restapi.model.ContactVo">

               select email,name,phone

               from contact_table

               where email = #{email}

        </select>

</mapper>

 

여기 까지 구현하였으면 디렉토리는 다음과 같은 형태가 된다..


 

이제 mvn package 명령어를 이용하여 war 파일을 만들고, tomcat 배포한후,

MySQL DB 아래와 같은 scheme contact_table 만들면 실행을 위한 준비가 끝난다.

 


수동으로 Tomcat 설치하고 실행하고 배포하면 까다롭기도 하거니와, 개발자 마다 다른 버전이나 다른 설정을 있기 때문에,  이번에는 mvn 스크립트내에서 빌드 과정내에, Tomcat 자동으로 기동 시키고 배포하는 스크립트를 추가해보자.

 

과정은 maven 플러그인이라는 기능을 이용하면 된다.

pom.xml <project> 엘리먼트 아래 다음과 같은 내용을 추가한다.

<build>

    <finalName>restapi</finalName>

         <plugins>

              <!-- 

                tomcat7 plugin

                caution!!. mvn tomcat:xxx will invoke default plugin

                do. mvn tomcat7:xxx

                -->

              <plugin>

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

                  <artifactId>tomcat7-maven-plugin</artifactId>

                  <version>2.1</version>

                          <configuration>

                                 <warSourceDirectory>${basedir}/target/${artifactId}</warSourceDirectory>

                          </configuration>

             </plugin>

         </plugins>

  </build>

위의 내용은 tomcat 7 플러그인을 추가하여, 빌드 후에 tomcat 기동할 있게 해주며, tomcat 실행시 ${basedir} (pom.xml 있는 프로젝트의 루트 디렉토리)아래 /target/terry 디렉토리를 war root 디렉토리로 인식하고 기동하게 한다.

${artifactid} maven 프로젝트 생성시 지정했던 프로젝트의 이름으로, war 빌드 스크립트는 별도의 지정이 없는한, war파일명을 ${artifactid}.war ${basedir}/target/ 아래 생성한다. 또한 컴파일 과정에서 war파일이 풀린 모든 파일들을 위치해놓는다.

 

자아 이제 모든 스크립트가 완성이 되었다.

%mvn package tomcat7:run

실행해보자

package 컴파일 war파일과 war 파일이 풀린 모든 파일들(exploded war) 만들게 하고

tomcat7:run tomcat7 위에서 만든 exploded war파일들을 읽어서 기동하게 한다.

 

이제 로컬 환경에서 배포와 실행이 되었으면 REST API 호출하여 테스트를 해보자. 간단한 테스트를 위해서 Google Chrome Browser Advanced REST Client 사용하였다.

 

 



 

 

그리드형