for each(var tempUnit:XML in myXML.uint)
{
var groupPages:Array =[];
for each(var tempUnit2:XML in tempUnit..@id)
{
groupPages[tempUnit2] = tempUnit..page(@id == tempUnit2);
}
}

'개발도 하냐?' 카테고리의 다른 글

FLEX - 멀티파일업로드  (0) 2009.11.13
FLEX - Grid 컴퍼넌트로 그린 달력.  (0) 2009.11.11
웹로직 DB 접속설정  (0) 2009.11.04
자동화 빌드도구 ANT  (0) 2009.11.04
JEUS 설정  (0) 2009.11.04
JDBC Setting

1. http://localhost:7001/console/   -> 로그인

2. domainStructure -> services 클릭

3.  jdbc 클릭

4. datasources 클릭

5. Lock & Edit 클릭

6. New 클릭

7. Name = OracleDataSource

8. JNDI Name = OracleJNDI

9. DatabaseType=oracle

10. Oracle`s Driver(Thin) version 9.0.1.9.2.0.10

11.  next ->next

12. DatabaseName = 오라클 SID  (java)

13. HOSTNAME = 127.0.0.1

14. port  =  1521 , 1522

15. database User name  = yoshikix

16.database UserPass = yoshikix

17.testConfiguration 클릭후 에러나면  수정 해서 될때까지 테스트

18 .  next ->check 후 -> finished -> 확정.   activated changed

19. jsp 파일에서 (DataSource ds;) 추가 후 임폴트
메뉴얼

http://ant.apache-korea.org/manual/index.html



Jakarta Ant


I. Ant 야 놀자~

Ant 란 "Java 기반의 빌드 도구입니다" 라고들 많이 나와있습니다
근데 이게 대체 무순 뜻이란 말인가 ㅡ.ㅡ;


쉽게 예기해서 환경에 구애받지 않고 간단히 java 소스를 컴파일 하고 필요한 파일이 있다면
그 파일들을 복사나 삭제하며 또한 javadoc 이나 war 같은 배포용 파일까지 생성해 주며
필요하다면 서버에 까지 바로 적용할 수 있도록 도와주는 도구입니다.


또한 여러팀원들이 프로젝트를 진행할 때 새로운 팀원이 참가하더라도
Ant 설정파일을 공유함으로써 손쉽게 참여가 가능하다는 것입니다


아직 사용해 보지 않았다면 얼렁 익혀서 사용해봅시다 무~지 편하답니다



II. 설치해보자
다운로드
Ant

http://ant.apache.org/bindownload.cgi

Ant manual

http://ant.apache.org/manual/index.html

http://ant.apache-korea.org/manual/index.html


다운받은 파일의 압축을 풀고 환경변수 및 패스를 잡아줍니다
set ANT_HOME=c:\ant
set JAVA_HOME=c:\jdk1.4.2
set PATH=%PATH%;%ANT_HOME%\bin



III. 간단한 Ant 예제

Ant를 이용하여 web application을 구성할 때 다음의 구조를 유지하기를 권장합니다


build : src, web, docs에서 결과적으로 만들어진 산출물 디렉토리
dist : build를 배포하기 위한 배포 디렉토리
docs : 배포판에 배포할 정적인 문서를 관리할 디렉토리
src : /WEB-INF/classes 에 위치할 java 소스 디렉토리
web : HTML, JSP, 이미지등의 컨텐트 디렉토리 (WEB-INF의 서브디렉토리 포함)
build.properties : build.xml에서 사용할 properties
build.xml : ant 명령으로 실행될 설정파일


src에 하나이상의 java 소스를 테스트로 넣어 놓으세요

자 이렇게 디렉토리를 설정하고 build.xml 을 다음 step에 따라 따라 해 BOA요 ^^&


STEP 1. build.xml 의 기본구조

xml을 기본적인 내용을 안다면 이해하기 쉽습니다

<project name="My Project" default="compile" basedir=".">

 <target name="clean">

   여러 작업

  </target>


  <target name="prepare" depends="clean">

   여러 작업

   </target>


   <target name="compile" depends="prepare">

    여러 작업

    </target>

</project>

하나의 build 파일은 하나의 project로 구성되며 이는 다시 여러 target으로 구성됩니다

target 이란 빌드 과정중 수행해야 할 task들을 모아놓은 job 단위 라고 보면 됩니다

compile target이라 한다면 compile에 관련된 작업들을 모아놓은 그룹이라 생각하면 쉽게 이해 될겁니다


STEP 2. 시~작 Ant 맛보기~
① build.xml에 다음을 입력한 후 저장 합니다

<project name="Unicorn Project" default="clear" basedir=".">
  <description>Simple Test</description>
 
  <property file="${basedir}/build.properties"/>
 
  <echo message="${catalina.home}"/>


   <target name="clear"/>
   
</project>

-. project

    project는 하나 이상의 target을 정의 합니다 또한 하나의 target은 task의 집합입니다

    ant를 실행할 시에 어느 타겟을 실행할 것인지 지정할 수가 있으며 (예: \ant clear)

    지정하지 않았을 경우 디폴트로 설정된 값이 사용됩니다 이부분이 default="clear"입니다

-. property

    전역변수 설정 혹은 그렇게 사용할 build.properties를 정의 합니다

    build.properties에 catalina.home을 정의하였으며 여러 환경이 변하더라도 이 값만

    변경해주면 build.xml을 수정없이 바로 실행 가능합니다

-. echo

    message 내용을 출력 합니다

-. target

    target 이란 task의 집합으로 실질적으로 실행될 코드들의 묶음입니다

    여기서는 아무 task도 없습니다


② build.properties에 다음을 입력 후 저장합니다

catalina.home=C:\Tomcat 5.0

catalina.home 은 변수로 사용할 것이며 그 값은 C:\Tomcat 5.0입니다


③ 실행

해당 디렉토리로 이동하여 도스창에서 ant 라고 칩니다

c:\예제\ant

Buildfile : build.xml

      [echo] c:\Tomcat 5.0


clear :


BUILD SUCCESSFUL

Total time : 0 seconds


STEP 3. 사전작업 하기~

이번 단계에서는 컴파일 하기전 전역변수 선언이나 컴파일 시 클래스 패스 설정을 해봅시다


① build.xml

<project name="Unicorn Project" default="prepare" basedir=".">
  <description>Simple Test</description>

  <property file="${basedir}/build.properties"/>


  <property name="app.name"      value="unicorn"/>
  <property name="app.path"       value="/${app.name}"/>
  <property name="app.version"   value="0.1-dev"/>

  <property name="build.home"    value="${basedir}/build"/>
  <property name="dist.home"     value="${basedir}/dist"/>
  <property name="docs.home"   value="${basedir}/docs"/>
  <property name="src.home"      value="${basedir}/src"/>
  <property name="web.home"     value="${basedir}/web"/>  


  <path id="compile.classpath">

    <pathelement location="${catalina.home}/common/classes"/>
    <fileset dir="${catalina.home}/common/endorsed">
      <include name="*.jar"/>
    </fileset>
    <fileset dir="${catalina.home}/common/lib">
      <include name="*.jar"/>
    </fileset>
    <pathelement location="${catalina.home}/shared/classes"/>
    <fileset dir="${catalina.home}/shared/lib">
      <include name="*.jar"/>
    </fileset>
    <fileset dir="${web.home}/WEB-INF/lib">
      <include name="*.jar"/>
    </fileset>
  </path>


  <target name="clean"
   description="Delete old build and dist directories">
    <delete dir="${build.home}"/>
    <delete dir="${dist.home}"/>
  </target>
 
  <target name="prepare" depends="clean">

    <mkdir dir="${build.home}"/>
    <mkdir  dir="${build.home}/WEB-INF"/>
    <mkdir  dir="${build.home}/WEB-INF/classes"/>
    <mkdir  dir="${build.home}/WEB-INF/lib"/>
   
    <copy todir="${build.home}">
       <fileset dir="${web.home}">
         <include name="**/*.jsp"/>
         <include name="**/*.css"/>
         <include name="**/*.html"/>
         <include name="**/*.js"/>
         <include name="**/*.jpg"/>
         <include name="**/*.gif"/>
         <include name="**/*.swf"/>
         <include name="**/*.xml"/>
         <include name="**/*.tld"/>
         <include name="**/*.jar"/>

       </fileset>
     </copy>

   </target>  

   
</project>

-. project

    이번에는 default 값을 prepare로 하였습니다 고로 target은 prepare가 실행될 것입니다

-. property

    역시나 build.properties를 정의하였고 여러 전역변수를 설정하였습니다

    build.home 이란 변수에는 ${basedir}/build 값이 정의되었으며

    build.home은 ${build.home}으로 사용할수 있습니다

    궁금하면 <echo message="${build.home}"/> 등으로 출력해 봅시다~

-. path

    ${catalina.home} 은 build.properties에서 정의하였다는것을 기역하실겁니다

    fileset은 파일들의 집합을 나타내는데 어떤 특정파일만 포함 할수 있거나 혹은 어느 특정파일만 제외할 수 있습니다

    특정파일만 포함하는것은 include 태그이며 그 반대는 exclude 입니다

    <fileset dir="${web.home}/WEB-INF/lib">
      <include name="*.jar"/>
    </fileset>

    이부분은 ${web.home}/WEB-INF/lib 에서 *.jar 파일만 클래스패스로 잡겠다는 의미입니다

-. target

   드디어 실질적으로 실행될 target 입니다.

   project 속성의 default가 prepare이므로 prepare target으로 실행하기 위해 가보니  depend 속성으로 "clean"이 설정되어 있습니다

  이것은 "clean" target을 먼저 실행 후 prepare를 실행하라는 말입니다

   즉 prepare는 clean이 실행조건 입니다

   clean target은 delete 태그를 이용하여 배포할 dist 디렉토리와 산출물 디렉토리인 build를 삭제하는 작업입니다
   prepare target으로 다시 와보면 mkdir 는 당연히 디렉토리를 만들라는 뜻입니다

   copy는 todir에 다음 web.home의 모든 fileset을 copy 하라는 의미입니다 여기서도 역시나 include, exclude가 사용될 수 있겠지요

   <include name="**/*.jsp"/> 는 모든디렉토리의 *.jsp 를 카피하라는 의미입니다

    즉 web 디렉토리의 모든 실행 가능할 파일을 build로 옮기는 작업입니다


② 실행

c:\예제\ant

Buildfile : build.xml


clean :

     [delete] : Deleting directory c:\예제\build

     [delete] : Deleting directory c:\예제\dist


prepare :

     [mkdir] Created dir : c:\예제\build\WEB-INF

     [mkdir] Created dir : c:\예제\build\WEB-INF\classes

     [mkdir] Created dir : c:\예제\build\WEB-INF\lib

     [copy] Copying 2 files to Deleting directory c:\예제\build


BUILD SUCCESSFUL

Total time : 1 seconds


STEP 4. 컴파일 하기

이제 컴파일할 모든 준비가 되었습니다

STEP2의 소스에 다음 target을 추가하고 project의 default 값을 compile로 수정한 후 실행해 봅시다


 <target name="compile" depends="prepare"
   description="Compile Java sources">


    <!-- Compile Java classes as necessary -->
    <javac srcdir="${src.home}"
          destdir="${build.home}/WEB-INF/classes">
        <classpath refid="compile.classpath"/>
    </javac>


    <!-- Copy application resources -->
    <copy  todir="${build.home}/WEB-INF/classes">
      <fileset dir="${src.home}" excludes="**/*.java"/>
    </copy>
   
 </target>

-. target

   depends가 prepare이므로 실행 순서는 clean, prepare, compile 입니다

   javac 태스크는 srcdir 인 소스디렉토리에 있는 자바소스를 desdir 쪽으로 컴파일 합니다

   classpath는 위에서 이미 설정한 compile.classpath를 사용합니다

   그 후 properties등 같은 기타 resource 들을 /WEB-INF/classes에 복사합니다

② 실행

c:\예제\ant

Buildfile : build.xml


clean :

     [delete] : Deleting directory c:\예제\build

     [delete] : Deleting directory c:\예제\dist


prepare :

     [mkdir] Created dir : c:\예제\build\WEB-INF

     [mkdir] Created dir : c:\예제\build\WEB-INF\classes

     [mkdir] Created dir : c:\예제\build\WEB-INF\lib

     [copy] Copying 2 files to Deleting directory c:\예제\build


compile :

     [javac] Compileing 1 source file to c:\예제\build\WEB-INF\classes

     [copy] Copying 1 file to c:\예제\build\WEB-INF\classes


BUILD SUCCESSFUL

Total time : 1 seconds


STEP 5. Javadoc 을 이용해 API를 만들어 보고 배포파일도 생성해 보자

이제 컴파일도 했으니 javadoc도 만들어 보고 war 같은 배포파일도 생성해 봅시다

STEP 3.까지의 build.xml에 아래 target을 더 추가하고 project의 default 값에 dist로 설정합니다

① build.xml

 <target name="javadoc" depends="compile"
    description="Create Javadoc API documentation">

     <mkdir dir="${dist.home}/docs/api"/>
     <javadoc sourcepath="${src.home}"
                  destdir="${dist.home}/docs/api"
                   packagenames="*">
       <classpath refid="compile.classpath"/>
     </javadoc>

   </target>


 <target name="dist" depends="compile,javadoc"
   description="Create binary distribution">

    <mkdir dir="${dist.home}/docs"/>

    <copy  todir="${dist.home}/docs">
      <fileset dir="${docs.home}"/>
    </copy>


    <jar jarfile="${dist.home}/${app.name}-${app.version}.war"
         basedir="${build.home}"/>

  </target>

-. target

   target의 실행순서는 clean, prpare, compile, javadoc, dist가 될겁니다

   javadoc target의 javadoc 태스트를 보면 java 소스가 있는 소스디렉토리와

   API를 생성할 타겟 디렉토리를 정해주면 알아서 API를 생성해 줍니다

   만들어진 API는 배포버젼의 dist디렉토리로 해주면 더 좋겠지요


   dist target은 배포파일인 war를 만듭니다

   필요한 문서가 있으면 docs 디렉토리를 만들어 로 복사도 하도록 합시다

   jar 태스크는 위의 방식과 같이 사용합니다


② 실행

c:\예제\ant

Buildfile : build.xml


clean :

     [delete] : Deleting directory c:\예제\build

     [delete] : Deleting directory c:\예제\dist


prepare :

     [mkdir] Created dir : c:\예제\build\WEB-INF

     [mkdir] Created dir : c:\예제\build\WEB-INF\classes

     [mkdir] Created dir : c:\예제\build\WEB-INF\lib

     [copy] Copying 2 files to Deleting directory c:\예제\build


compile :

     [javac] Compileing 1 source file to c:\예제\build\WEB-INF\classes

     [copy] Copying 1 file to c:\예제\build\WEB-INF\classes


javadoc :

     [mkdir] Created dir : c:\예제\dist\docs\api

     [javadoc] Generating Javadoc

     [javadoc] Javadoc execution

     [javadoc] Loading source files for package com.jakartaproject.db...

     [javadoc] Constructing Javadoc information...

     [javadoc] Standard Doclet version 1.4.1

     [javadoc] Building tree for all the packages and classes...

     [javadoc] Building index for all the packaes and classes...

     [javadoc] Building index for all classes...


dist :

     [jar] Building jar :Created dir : c:\예제\dist\unicorn-0.1-dev.war


BUILD SUCCESSFUL

Total time : 3 seconds



VI. Ant 실행

C:\예제\ant -help

ant [options] [target [target2 [target3] ...]]


Options :
  -help                    이 메세지의 표시
  -projecthelp           프로젝트 도움 정보의 출력
  -version                버전 정보의 출력과 종료
  -diagnostics           diagnose 나 report 문제에  도움이 되는 정보의 출력.
  -quiet, -q              한층 더 메세지를 적게
  -verbose, -v          한층 더 메세지를 많게
  -debug                 디버그 정보의 출력
  -emacs                 adornments 없이 로그 정보의 생성(produce)
  -logfile <file>         로그를 지정 파일에 출력
    -l     <file>                ''
  -logger <classname>    로그 생성을 실행하기 위한 클래스
  -listener <classname>  프로젝트 청취자(listener) 역할의 class의 인스턴스를 추가
  -buildfile <file>            지정된 빌드 파일의 사용
    -file    <file>              ''
    -f       <file>              ''
  -D<property>=<value> 지정된 프로퍼티의 값의 사용
  -propertyfile <name>    모든 프로퍼티를 파일로부터 로드  (-D프로퍼티보다 전에)
  -inputhandler <class>  입력 요청(requests)를 취급하는 클래스
  -find <file>                 파일시스템의 루트로 향해 빌드파일을  검색하고 그것을 사용


C:\예제\ant

현재 디렉토리에 있는 build.xml 파일을 이용해, 디폴트 타겟으로 Ant 를 실행합니다.


C:\예제\ant compile

현재 디렉토리에 있는 build.xml이 실행되며 파라미터로 compile을 지정하면 project의 default 값을 무시하고 compile target을 실행합니다 물론 depends 가 있다면 먼저 실행합니다

 

C:\예제\ant -buildfile test.xml

현재 디렉토리에 있는 test.xml 파일을 이용해, 디폴트 타겟으로 Ant 를 실행합니다.


C:\예제\ant -buildfile test.xml dist

현재 디렉토리에 있는 test.xml 파일을 이용해, dist 라는 이름의 타겟으로 Ant 를 실행합니다.


C:\예제\ant -buildfile test.xml -Dbuild=build/classes dist

현재 디렉토리에 있는 test.xml 파일을 이용해, dist 라는 이름의 타겟으로, build 프로퍼티에 build/classes 값을 설정해 Ant 를 실행합니다.


VII. 기본 프로퍼티

Ant는 다음과 같은 프로퍼티를 기본으로 제공합니다

basedir : 기본 디렉토리 경로를 나타내며 project 태그의 basedir에 명시되어 있습니다

ant.file : 빌드 파일의 절대 경로입니다

ant.version : Ant 버젼을 나타냅니다

ant.project.name : project 태그의 name에 명시되어있습니다

ant.java.version : 자바 버젼을 나타냅니다

자바 시스템 프로퍼티를 사용 가능 합니다

   예) ${os.name} 참고 http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#getProperties()


<echo message="${ant.file}"/> 으로 한번 출력해 보면 이해가 쉽습니다


다음 시간에는 각 타스크의 종류와 상세 설정에 관해 알아봅시다


=============================================

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================

'개발도 하냐?' 카테고리의 다른 글

FLEX - XML의 내용을 배열에 넣는법  (0) 2009.11.08
웹로직 DB 접속설정  (0) 2009.11.04
JEUS 설정  (0) 2009.11.04
전자세금계산서/세금계산서 업체 정보리스트  (0) 2009.10.29
Anyframe Doc  (0) 2009.09.16

### JEUS/WEBTOB 연동하기 ###

--------------------------------------------------------------------------------------

1. webtob 설정

   - 웹투비홈/config/http.m의 각 항목에 추가합니다.

   *NODE

       JSVPORT = 9900

   *SVRGROUP

       jsvg     NODENAME=노드이름, SVRTYPE=JSV

   *SERVER

      MyGroup    SVGNAME=jsvg, MinProc=10, MaxProc=10

   *URI

      uri2    Uri="/examples/", Svrtype=JSV

--------------------------------------------------------------------------------------

2. jeus 설정

   - 제우스홈/config/노드이름/노드이름_servlet_engine1/WEBMain.xml 수정

        <webserver-connection>
            <webtob-listener>
                <listener-id>webtob1</listener-id>
                <port>9900</port>
                <hth-count>1</hth-count>
                <webtob-address>IP 혹은 127.0.0.1(동일서버에 JEUS와 WEBTOB존재시)</webtob-address>
                <registration-id>MyGroup</registration-id>
                <thread-pool>
                    <min>4</min>
                    <max>10</max>
                    <step>2</step>
                    <max-idle-time>30000</max-idle-time>
                    <max-wait-queue>4</max-wait-queue> 
                </thread-pool>
            </webtob-listener>
        </webserver-connection>


--------------------------------------------------------------------------------------

3. 제우스홈/bin/jeus.properties 조정

    - JEUS_WSDIR 부분을 주석처리 하거나 삭제

    - PATH 에서 $JEUS_HOME/webserver 부분도 제거

--------------------------------------------------------------------------------------

4. webtob 와 jeus 를 부팅 후 확인

   http://주소:8080/exapmples/index.jsp 에서 테스팅 페이지 보기

--------------------------------------------------------------------------------------

### DB 연동 ###

--------------------------------------------------------------------------------------

* MySQL 커넥션풀 샘플 (WEBMain.xml에 추가)

JEUS에서 제공하는 ConnectionPool은 JDBC Drive를 통해 얻은 Connection의 관리는 
엔진에서 해주는 것이므로 JDBC Driver를 $JEUS_HOME/lib/datasource 아래에 두고
DBConnectionPool은 container.xml에 DataSource는 JeusMain.xml에 다음과 같이 
설정을 하시면 사용하실 수가 있습니다. 
 
1) DBConnectionPool
------------------------------------------------------------------------------
<DBConnectionPool MaxUseCount="-1" 
                  ConnectionPoolType="shared" 
                  CloseDelayMillis="-1" 
                  MaxActiveTimeSecs="-1" 
                  ConnectionPoolID="mysql-shared" 
                  ConnectionArguments="user=root;password=" 
                  DriverClassName="org.gjt.mm.mysql.Driver" 
                  DynamicIncrement="true" 
                  ConnectionURL="jdbc:mysql://localhost:3306/mysql" 
                  LoginDelayMillis="-1" 
                  CloseLongActiveConnection="false" 
                  ConnectionTimeOutSecs="10"> 
        <DBPoolControl MaxCapacity="30" 
                   InitCapacity="20" 
                   MaxIdleTimeSecs="300" 
                   IncrementRate="4" /> 
        <DBAConnection ForcedClose="false" />
</DBConnectionPool>
 
 
2) DataSource
------------------------------------------------------------------------------
<DataSource> 
    <Database> 
            <Vendor>others</Vendor> 
            <ExportName>mysql</ExportName> 
            <DataSourceClassName>
                jeus.jdbc.driver.blackbox.BlackboxConnectionPoolDataSource
            </DataSourceClassName> 
            <Property> 
                <Name>URL</Name> 
                <Type>java.lang.String</Type> 
                <Value>jdbc:mysql://localhost:3306/mysql</Value> 
            </Property> 
            <Property> 
                <Name>DriverClassName</Name> 
                <Type>java.lang.String</Type> 
                <Value>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</Value> 
            </Property> 
            <Property> 
                <Name>Password</Name> 
                <Type>java.lang.String</Type> 
                <Value></Value> 
            </Property> 
            <Property> 
                <Name>User</Name> 
                <Type>java.lang.String</Type> 
                <Value>root</Value> 
            </Property> 
            <DataSourceType>ConnectionPoolDataSource</DataSourceType> 
            <ConnectionPool> 
                <MinPoolSize>4</MinPoolSize> 
                <MaxPoolSize>4</MaxPoolSize> 
                <IncreasingStep>1</IncreasingStep> 
                <ResizingPeriod>10</ResizingPeriod> 
                <OperationTimeout>30000</OperationTimeout> 
                <WaitForFreeConnection> 
                    <WaitingTime>10000</WaitingTime> 
                </WaitForFreeConnection> 
            </ConnectionPool> 
        </Database> 
  </DataSource>
--------------------------------------------------------------------------------------

* Oracle 커넥션풀 샘플 (JEUSMain.xml의 </node>하단에 추가)

    <resource>
        <data-source>
            <database>
                <vendor>oracle</vendor>
                <export-name>오라클UID</export-name>
                <data-source-class-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-class-name>
                <data-source-type>DataSource</data-source-type>
                <database-name>디비명</database-name>
                <data-source-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-name>
                <network-protocol>tcp</network-protocol>
                <user>scott</user>
                <password>tiger</password>
                <port-number>1521</port-number>
                <server-name>아이피 또는 127.0.0.1</server-name>
                <driver-type>thin</driver-type>
                <connection-pool>
                    <pooling>
                        <max>20</max>
                        <step>1</step>
                        <period>500000</period>
                    </pooling>
                </connection-pool>
            </database>
        </data-source>
    </resource>

--------------------------------------------------------------------------------------

* DB2

  1) JEUS 3.x ($JEUS_HOME/config/<NODENAME>/JeusMain.xml
        <Database> 
            <Vendor>db2</Vendor> 
            <ExportName>db2local</ExportName> 
            <DatabaseName>SAMPLE</DatabaseName> 
            <DataSourceClassName>COM.ibm.db2.jdbc.DB2ConnectionPoolDataSource</DataSourceClassName>
            <DataSourceName/> 
            <ServiceName/> 
            <Description/> 
            <NetworkProtocol/> 
            <Password>jeus2013</Password> 
            <PortNumber>포트번호</PortNumber> 
            <ServerName>DB서버 IP</ServerName> 
            <User>db2inst1</User> 
            <DataSourceType>LocalXADataSource</DataSourceType> 
            <ConnectionPool> 
                <MinPoolSize>2</MinPoolSize> 
                <MaxPoolSize>4</MaxPoolSize> 
                <IncreasingStep>1</IncreasingStep> 
                <ResizingPeriod>600000</ResizingPeriod> 
                <OperationTimeout>30000</OperationTimeout> 
                <WaitForFreeConnection> 
                    <WaitingTime>10000</WaitingTime> 
                </WaitForFreeConnection> 
            </ConnectionPool> 
        </Database>  
  2) JEUS 4.x ($JEUS_HOME/config/<NODENAME>/JEUSMain.xml
           <database>
                <vendor>db2</vendor>
                <export-name>db2XADatasource1</export-name>
<data-source-class-name>COM.ibm.db2.jdbc.DB2XADataSource</data-source-class-name>
                <data-source-type>XADataSource</data-source-type>
                <database-name>sample</database-name>
                <description>Customer DB</description>
                <password>db2inst1</password>
                <encryption>false</encryption>
                <port-number>포트번호</port-number>
                <server-name>DB서버 IP</server-name>
                <user>db2inst1</user>
                <connection-pool>
                    <pooling>
                        <min>2</min>
                        <max>4</max>
                        <step>1</step>
                        <period>600000</period>
                    </pooling>
                    <wait-free-connection>
                        <enable-wait>false</enable-wait>
                        <wait-time>10000</wait-time>
                    </wait-free-connection>
                    <operation-to>30000</operation-to>
                </connection-pool>
            </database>
--------------------------------------------------------------------------------------


 

### TIPS ###

--------------------------------------------------------------------------------------

* 파일경로설정

1) 파일 실제경로 (기본값)

- servlet : 제우스홈\webhome\servlet_home\webapps\examples\WEB-INF\classes

- jsp : 제우스홈\webhome\servlet_home\webapps\examples

2) 기존의 examples 컨텍스트 이외에 새로운 aaa라는 컨텍스트를 추가하는 방법 (컨텍스트 설정법)
- WEBMain.xml에서 다음 부분을 추가한다. 
  <context> 
    <context-name>aaa</context-name> 
    <context-path>/aaa</context-path> 
  </context> 
- aaa 컨텍스트의 DD(deployment descriptor)파일을 작성 
  제우스홈\config\노드명\[SERVLET_ENGINE_NAME]\jeus-web-dd_examples.xml 파일을 jeus-web-dd_aaa.xml 파일로 복사  

  하여 편집. context-name, docbase 만 설정하면 됩니다. WEBMain.xml의 이름과 동일해야 함. 
  <?xml version="1.0"?> 
  <!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN" 
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd"> 
  <jeus-web-dd> 
    <context> 
        <context-name>aaa</context-name> 
        <docbase>서버의 물리적 절대경로</docbase> 
        <auto-reload> 
            <enable-reload>true</enable-reload> 
            <check-on-demand>true</check-on-demand> 
        </auto-reload> 
    </context> 
  </jeus-web-dd> 
- WebtoB의 환경설정파일(http.m)의 URI 절에 aaa 컨텍스트 경로를 다음과 같이 추가한다. 
  *URI 
  uri8 Uri = "/aaa/",Svrtype = JSV 
- WebtoB의 환경파일 수정 후에는 반드시 환경파일 컴파일 후 WebtoB를 재기동 : wscfl -i http.m 
- JEUS 를 재기동


--------------------------------------------------------------------------------------

* index.jsp를 자동으로 인식시키려면

- 제우스홈\config\노드명\[SERVLET_ENGINE_NAME]\webcommon.xml 파일에 index.jsp추가

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>

--------------------------------------------------------------------------------------

* jspwork 디렉토리 변경

1. JEUS 3.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/container.xml의
<JSPEngine> 태그 안에 JspWorkDir을 설정하면 됩니다.
<Container>
  ...
  <ContextGroup>
    ...
    <JSPEngine ... 
      JspWorkDir="/app/jwork" 
      ...
    />
2. JEUS 4.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/WEBMain.xml의
<jsp-engine> 태그 안에 <jsp-work-dir>를 설정하면 됩니다.
<web-container>
  <context-group>
    ...
    <jsp-engine>
      ...
      <jsp-work-dir>/app/jwork</jsp-work-dir>
      ...
    </jsp-engine>
--------------------------------------------------------------------------------------

* 폴더관리 (webtob, jeus 연동시)

- image, js, css, html 등은WebToB홈\docs 에 폴더로 관리해서 WEBTOB가 처리

- jsp, servlet은 context를 별도 설정 (컨텍스트 설정법 참조)해서 JEUS가 처리

--------------------------------------------------------------------------------------

* 오라클 데이터베이스 사용시 C:/jeus/lib/datasource 폴더에 classes12.zip 복사

--------------------------------------------------------------------------------------

* trouble shooting

- Out Of Memory 에러

  JVM에서 사용할 수 있는 memory가 부족할 때 발생합니다. 
  이것을 해결하는 방법으로는 버전별로 다음과 같이 JEUS 환경 파일에서
  추가하면 됩니다. -Xms가 min 값이고 -Xmx가 max 값입니다.
  1) JEUS 3.x ($JEUS_HOME/config/<HOSTNAME>/JeusMain.xml)
  <JeusSystemConfig>
      <NodeConfig>
          ...
          <EngineContainer>
              ...
              <CommandOption>-Xms256m -Xmx256m<CommandOption>
  2) JEUS 4.x ($JEUS_HOME/config/<HOSTNAME>/JEUSMain.xml)
  <jeus-system>
      <node>
          ...
          <engine-container>
             ...
              <command-option>-Xms256m -Xmx256m<command-option>
- 노드명에 '-' 문자를 썼을 경우 또는 노드명에 공백이 있는 경우

  wscfl -i http.m 부분에서 오류 -> 노드명을 ""으로 묶어준다.

- 8080포트 사용하려고 할때 XDB 인증창이 뜬다면... 

  =====> 오라클의 XDB포트와 충돌하는 경우이므로 오라클의 XDB포트를 아래와 같이 변경해준다.

  [시작] -> [프로그램] -> [Oracle - OraHome92] -> [Configuration and Migration Tools] 

  -> [Database Configuration Assistant]   선택

  프로그램이 실행이되면.....

  [다음] 버튼을 Click -> [데이터베이스의 데이이터베이스 옵션구성] 선택 -> [사용 가능한 데이터베이스] 선택 

  -> [표준데이터베이  스 기능...] 버튼을 Click -> Oracle XML DB 의 [사용자 정의 ...] 버튼을 Click 

  -> [포트 번호 구성] 항목의 [사용자 정의 값 지정] 을 선택하셔서 HTTP 포트를 바꿔줍니다. 

  그리고 FTP 및 WebDAV 포트는 기본 설정인 2100 을 사용합니다. -> [확인] 버튼을 Click 하시고 

  [다음] 버튼을 Click 하셔서 데이터베이스를 실행할 기본모드를 선택하시고 [완료] 버튼을 눌러주시면 

  요약 메세지창이 뜨고 [확인] 버튼을 눌러주시면 XDB 의 Port 설정이 끝나게 됩니다.

- 다음과 같은 nullpointer exception 발생시

  <<__Exception__>>
  java.lang.NullPointerException
          at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:20
  5)
          at javax.servlet.GenericServlet.log(GenericServlet.java:300)
          at javax.servlet.GenericServlet.init(GenericServlet.java:257)
          at jeus.servlet.common.WebContainerManager.startContainer(WebContainerMa
  nager.java:538)
          at jeus.servlet.syscontext.SystemContext.startup(SystemContext.java:64)
          at jeus.servlet.deployment.SystemWebContainer.startup(SystemWebContainer
  .java:35)
          at jeus.server.SystemEngineController.startEngine(SystemEngineController
  .java:26)
          at jeus.server.JeusServer.boot(JeusServer.java:720)
          at jeus.server.ControlThread.acceptRequests(ControlThread.java:181)
          at jeus.server.ControlThread.run(ControlThread.java:86)
  java.lang.NullPointerException : null
  [SystemEngineController] fail to start System Engine [devserver_system_engine] :
   jeus.server.JeusServerException
  <<__!Exception__>>
  [2005.05.26 10:30:05][2] [ControlThread] command (210.117.198.62:1063) : disconn
  ect()

 =====> j2sdk1.4.1_07 이하 버젼으로 jdk를 다시 설치한 수 jeus/webtob 다시설치 해보세요.

- C:\Program Files\Java\j2re1.4.1_07\bin\server\jvm.dll 파일을 찾지 못할때

  =====> C:\j2sdk1.4.1_07\jre\bin\server 폴더를 카피해서 

             C:\Program Files\Java\j2re1.4.1_07\bin 폴더에 복사하세요.

--------------------------------------------------------------------------------------

* 클래스파일 변경시 실시간으로 변경 반영

소스가 WEB-INF/classes 아래에 있으면 리부팅이 필요 없습니다. 
단, 확인 하실 것이 container.xml(WEBMain.xml)에 context 태그 내에 AutoReload="true"가 설정되어 있으면 됩니다.
WEB-INF/lib/*.jar는 라이브러리와 같이 수정하지 않는다는 의미를 포함하고 있으므로(J2EE 스펙에 준하면...) 
jar 파일 내의 수정은  반드시 제우스를 리부팅 해야 적용됩니다.
--------------------------------------------------------------------------------------

* 인클루드된 파일 변경시 즉시 적용(<%@ include 자동 반영하기)

JSP의 include의 방식에는 <%@ include (action), <jsp:include (directive) 가 있다.

이 중 <jsp:include (action) 는 include하는 JSP(a.jsp)와 include되는 JSP(b.jsp)가 각각 별도의 servlet으로 변환된다.
a.jsp가 수행 도중 b.jsp의 include 구문을 만나면 b.jsp로 제어권이 넘어가서 수행된 후 다시 a.jsp로 제어권이 넘어와서 계속 수행된다.
그래서 b.jsp가 변경된 경우 변경사항이 자동으로 반영된다.

그리고 <%@ include (directive)는 include하는 JSP(a.jsp)와 include되는JSP(b.jsp)가  하나의 servlet으로 변환되어서 a.jsp 내에 b.jsp가 완전히 포함되는 형태로 변환된다.
<%@ include (directive)의 목적은 JSP가 Servlet으로 변환되어 컴파일 될 때에
특정 코드나 text를 포함하기 위해서 이다.
따라서 b.jsp가 변경된 경우 a.jsp는 b.jsp가 변경되었는지 모르기 때문에 include 된 JSP의 변경시 이것을 인지하지 못한다.

<%@ include (directive) 를 사용하는 경우 JSP container가 include된 파일이 변경된경우 자동으로 반영해 주기 위해서는 include하는 파일이 수행될 때 마다 include된 파일의 변경 여부를 검사해서변경되었다면 include 하는 파일을 recompile 해 주어야 한다.
이것은 JSP container에게는 상당히 부하를 주는 작업이다.
그래서 JSP Spec에서는 include된 파일의 변경시 반영 여부는 명시하지 않고 있다.

JEUS에서는 개발과 운영의 편의성을 위해서 이것을 옵션으로 지정하여 변경시 자동 반영이 되게 설정할 수 있다.
하지만 이 옵션을 true로 설정하는 경우 불필요한 검사가 들어가게 되므로 수행 속도에 지장을 주게됩니다. 반드시 JSP 파일의 변경이 빈번한 경우에만 설정하면 된다.

1. JEUS 3.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/container.xml에 설정
---------------------------------------------------------
<Container>
    ...
    <ContextGroup>
        ...
        <JSPEngine ...
            CheckIncludedJspFile="true"
            ... />
2. JEUS 4.x
$JEUS_HOME/config/<HOSTNAME>/<SERVLET_ENGINE_NAME>/WEBMain.xml에 설정
---------------------------------------------------------
<web-container>
    ...
    <context-group>
        ...
        <jsp-engine>
            ...
            <check-included-jspfile>true</check-included-jspfile>
            ...
        </jsp-engine>
        ...
    </context-group>
    ...
</web-container>
--------------------------------------------------------------------------------------

* http.m 샘플

*DOMAIN
WebtoB

*NODE
devserver WEBTOBDIR="C:/webtob", 
  SHMKEY = 54000,
  DOCROOT="C:/tmax/webdocs",
  IndexName="index.jsp,index.html,index.htmm",
  PORT = "80", 
  LOGGING = "log1",
  ERRORLOG = "log2",
  HTH = 1,
  JSVPORT = 9900

*SVRGROUP
htmlg  NODENAME = devserver, SvrType = HTML
cgig  NODENAME = devserver, SVRTYPE = CGI
ssig  NODENAME = devserver, SVRTYPE = SSI
jsvg  NODENAME = devserver, SVRTYPE=JSV

*SERVER
html  SVGNAME = htmlg, MinProc = 3, MaxProc = 10
cgi  SVGNAME = cgig, MinProc = 3, MaxProc = 10
ssi  SVGNAME = ssig, MinProc = 3, MaxProc =10
MyGroup  SVGNAME=jsvg, MinProc=10, MaxProc=10

*URI
uri1  Uri = "/cgi-bin/", Svrtype = CGI
uri2  Uri="/examples/", Svrtype=JSV
uri3  Uri="/", Svrtype=JSV

*ALIAS
alias1  URI = "/cgi-bin/", RealPath = "C:/webtob/cgi-bin/"

*LOGGING
log1  Format = "DEFAULT", FileName = "C:/webtob/log/access.log", Option = "sync"
log2  Format = "ERROR", FileName = "C:/webtob/log/error.log", Option = "sync"

*EXT
htm  MimeType = "text/html", SvrType = HTML
--------------------------------------------------------------------------------------

* JEUSMain.xml 샘플

<?xml version="1.0"?>
<!DOCTYPE jeus-system PUBLIC "-//Tmax Soft, Inc.//DTD JEUS Main Config 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-main-config.dtd">
<jeus-system>
    <node>
        <name>devserver</name>
        <class-ftp>true</class-ftp>
        <sequential-start>true</sequential-start>
        <enable-webadmin>true</enable-webadmin>
        <system-log>
            <level>debug</level>
        </system-log>
        <engine-container>
            <name>container1</name>
            <engine-command>
                <type>servlet</type>
                <name>engine1</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
    </node>
</jeus-system>

--------------------------------------------------------------------------------------

* WEBMain.xml 샘플

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>MyGroup</group-name>
        <group-docbase>webapps</group-docbase>
        <session-config>
            <timeout>20</timeout>
            <shared>true</shared>
        </session-config>
        <logging>
            <error-log>
                <target>stdout</target>
                <level>information</level>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
            </error-log>
            <user-log>
                <target>file</target>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
            </user-log>
            <access-log>
                <target>file</target>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
        <context>
            <context-name>examples</context-name>
            <context-path>/examples</context-path>
        </context>
  <context> 
   <context-name>ngi</context-name> 
   <context-path>/</context-path> 
  </context> 
        <webserver-connection>
            <webtob-listener>
                <listener-id>webtob1</listener-id>
                <port>9900</port>
                <hth-count>1</hth-count>
                <webtob-address>127.0.0.1</webtob-address>
                <registration-id>MyGroup</registration-id>
                <thread-pool>
                    <min>4</min>
                    <max>10</max>
                    <step>2</step>
                    <max-idle-time>30000</max-idle-time>
                    <max-wait-queue>4</max-wait-queue> 
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
    </context-group>
</web-container>
--------------------------------------------------------------------------------------

### 실무 적용 예 (버츄얼호스팅 사용) ###

-------------------------------------------------------------------------------------- 

프로젝트 실제환경을 로컬에서 구현해 작업해야 하는 상황에서...

두대의 IBM서버로 돌아가는 JEUS/WEBTOB의 환경설정 입니다.

<<< 실제환경 >>>

---------------------------------------------------------------------------

- 서버1 : WindowsServer2003Standard, 웹서버 (WEBTOB)

- 서버2 : WindowsServer2003Standard, 웹컨테이너 (JEUS), DB(Oracle9i)

- 두 서버는 9999포트를 통해 연동한다.

- images,css,js는 서버1에 jsp,java는 서버2에 위치시킨다.

- 서버구조는 1 WEBSERVER, 2 CONTAINER (원래 4개에서 필요한 두개만 가동)

- 윈도우 hosts파일에 localhost2, localhost3 추가

----------------------------------------------------------------------------

<<< sample.m >>>

*DOMAIN
WebtoB

*NODE
realchokyCompaq
  WebtobDir="C:/webtob",
  Shmkey=54000,
  Docroot="C:/center",
  HTH=1,
  port="9900",
  JSVPort=9999,
  IndexName="index.jsp,index.htm,index.html",
  Logging="log1",
  ErrorLog="log2"

*VHOST
center
  NodeName="realchokyCompaq",
  HostName="localhost2",
  DocRoot="C:/center",
  Port="9900",
  SSLFlag=N,
  IndexName="index.jsp,index.htm,index.html"

admin
  NodeName="realchokyCompaq",
  HostName="localhost3",
  DocRoot="C:/admin",
  Port="9900",
  IndexName="index.jsp,index.htm,index.html"

*SVRGROUP
htmlg
  NodeName="realchokyCompaq",
  SvrType=HTML

jsvg
  NodeName="realchokyCompaq",
  SvrType=JSV,
  VHostName=center

jsvg2
  NodeName="realchokyCompaq",
  SvrType=JSV,
  VHostName=admin

*SERVER
html
  SvgName=htmlg,
  MinProc=30,
  MaxProc=60

Center
  SvgName=jsvg,
  MinProc=30,
  MaxProc=30,
  HttpInBufsize=0,
  HttpOutBufsize=0

Admin
  SvgName=jsvg2,
  MinProc=10,
  MaxProc=10,
  HttpInBufsize=0,
  HttpOutBufsize=0

*URI
images
  Uri="/images/",
  SvrType=HTML

center
  Uri="/",
  SvrType=JSV,
  VhostName=center

admin
  Uri="/",
  SvrType=JSV,
  VhostName=admin

*LOGGING
log1
  FileName="C:/webtob/log/access.log",
  Format="DEFAULT",
  Option="sync"

log2
  FileName="C:/webtob/log/error.log",
  Format="ERROR",
  Option="sync"

*EXT
htm
  Mimetype="text/html",
  Svrtype=HTML

jsp
  Mimetype="application/jsp",
  Svrtype=JSV

<<< JEUSMain.xml >>>

<?xml version="1.0"?>
<!DOCTYPE jeus-system PUBLIC "-//Tmax Soft, Inc.//DTD JEUS Main Config 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-main-config.dtd">
<jeus-system>
    <node>
        <name>realchokyCompaq</name>
        <class-ftp>true</class-ftp>
        <sequential-start>true</sequential-start>
        <system-log>
            <level>debug</level>
        </system-log>
        <engine-container>
            <name>container1</name>
            <engine-command>
                <type>servlet</type>
                <name>engine1</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
        <engine-container>
            <name>container2</name>
            <engine-command>
                <type>servlet</type>
                <name>engine2</name>
                <startup-mode>xml</startup-mode>
            </engine-command>
            <tm-config>
                <pooling>
                    <min>10</min>
                    <max>20</max>
                    <step>2</step>
                    <period>600000</period>
                </pooling>
                <active-timeout>300000</active-timeout>
                <commit-timeout>120000</commit-timeout>
                <capacity>20000</capacity>
            </tm-config>
        </engine-container>
    </node>
    <resource>
        <data-source>
            <database>
                <vendor>oracle</vendor>
                <export-name>오라클UID</export-name>
                <data-source-class-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-class-name>
                <data-source-type>DataSource</data-source-type>
                <database-name>디비명</database-name>
                <data-source-name>oracle.jdbc.pool.OracleConnectionPoolDataSource</data-source-name>
                <network-protocol>tcp</network-protocol>
                <user>아이피</user>
                <password>패스워드</password>
                <port-number>1521</port-number>
                <server-name>아이피 혹은 127.0.0.1</server-name>
                <driver-type>thin</driver-type>
                <connection-pool>
                    <pooling>
                        <max>20</max>
                        <step>1</step>
                        <period>500000</period>
                    </pooling>
                </connection-pool>
            </database>
        </data-source>
    </resource>
</jeus-system>

<<< WEBMain.xml (컨테이너 1) >>>

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>Center</group-name>
        <group-docbase>webapps</group-docbase>
        <servlet-home>c:\</servlet-home>
        <context>
            <context-name>Center</context-name>
            <context-path>/</context-path>
        </context>
        <session-config>
            <shared>true</shared>
            <timeout>20</timeout>
        </session-config>
        <webserver-connection>
            <webtob-listener>
                <listener-id>Center</listener-id>
                <port>9999</port>
                <output-buffer-size>0</output-buffer-size>
                <webtob-address>127.0.0.1</webtob-address>
                <thread-pool>
                    <min>30</min>
                    <max>30</max>
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
        <logging>
            <error-log>
                <target>stdout</target>
                <buffer-size>0</buffer-size>
                <level>information</level>
            </error-log>
            <user-log>
                <buffer-size>0</buffer-size>
            </user-log>
            <access-log>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
    </context-group>
</web-container>

<<< jeus-web-dd_Center.xml >>>

<?xml version="1.0"?>
<!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd">
<jeus-web-dd>
    <context>
        <context-name>center</context-name>
        <docbase>center</docbase>
        <auto-reload>
            <enable-reload>true</enable-reload>
            <check-on-demand>true</check-on-demand>
        </auto-reload>
    </context>
</jeus-web-dd>

<<< WEBMain.xml (컨테이너 2) >>>

<?xml version="1.0"?>
<!DOCTYPE web-container PUBLIC "-//Tmax Soft., Inc.//DTD WEB Main Config 4.0//EN"
                               "http://www.tmaxsoft.com/jeus/dtd/4.0/web-main-config.dtd">
<web-container>
    <context-group>
        <group-name>Admin</group-name>
        <group-docbase>webapps</group-docbase>
        <servlet-home>c:\</servlet-home>
        <context>
            <context-name>Admin</context-name>
            <context-path>/</context-path>
        </context>
        <session-config>
            <shared>true</shared>
            <timeout>20</timeout>
        </session-config>
        <webserver-connection>
            <webtob-listener>
                <listener-id>Center</listener-id>
                <port>9999</port>
                <output-buffer-size>0</output-buffer-size>
                <webtob-address>127.0.0.1</webtob-address>
                <thread-pool>
                    <min>30</min>
                    <max>30</max>
                </thread-pool>
            </webtob-listener>
        </webserver-connection>
        <logging>
            <error-log>
                <target>stdout</target>
                <buffer-size>0</buffer-size>
                <level>information</level>
            </error-log>
            <user-log>
                <buffer-size>0</buffer-size>
            </user-log>
            <access-log>
                <buffer-size>0</buffer-size>
                <valid-day>1</valid-day>
                <log-format>
                    <time-format>default</time-format>
                </log-format>
            </access-log>
        </logging>
    </context-group>
</web-container>


 

<<< jeus-web-dd_Admin.xml >>>

<?xml version="1.0"?>
<!DOCTYPE jeus-web-dd PUBLIC "-//Tmax Soft., Inc.//DTD JEUS WEB Deployment Info 4.0//EN"
                             "http://www.tmaxsoft.com/jeus/dtd/4.0/jeus-web-dd.dtd">
<jeus-web-dd>
    <context>
        <context-name>admin</context-name>
        <docbase>admin</docbase>
        <auto-reload>
            <enable-reload>true</enable-reload>
            <check-on-demand>true</check-on-demand>
        </auto-reload>
    </context>
</jeus-web-dd>

'개발도 하냐?' 카테고리의 다른 글

웹로직 DB 접속설정  (0) 2009.11.04
자동화 빌드도구 ANT  (0) 2009.11.04
전자세금계산서/세금계산서 업체 정보리스트  (0) 2009.10.29
Anyframe Doc  (0) 2009.09.16
JSP_MVC 형식  (0) 2009.09.16

국세청 전자세금계산서   http://www.esero.go.kr/    

싸이빌  http://cybill.co.kr/  월 50건무료. 200건 11,000원.  무제한 22,000원 . 기업연동 및 구축전문

얼마에요  http://www.tax2tax.co.kr    70건 1만원/ 140건 2만원/ 기간제한은 없슴.

이지폼   http://www.easyform.co.kr   건당  일반 200원,  회원 110원.

KT 세무로   http://semuro.com 1건에서30건까지는건당300원,31건에서60건까지는200원61건

이상은150원

스피드빌  http://www.speedbill.co.kr/  매월20건4,000원[초과건당300원],매월 50건

10,000원[초과건당 220원]

트루비즈   http://www.truebiz.co.kr/   월 30회- 5천원/ 월60회 -1만원/ 월100회- 1만5

천원/ 월10회이하 년 3만원/

다이렉트 빌   http://directbill.co.kr     월1만원 - 무제한 발송/ 월 30건 5천원/

메이크빌  http://www.makebill.co.kr 월 10건-년3만원/월25건-년5만원/월50건-매월1만원/

월500건-매월 9만원

LG데이콤  http://www.webtax21.com   월 50건 - 월1만원/ 추가 건당 200원/

sERP /WEBcash   http://www.taxbill365.com/   건당 100원/

IT 경영연구소   http://www.erpm.kr/   월  3만원. 프로그램안에서 발송

가비아빌  http://www.gabiabill.com/   월 1만원 - 무제한 발송

엔택스  http://www.entax.co.kr   [무료회계프로그램]   건당 50원/

이지스 효성   http://www.allthegate.com    건당 500원/ 포인트충전후 차감방식

바로빌 http://www.barobill.co.kr/  (한달10건-3,300원/30건-5,500원/50건-9,900원)요금

제 이용안할시1건-550원

한국무역정보통신   http://www.ktneterp.co.kr   ERP사용료 4만원에 전자세금계산서 포함

예정.


'개발도 하냐?' 카테고리의 다른 글

자동화 빌드도구 ANT  (0) 2009.11.04
JEUS 설정  (0) 2009.11.04
Anyframe Doc  (0) 2009.09.16
JSP_MVC 형식  (0) 2009.09.16
Eclipse + JEUS  (0) 2009.08.19

 

Anyframe Java

 

 

Template Guide

 

 

 

 

 

 

Anyframe Java

Ver. 3.2.0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Preface

문서는 Anyframe Template 대한 내용을 담고 있으며, 작성자나 검증자의 실수로 인해 오류가 있을 수도 있음에 양해를 구합니다. 문서에 심각한 오류가 있다고 판단될 경우 Anyframe 포럼에 등록해 주시면 담당자가 적절한 조치를 취할 있도록 것입니다. 문서는 개인적인 용도로 사용될 있으며, 다른 사람에게 배포되어야 하는 경우 반드시 이와 같은 Copyright Notice 포함하도록 합니다. 내용에 대한 자유로운 추가 수정 작업은 허용하나, 문서의 상업적인 사용은 허용하지 않습니다. 상업적 사용시 반드시 Anyframe Portal Site 통해 요청하셔야 함에 유의하시기 바랍니다.

 

 

Copyright 2008, www.anyframejava.org - Site maintained by SAMSUNG SDS

 

 

제 1 장    개 요    5

1.1 목 적    5

1.2 유의사항    5

제 2 장    설치하기    6

2.1 설치 환경    6

2.2 Template 설치    6

2.2.1 Basic Template설치    6

2.2.2 MiPlatform Template설치    7

2.3. Template실행    9

제 3 장    Basic Template 소개    11

3.1. 개 요    11

3.2. 구 현    11

3.2.1. 비즈니스 레이어    11

3.2.2. 프리젠테이션 레이어    13

제 4 장    MiPlatform Template 소개    15

4.1. 개요    15

4.2. 구 현    15

4.2.1. 비즈니스 레이어    15

4.2.2. 프리젠테이션 레이어    17

제 5 장    Base Framework    19

5.1. Spring IoC    19

5.2. Spring AOP    20

5.3. Hibernate    23

5.4. Query 서비스    26

5.5. MiPQueryService    28

5.6. Spring MVC    30

5.7. MiPlatform    34

5.8. 기타    36

별첨-1. 주요 클래스 다이어그램 Category @Basic Template    38

별첨-2. 주요 클래스 다이어그램 Category @MiPlatform Template    39

제 1 장    개 요

1.1 목 적

Anyframe Java에 대한 대표적인 적용 방안을 제시함으로써 Anyframe Java를 기반으로 어플리케이션을 개발하는 프로젝트에 효과적인 개발구조 가이드를 제시하고 개발 초기에 해당 프로젝트에서 개발 템플릿을 정의하는데 소요되는 시간을 줄이고자 구현 기준 샘플 프로젝트를 Template으로 제공하고, 설치에서부터 구현 기능 및 활용 서비스에 대한 설명을 하고자 한다.

Anyframe Java 3.2.0 (jdk 1.4)은 다음과 같이 기본 템플릿과 MiPlatform 템플릿 두 가지로 제공된다. 또한 기본 템플릿은 웹 어플리케이션에 따라 두 가지로 나뉜다.

 

  • 기본 템플릿
    • 서비스 어플리케이션 : Spring 기반, QueryService, Hibernate를 이용한 DB Access Layer
    • 웹 어플리케이션
      • SpringMVC 기반, JSP를 이용하여 구현
      • Struts 기반, JSP를 이용하여 구현
  • MiPlatform 템플릿
    • 서비스 어플리케이션 : Spring 기반, MiPQueryService를 이용한 DB Access Layer
    • 웹 어플리케이션 : SpringMVC 기반, MiPlatform을 이용하여 구현

 

1.2 유의사항

문서에서 사용된 코드와 아키텍처 스타일은 다양한 프레임워크 기능의 사용예와 아키텍처의 유연성을 고려한 샘플이며 성능에 최적화되어 제공하는 것은 아니므로 실제로 프레임워크를 적용하여 프로젝트 수행 디자인 코드와 성능에 대한 여러 요구 사항들(주로 비기능적인 요구조건) 적절히 고려하여 어플리케이션을 구축하여야 한다

 

제 2 장    설치하기

2.1 설치 환경

JDK: JDK 1.4.2 이상

Web Container: Tomcat 5.0.28 이상, WebLogic 8.1.6 이상

DataBase: HSQL DB 1.8.0.4 이상, Oracle 8i 이상

IDE : Eclipse 3.3 이상(프레임워크에서 제공하는 플러그인이 포함된 Eclipse 권장)

Anyframe : Anyframe Core / Web 3.2.0 이상

Anyframe 설치는 Anyframe Portal Site의 설치문서 참고

※ MiPlatform의 경우 MiPlatform 클라이언트 프로그램이 설치되어야 한다. MiPlatform은 상용프로그램이므로 사용자가 S/W를 구입하여 설치하였다고 가정한다.

2.2 Template 설치

2.2.1 Basic Template설치

  • 압축파일 해제
    - 적당한 폴더를 선택하여 템플릿 압축 해제 실시
    à [템플릿 압축해제 폴더]
  • Eclipse 실행
  • 프로젝트 Import
  1. Eclipse 메뉴의 File – Import 선택
  2. Existing Projects into Workspace 선택 후 Next 버튼 클릭
  3. Select root directory의 Browse버튼 클릭 하고 [템플릿 압축해제 폴더] 선택
  4. 하단 Projects 리스트에서 "anyframe-template-service", "anyframe-template-web-struts", "anyframe-template-web-springmvc"를 선택하고 Finish 버튼 클릭
  • 라이브러리 설정
  1. Anyframe Core와 Web 설치 폴더의 모든 jar 파일을 [템플릿 압축해제 폴더]/anyframe-template-web-struts/src/webapp/WEB_INF/lib와 [템플릿 압축해제 폴더]/anyframe-template-web-springmvc/src/webapp/WEB_INF/lib로 복사
  2. Eclipse 메뉴의 Window – Preferences선택
  3. 좌측의 트리 메뉴에서 Java – Build Path – User Libraries 선택
  4. New 버튼 클릭하고 User Library Name에 'TEMPLATE_LIB' 입력
  5. 우측의 Add JARs 버튼을 클릭하여 Anyframe Core와 Web 설치 폴더의 모든 jar 파일을 선택
  • Web Container 설정
  1. Eclipse 메뉴의 Window – Preferences선택
  2. 좌측의 트리 메뉴에서 Server – Installed Runtimes 선택
  3. Add 버튼 클릭하고 Apache Tomcat 5.0 선택하고 Next 버튼 클릭
  4. Browse 버튼을 클릭하여 설치된 Tomcat Root 폴더를 선택

    ※ Eclipse의 default JRE 버전이 JDK 1.4일 경우 Tomcat 5.0을,

JDK 1.5일 경우 Tomcat 5.5 버전을 사용한다.

 

  • 사용자 환경에 맞추어 서비스 배포
  1. Eclipse에서 anyframe-template-service프로젝트의 build.xml파일을 열어서 anyframe.lib의 위치를 Anyframe Core와 Web 설치 폴더로 변경
    (artifacts.dir 변수는 오픈 소스 자바 코드 코드커버리지 툴킷인 emma를 사용하기 위한 변수로, emma를 통해 생성되는 리포트 파일이 만들어질 위치이다.)
  2. Eclipse의 Package Explorer에서 build.xml을 선택하고 마우스 오른쪽 버튼을 클릭하여 Run As – Ant Build를 선택하고 all target을 선택하여 Run 버튼 클릭

※ 템플릿을 구성하는 서비스 코드 및 속성 정의가 변경 됐을 경우 all target을 실행시키면 자신의 환경에 수정 내용을 배포할 수 있다.

※ Junit 테스트와 emma를 통한 리포팅을 모두 적용하려면 test target을 실행시키면 된다.

2.2.2 MiPlatform Template설치

  1. 압축파일 해제
    - 적당한 폴더를 선택하여 템플릿 압축 해제 실시
    à [템플릿 압축해제 폴더]
  2. Eclipse 실행
  3. 프로젝트 Import
    1. Eclipse 메뉴의 File – Import 선택
    2. Existing Projects into Workspace 선택 후 Next 버튼 클릭
    3. Select root directory의 Browse버튼 클릭 하고 [템플릿 압축해제 폴더] 선택
    4. 하단 Projects 리스트에서 "anyframe-template-mi-service","anyframe-template-mi-web"를 선택하고 Finish 버튼 클릭

     

  4. 라이브러리 설정
    1. Anyframe Core와 Web 설치 폴더의 모든 jar 파일을 [템플릿 압축해제 폴더]/anyframe-template-mi-web/src/webapp/WEB_INF/lib로 복사
    2. Eclipse 메뉴의 Window – Preferences선택
    3. 좌측의 트리 메뉴에서 Java – Build Path – User Libraries 선택
    4. New 버튼 클릭하고 User Library Name에 'TEMPLATE_LIB' 입력
    5. 우측의 Add JARs 버튼을 클릭하여 Anyframe Core와 Web 설치 폴더의 모든 jar 파일을 선택
      ※ MiPlatform을 사용할 경우 MiPlatform의 library가 필요하다. MiPlatform은 상용소프트웨어이므로 구매하여 추가하기 바란다.

 

  1. Web Container 설정
    1. Eclipse 메뉴의 Window – Preferences선택
    2. 좌측의 트리 메뉴에서 Server – Installed Runtimes 선택
    3. Add 버튼 클릭하고 Apache Tomcat 5.0 선택하고 Next 버튼 클릭
    4. Browse 버튼을 클릭하여 설치된 Tomcat Root 폴더를 선택

    ※ Eclipse의 default JRE 버전이 JDK 1.4일 경우 Tomcat 5.0을,

JDK 1.5일 경우 Tomcat 5.5 버전을 사용한다.

 

  1. 사용자 환경에 맞추어 서비스 배포
    1. Eclipse에서 anyframe-template-mi-service프로젝트의 build.xml파일을 열어서 anyframe.lib의 위치를 Anyframe Core와 Web 설치 폴더로 변경
    2. Eclipse의 Package Explorer에서 build.xml을 선택하고 마우스 오른쪽 버튼을 클릭하여 Run As – Ant Build를 선택하고 all target을 선택하여 Run 버튼 클릭

    ※ 템플릿을 구성하는 서비스 코드 및 속성 정의가 변경 됐을 경우 all target을 실행시키면 자신의 환경에 수정 내용을 배포할 수 있다.

2.3. Template실행

  1. 테이블 및 데이터 생성
  • Hsql DB의 경우,
    • [템플릿 압축해제 폴더]/anyframe-template-service/DATABASE/db 폴더 (MiPlatform Template의 경우 [템플릿 압축해제 폴더]/anyframe-template-mi-service/DATABASE/db 폴더)의 insertvalue.sql의 내용을 sampledb.script의 기존 내용(DDL)에 이어 붙여 넣은 후 runHsqlDB.cmd 파일 실행
  • Oracle DB의 경우,
    • [템플릿 압축해제 폴더]/anyframe-template-service/DATABASE/db 폴더의 templateDB.sql을 이용하여 테이블 및 데이터 생성

    

※ 사용하는 DBMS의 종류에 따라 Data Source 설정을 바꿔야 한다.

anyframe-template-service/src/main/resources/spring/common/context-

datasource.xml 파일에 있는 dataSource의 속성을 사용자의 환경에 맞게

수정한 후 build.xml을 선택하고 마우스 오른쪽 버튼을 클릭하여

Run As – Ant Build 를 실행해 다시 배포한다.

 

  1. Web Container 구동
    1. Eclipse의 Package Explorer에서 anyframe-template-web-springmvc 또는 anyframe-template-web-struts 프로젝트 선택
      MiPlatform Template의 경우 anyframe-template-mi-web 프로젝트 선택.
    2. src/webapp/login.jsp를 선택하고 마우스 오른쪽 버튼을 클릭하여 Run AS – Run on Server 을 선택하여 실행. 또는 Internet Explorer에서 anyframe-template-web-springmvc 또는 anyframe-template-web-struts 프로젝트의 주소를 입력하여 로그인 화면이 나타나는 것을 확인.
      MiPlatform Template의 경우 anyframe-template-mi-web 프로젝트 주소.
      예)
      http://localhost:8080/anyframe-template-web-springmvc
      http://localhost:8080/anyframe-template-mi-web
  2. 실행 결과

① 로그인 할 수 있는 화면

② ID, Password에 'test/test123'을 입력하고 Login 버튼 클릭 시 Welcome

페이지로 이동

③ 좌측 메뉴를 클릭하여 이용

제 3 장    Basic Template 소개

3.1. 개 요

Anyframe Template은 기본적으로 Eclipse의 프로젝트 형태로 제공된다. Anyframe Basic Template은 비즈니스 레이어를 구현한 Service(anyframe-template-service)프로젝트와 프리젠테이션 레이어를 구현한 Web(anyframe-template-web-springmvc와 anyframe-template-web-struts)프로젝트로 구성되어 있다.

Service프로젝트는 Anyframe Core 3.2.0의 Spring IoC, Spring AOP, Hibernate, Query 서비스를 이용하여 구현하였고, Web프로젝트는 Spring MVC를 기반으로 구현한 것과 Struts기반으로 구현한 것, 이렇게 두 가지로 구성되어 있다.

Template에서 구현한 서비스는 제품(Product)의 등록, 수정, 삭제, 조회 및 분류체계(Category)의 등록, 수정, 삭제, 조회 기능으로 일반적으로 많이 사용되는 기능을 중심으로 하되 확대가 용이한 구조로 구현하였다.

3.2. 구 현

3.2.1. 비즈니스 레이어

비즈니스 서비스는 아래 그림과 같이 도메인 모델, 서비스 인터페이스 클래스, 서비스 구현클래스, DAO 인터페이스 클래스 및 DAO 구현 클래스로 구성되어 있다

1) 제품(Product) 관련 클래스

종류

클래스

클래스 설명

도메인 모델

Product 

Product 테이블 컬럼과 동일한 멤버변수와 그에 대한 Setter/Getter 메소드로 구성

서비스 인터페이스

ProductService 

Product 관리 기능을 제공하기 위한 인터페이스로 Create/Find/Update/Remove 기본 CRUD 메소드에 카테고리별 제품 수량 정보 추출을 위한 countProductListByCategory 카테고리별 제품 리스트 제공을 위한 findProductList 메소드로 구성

서비스 구현

ProductServiceImpl

ProductService implements 하는 클래스로 ProductDAO 메소드를 호출하여 DB처리를 하도록 하고, IIdGenerationService 이용하여 Product 정보를 생성하고, MessageSource 이용하여 오류메세지를 처리하는 기능 구현

Spring IoC 활용

DAO 인터페이스

ProductDAO 

Product관련 DB 조작하기 위한 메소드를 정의한 인터페이스

DAO 구현

ProductDAOHibernateImpl 

ProductDAO implements 하는 클래스로 HibernateDaoSupport 상속받아서 DB 조작하고 propertiesService 이용하여 findProductList 메소드내에서 Page관련 정보를 처리함

Hibernate 활용, Spring IoC 활용

ProductDAOQueryImpl

ProductDAO implements 하는 클래스로 AbstractDAO 상속받아서 DB 조작하고 propertiesService 이용하여 findProductList내에서 Page관련 정보를 처리함

Query서비스 활용, Spring IoC 활용

※ Category 관련 클래스와 Code 관련 클래스도 동일하게 구성.

 

2) 공통(Common) 클래스

종류

클래스

클래스 설명

Data Transfer Object

SearchVO

검색 기능과 관련된 정보를 가진 클래스로 멤버변수의 Setter/Getter 메소드로 구성

서비스구현

EmpException

BaseException 상속받은 클래스. 여러가지 입력 파라미터를 받는 생성자로 구성

EmpUtil 

Null 처리를 위한 메소드 여러가지 String utility 메소드를 담고 있음

ExceptionTransfer

Exception 발생되었을 Spring AOP 의해 transfer 메소드가 호출된다. Exception 별로 정의된 메시지를 MessageSource 이용하여 처리를 하도록

Spring AOP, Spring IoC 활용

LoggingAspect 

클래스의 메소드가 호출 되었을 Spring AOP 의해 beforeLogging 메소드가 실행된다. 호출된 클래스와 메소드명 그리고 호출 시점에 입력된 parameter 값까지 추출하여 Logging하는 클래스임

Spring AOP, Spring IoC 활용

※ 이외, 클래스들은 Security 관련 클래스로 서비스 인터페이스 클래스인 AuthenticationService와 그 구현클래스인 DBAuthenticationService, java.util.Properties를 상속받은 Credential 클래스로 구성되어 있다.

 

3.2.2. 프리젠테이션 레이어

Anyframe Basic Template에서 제공하는 프리젠테이션 레이어 어플리케이션은 Spring MVC 기반으로 구현된 것과 Struts를 기반으로 구현된 것, 두 가지가 있다. 이 중 Spring MVC 기반으로 구현된 Template에 대해서 설명하도록 한다. Spring MVC 기반의 프리젠테이션 레이어는 아래 그림 같이 DispatcherServlet, Interceptor, Controller, JSP, Custom Tag Library로 구성되어 있다.

 

 

 

 

 

 

 

 

 

 

 

[프리젠테이션 레이어 구성]

 

1) 제품(Product) 관련 구성요소

종류

구성요소

Controller 

ProductController.java

Product 도메인에 관련된 기본 CRUD 기능을 호출하는 각각의 addView(), add(), get(), update(), list(), delete() 메소드로 구성되며 double submit 방지 기능이 적용되어 있지 않다.

JSP 

addProduct.jsp

제품 등록을 위한 화면으로 ProductController add()메소드를 호출하여 제품등록처리를 한다

listProduct.jsp

제품리스트를 조회하기 위한 화면으로 ProductController

list()메소드를 호출하여 리스트를 보여준다

updateProduct.jsp

제품 수정을 위한 화면으로 ProductController get()메소드를 이용하여 내용을 조회하고 update()메소드를 호출하여 수정되도록 한다

Config File 

product-servlet.xml

제품(Product)관련 웹페이지 요청에 대한 ProductController 매핑정보가 정의 되어 있으며, ProductController Bean에서 사용하는 서비스 Bean정보와 프로퍼티 정보가 정의되어 있다.

2) 카테고리(Category) 관련 구성요소

종류

구성요소

Controller 

CategoryController.java

카테고리 도메인에 관련된 기본 CRUD 기능을 호출하는 각각의 add(), update(), list(), delete() 메소드로 구성되며 Add, Update, Delete 대한 double submit 방지 기능이 적용되어 있다

JSP 

addCategory.jsp

카테고리 등록을 위한 화면으로 CategoryController add()메소드를 호출하여 제품등록처리를 한다

listCategory.jsp

카테고리 리스트를 조회하기 위한 화면으로 CategoryController

list()메소드를 호출하여 리스트를 보여준다

updateCategory.jsp

카테고리 수정을 위한 화면으로 CategoryController get()메소드를 이용하여 내용을 조회하고 update()메소드를 호출하여 수정되도록 한다

Config File 

category-servlet.xml

카테고리 관련 웹페이지 요청에 대한 CategoryController 매핑정보가 정의 되어 있으며, CategoryController Bean에서 사용하는 서비스 Bean정보와 프로퍼티 정보가 정의되어 있다.

 

3) 공통(Common) 구성요소

종류

구성요소

Interceptor 

AuthorizationInterceptor.java

페이지 권한처리를 위한 인터셉터로 세션에서 로그인 아이디를 받아서 권한 정의된 사용자 여부를 체크

LoginInterceptor.java

중간접속 차단을 위해 만든 Login여부 체크 인터셉터

Config File 

common-servlet.xml

Spring MVC에서 제공하는 기본적인 Resolver들을 정의하여 사용한다. (ex> viewResolver, paramResolver, handlerMapping)

security-servlet.xml

사용자 로그인에 관련된 매핑 정보가 정의되어 있다.

 

제 4 장    MiPlatform Template 소개

4.1. 개요

Anyframe MiPlatform Template은 비즈니스 레이어를 구성하는 Service(anyframe-template-mi-service)프로젝트와 프리젠테이션 레이어를 구성하는 Web(anyframe-template-mi-web)프로젝트로 구성되어 있다.

Service프로젝트는 Anyframe Core 3.2.0의 Spring IoC, Spring AOP, MiPQueryService를 이용하여 구현하였고, Web프로젝트는 Anyframe Web 3.2.0의 Spring MVC를 기반으로 구현되어 있다.

Template에서 구현한 서비스는 분류체계(Category)의 등록, 수정, 삭제, 조회 기능으로 일반적으로 많이 사용되는 기능을 중심으로 하되 확대가 용이한 구조로 구현하였다. 단, MiPlatform을 이용한 화면 구성(jsp, xml)에 대해서는 MiPlatform에서 제공하는 툴을 이용하도록 한다.

 

4.2. 구 현

4.2.1. 비즈니스 레이어

비즈니스 서비스는 아래 그림과 같이 서비스 인터페이스 클래스, 서비스 구현클래스, DAO 클래스로 구성되어 있다.

1) 분류체계(Category) 관련 클래스

종류

클래스

클래스 설명

서비스 인터페이스

서비스 구현

CategoryService

Category관리 기능을 제공하기 위한 인터페이스로 CRUD 작업을 하는 saveAll메소드에 카테고리 리스트 제공을 위한 findProductList 메소드로 구성

CategoryServiceImpl

CategoryService implements 하는 클래스로 CategoryDAO 메소드를 호출하여 DB처리를 하도록 한다.

Spring IoC 활용

DAO 클래스

CategoryDAO 

Category 관련 DB 조작하는 로직을 수행하고 IIdGenerationService 사용하여 유일한 아이디를 생성한다.

MiPQueryService활용, Spring IoC 활용

 

2) 공통(Common) 클래스

종류

클래스

클래스 설명

도메인 모델

SearchVO 

검색 기능과 관련된 정보를 가진 클래스로 멤버변수의 Setter/Getter 메소드로 구성

서비스구현

EmpException

BaseException 상속받은 클래스. 여러가지 입력 파라미터를 받는 생성자로 구성

ExceptionTransfer

Exception 발생되었을 Spring AOP 의해 transfer 메소드가 호출된다. Exception 별로 정의된 메시지를 MessageSource 이용하여 처리를 하도록

Spring AOP, Spring IoC 활용

LoggingAspect 

클래스의 메소드가 호출 되었을 Spring AOP 의해 beforeLogging 메소드가 실행된다. 호출된 클래스와 메소드명 그리고 호출 시점에 입력된 parameter 값까지 추출하여 Logging하는 클래스임

Spring AOP, Spring IoC 활용

※ 이외, 클래스들은 Security 관련 클래스로 서비스 인터페이스 클래스인 AuthenticationService와 그 구현클래스인 DBAuthenticationService, java.util.Properties를 상속받은 Credential 클래스로 구성되어 있다.

4.2.2. 프리젠테이션 레이어

MiPlatform Template의 프레젠테이션 레이어는 Spring MVC 기반으로 작성되어 있어 아래 그림 같이 DispatcherServlet, Interceptor, Controller 로 구성되어 있다.

 

 

 

 

 

 

 

 

 

 

 

[프레젠테이션 레이어 구성]

 

1) 카테고리(Category) 관련 구성요소

종류

구성요소

Controller 

CategoryMiPController.java

Category 도메인에 관련된 리스트 출력을 위한 getCategoryLIst()메소드와, 데이터의 일괄 저장을 위한create, update, delete 기능을 동시에 처리하는 updateCategory() 메소드가 정의되어 있다.

Config File 

category -servlet.xml

Category 관련 웹페이지 요청에 대한 Category관련 Controller 대한 매핑정보가 정의 되어 있으며, Controller Bean에서 사용하는 서비스 Bean정보와 프로퍼티 정보가 정의되어 있다.

 

2) 공통(Common) 구성요소

종류

구성요소

Interceptor 

LoginInterceptor.java

중간접속 차단을 위해 만든 Login여부 체크 인터셉터

Config File 

common-servlet.xml

Spring MVC에서 제공하는 기본적인 Resolver들을 정의하여 사용한다. (ex> viewResolver, paramResolver, handlerMapping)

security-servlet.xml

사용자 로그인에 관련된 매핑 정보가 정의되어 있다.

 

제 5 장    Base Framework

본 문서에서는 템플릿에서 활용하고 있는 기능들에 대해서 개발자들이 꼭 알아야 할 사항에 대해서만 기술하므로, 여기서 언급하는 내용에 대한 자세한 가이드는 Anyframe Java 매뉴얼 참고하기 바란다.

5.1. Spring IoC

  1. 개 요
    한 클래스가 특정 작업을 수행하기 위해 필요한 다른 클래스들을 직접 생성하거나 획득하지 않고, 이러한 의존성들을 외부에 정의하고 컨테이너에 의해 공급받는 방법을 IoC(Inversion of Control)라고 한다. 이는 Spring Framework의 핵심적인 개념으로 템플릿에서는 모든 클래스에서 외부 클래스를 참조할 때 이 방법을 이용하고 있다.

 

  1. 서비스 사용 설명
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/common/*.xml
      [템플릿 압축해제 폴더]/src/main/resource/spring/hibernate/*.xml
      [템플릿 압축해제 폴더]/src/main/resource/spring/query/*.xml
    2. 서비스 속성 정의 파일에 bean class 선언
    3. 서비스 속성 정의 파일에 클래스에서 참조하는 다른 클래스 정의
    4. bean class에서 사용하기 위한 Setter 정의

     

     

     

5.2. Spring AOP

  1. 개 요
    비즈니스 로직이 구현된 코드를 수정하지 않고서 특정 클래스 및 메소드를 패턴 매칭 방법으로 정의하여 지정된 패턴이 실행되는 시점에 필요한 공통 작업을 수행하게 해주는 서비스로 템플릿에서는 Logging, Exception, Transaction 등의 처리를 수행하는 샘플을 제시함

 

  1. Logging Aspect
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/common/context-aspect.xml
    2. 서비스 속성 정의 파일에 Logging처리 Class 선언
    3. 서비스 속성 정의 파일에 수행시점을 패턴매칭방법으로 정의
    4. 서비스 속성 정의 파일에 동작시점과 수행 메소드 선언
    5. Logging처리 Class에 수행 메소드 구현

     

     

     

     

 

  1. Exception Aspect
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/common/context-aspect.xml
    2. 서비스 속성 정의 파일에 Exception처리 Class 선언
    3. 서비스 속성 정의 파일에 수행시점을 패턴매칭방법으로 정의
    4. 서비스 속성 정의 파일에 동작시점과 수행 메소드 선언
    5. Exception처리 Class에 수행 메소드 구현
      구현 기능 : Exception을 EmpException, Exception으로 구분하여 처리하며. Exception을 throw하기 전에 ERROR 레벨의 로그를 남김. 각 Exception을 구현 클래스에서 처리하지 않고 정해진 규칙에 맞게 해당하는 Exception key를 찾아 처리함. 따라서 메소드 별 특정 값에 대한 로그 처리는 개별적으로 구현 필요함

     

     

  2. Transaction 관리
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/hibernate/context-transaction.xml
      [템플릿 압축해제 폴더]/src/main/resource/spring/query/context-transaction.xml
    2. 서비스 속성 정의 파일에 Transaction처리 Class 선언
    3. 서비스 속성 정의 파일에 수행시점을 패턴매칭방법으로 정의
    4. 서비스 속성 정의 파일에 동작시점과 수행 메소드 선언

     

     

5.3. Hibernate

  1. 개 요
    Hibernate는 객체지향모델링(Object Oriented Modeling)과 관계형 데이터 모델링 (Relational Data Modeling) 사이의 불일치를 해결해 주는 ORM 도구로 특정 플랫폼에 의존적인 제약을 정의하고 있지 않기 때문에 POJO 기반의 개발이 가능하고 또한 Java에서 지원하는 다양한 Collection 유형을 지원함으로써 객체 모델링을 관계형 모델링으로 매칭하는데 따르는 제약을 최소화하고 있다. 본 Template에서는 Hibernate를 활용하여 CRUD를 구현하는 샘플을 제시함.

 

  1. 서비스 사용 설명
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/hibernate/context-hibernate.xml
    2. 서비스 속성 정의 파일에 매핑 정의 파일 위치 지정
    3. 서비스 속성 정의 파일에 dynamicHibernateService를 위한 설정 파일 지정
    4. 매핑정의 파일 설정(②에서 위치 지정한): hibernate 툴 이용해 자동생성 가능
      [템플릿 압축해제 폴더]/src/main/resource/hibernate/Category.hbm.xml
      테이블 컬럼과의 매핑정보 정의
      CRUD외 Query 정의 (CRUD는 Query 정의 없이 가능)
    5. dynamicHibernateService를 위한 설정 파일 정의(③에서 파일 지정한)
    6. DAO 클래스에서의 사용

     

     

     

     

  2. DataSource 서비스 설정 (Hibernate와 Query에서 모두 사용함)
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/common/context-datasource.xml
    2. DB 관련 정보 설정(HSQL 설정 정보)

    아래QueryService의 'DataSource 서비스 설정'설명 참고.

     

     

     

     

5.4. Query 서비스

  1. 개 요
    쿼리 문이나 객체의 입력만으로 DB 데이터 조작을 가능하게 하는 서비스로 JDBC(Java Database Connectivity)를 이용한 데이터 액세스 수행 부분을 추상화함으로써 간편한 데이터 액세스 방법을 제공하고, JDBC 사용시 발생할 수 있는 공통 에러를 줄여주게 된다. 본 Template에서는 DAO 클래스에서 Query 서비스에서 제공하는 AbstractDAO를 상속받아 CRUD를 구현하는 샘플을 제시함.

 

  1. 서비스 사용 설명
    1. 서비스 속성 정의 파일 생성
    2. 서비스 속성 정의 파일에 매핑 정의 파일 위치 지정
    3. 매핑정의 파일 설정(②에서 위치 지정한)
    4. DAO 클래스에서의 사용

     

     

     

    QueryService의 AbstractDAO에서 제공하는 메소드들을 사용하면 DAO클래스를 간단하게 만들 수 있다. 자세한 내용은 Anyframe Java의 Query서비스 매뉴얼 참고.

     

     

     

     

     

     

 

  1. DataSource 서비스 설정 (Hibernate와 Query에서 모두 사용함)
    1. 서비스 속성 정의 파일 생성
      [템플릿 압축해제 폴더]/src/main/resource/spring/common/context-datasource.xml
    2. DB 관련 정보 설정(HSQL 설정 정보)
    3. Anyframe에서 제공하는 ID Generation 서비스가 사용하는 DataSource는 따로 분리.

     

     

5.5. MiPQueryService

  1. 개 요
    MiPQueryService는 MiPlatform 기반 개발을 위해 Query 서비스를 확장한 서비스이며 query작성만으로 Table에 특정 Data를 insert, update, delete, select할 수 있다.
    기본적으로 QueryService를 확장한 것이기 때문에 설정방법은 QueryService와 유사하다. 설정 XML의 자세한 속성 정보들은 Anyframe Java 의 매뉴얼을 참고하기 바란다.

 

  1. 기본 서비스 사용 설명
    1. 서비스 속성 정의 파일 생성
      [MiPlatform 템플릿 압축해제 폴더]/src/main/resource/spring/context-query.xml
    2. 서비스 속성 정의 파일에 매핑 정의 파일 위치 지정
    3. 매핑 정의 파일 설정(②에서 위치 지정한)
    4. DAO 클래스에서 사용

     

     

    ※ MiPQueryService를 이용해 DB에 값을 전달하기 전, 후에 특정 값을 셋팅해야 하는 경우가 있다. 이 때 위의 CategoryMiPActionCommand 클래스처럼 anyframe.core.query.ria.mip.IMiPActionCommand를 구현한 클래스를 통해 필요한 비즈니스 로직을 추가할 수 있다.

     

5.6. Spring MVC

  1. 개 요
    Spring MVC를 이용하여 프리젠테이션 레이어를 개발 할 때에는 크게 Controller와 Config 파일(Mapping XML), JSP(Custom Tag) 세 개의 파일을 작성해야 한다. 또한 필요에 따라 Interceptor, Validator등을 구현할 수 있다.

 

  1. 기본 서비스 사용 설명
    1. Config 파일(Mapping) 작성
      ⓐ Control Class 정의, ⓑ 호출 Service Bean 정의 ⓒ 사용 프로퍼티 정의
      ⓓ 중복 서브밋 방지 프로퍼티 정의 – 이중 저장 방지를 위한 기능 구현
    2. Controller 구현
      ⓐ Service Bean Setter 정의, ⓑ 폼 입력 데이터 바인딩, ⓒ ModelAndView 객체 리턴
    3. JSP 구현

     

     

     

     

     

     

     

     

     

     

  2. Interceptor 구현
    1. Config 파일(Mapping)에 Interceptor 정의
    2. Interceptor 구현

     

     

     

     

  3. Anyframe Tag Library 사용
    1. Page Navigator Tag 사용
    2. Message Tag 사용

     

 

5.7. MiPlatform

  1. 개 요
    SpringMVC와 MiPlatform을 이용하여 Presentation Layer를 개발 할 때에는 크게 Controller와 Config 파일(Mapping XML), MiPlatform 관련 화면 구성 파일(이는 MiPlatform에서 제공하는 툴을 사용하여 별도로 작성)을 작성해야 한다.

 

  1. 기본 서비스 사용 설명
    1. Config파일(Mapping XML) 작성
      Control Class 정의, 호출 Service Bean 정의
    2. Controller구현
      Service Bean Setter 정의, 비즈니스 서비스 호출 후 Dataset 생성,
      ds_access에 리턴할 Dataset 셋팅

     

     

     

 

5.8. 기타

본 Template은 설명된 서비스 외에도 PropertiesService, IdGenerationService, MessageSource를 이용하여 구현되었다. 각각에 대한 사용 방법은 아래와 같다.

 

  1. Properties Service
    변경 사항이 빈번한 property(여기에선 PAGE_SIZEPAGE_UNIT)에 대해 소스가 아닌 XML에 정의하여 관리할 수 있다.


  2. ID Generation Service
    TableIdGenerationService를 사용하여 Table기반의 유일한 Id를 자동 생성시킬 수 있도록 작성하였다.

 

 

 

  1. MessageSource
    프로젝트에 맞는 message 정의 properties파일을 만들고 이 properties 파일의 위치를 MessageSource bean에서 정의한다.

 



 

 

별첨-1. 주요 클래스 다이어그램
Category @Basic Template

 

별첨-2. 주요 클래스 다이어그램
Category @MiPlatform Template

 

'개발도 하냐?' 카테고리의 다른 글

JEUS 설정  (0) 2009.11.04
전자세금계산서/세금계산서 업체 정보리스트  (0) 2009.10.29
JSP_MVC 형식  (0) 2009.09.16
Eclipse + JEUS  (0) 2009.08.19
약도 만들기  (0) 2009.08.14

MVC의 개요

기존의 모델1 개발방식에 익숙하신 분들을 위해서 보다 효율적이고 유지보수하기 편한 MVC기법으로 웹프로그래밍 하는 방법에 대해서

강좌를 시작하려고 합니다.

그럼 기존의 모델1과 MVC는 도대체 뭐가 다르냐고 반문하시는 분들이 계실겁니다.

크게 다른점은 모델1의 경우에 jsp파일 하나에 모든 내용이 다 들어간다는것과 MVC는 그러한 부분을 각각의 특성에 맞게 분리했다는겁니다.

그럼 뭘 어떻게 분리하냐가 중요하겠죠.. 여기서 MVC 즉 Model, View, Controller에 대한 이해가 필요합니다.

View는 다들 잘 알다시피 html태그라고 생각하시면 됩니다. Model은 간단하게 데이타베이스에 쿼리하는 부분이라고 할수있습니다.

나머지 Controller 는 2개를 연결시켜주는 역할이라고 보시면 됩니다.

의미상으로는 아주 간단합니다. 앞으로 진행할 강좌는 다음과 같은 단계에 걸쳐 진행하도록 하겠습니다.

1.이클립스에서 톰캣을 활용한 웹프로그래밍 환경구축하기
2.모델1 기법으로 게시판 리스트 화면 만들기(List.jsp)
3.MVC 기법으로 게시판 리스트 화면 만들기
4.위의 2개의 구조를 비교분석하기

다음강좌에서 뵙겠습니다..

 

MVC 첫번째강좌 - 모델1 기법으로 게시판 리스트 만들기

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

본강좌는 jsp에 어느정도 익숙하신걸로 가정하고 진행하겠습니다. 일단 환경부터 구축해야겠죠^^.

먼저 DB에 테이블을 하나 만들겠습니다. Board(번호, 이름, 제목, 내용, 등록일) 테이블을 하나 만들고 디폴트로 몇개의 데이타를 넣겠습니다.(Board.sql, insert.sql) 자, 기본적인 준비는 됐습니다.

이제 이클립스에서 자바프로젝트를 하나 만듭니다. 프로젝트명은 MvcBoard 라고 하겠습니다.

프로젝트에서 www 폴더를 만듭니다. 이제 톰캣플러그인이 필요합니다. 설치하지 않으신분은 자료실에서 다운 받으시면 됩니다.

톰캣플러그인이 설치되셨다면 MvcBoard->특성을 누릅니다. 왼편에 Tomcat을 선택하고 Is a Tomcat Project 를 체크합니다. 다음에 Subdirectory to set as web application root(optional) 부분을 /www 로 변경합니다. 변경한 화면은 다음과 같습니다.


확인을 누르면 톰캣설정이 완료되었습니다. 이제 www폴더에 test.jsp를 만들고 내용은 test 로 합니다.

톰캣을 실행하고 브라우저에서 http://localhost:8080/test.jsp 를 입력합니다. 아래화면처럼 나오면 성공입니다.


지금까지는 db를 구성하고 이클립스에서 프로젝트를 톰캣과 연동하는 과정이었습니다. 앞으로 진행할 웹관련 강좌는 이런형태로
프로젝트를 설정하게됩니다.

자 그럼 모델1방식으로 게시판 리스트를 만들어보도록 하겠습니다. www폴더에 List.jsp 를 만들고 다음의 순서대로 내용을 채우겠습니다.

먼저 import 와 contentType을 설정합니다.
<%@ page language="java" import="java.sql.*,java.io.*" contentType="text/html; charset=euc-kr" %>

그 다음에 db에 접속을 해서 커넥션을 맺습니다. db서버주소, db명, 유저명,암호는 여러분의 db에 맞게 직접 넣으시기 바랍니다.
본강좌에서는 mysql을 사용합니다.

<%
   String url = "jdbc:mysql://db서버주소:3306/db명";
   String username = "유저명";
   String password = "암호";
   Connection con = null;
   try {
      Class.forName("org.gjt.mm.mysql.Driver");
      con = DriverManager.getConnection(url, username, password);
   } catch (ClassNotFoundException e) {
      out.println("드라이버를 찾을수 없습니다.");
   } catch (SQLException ex) {
      out.println("접속실패");
   }
%>

커넥션을 얻었다면 ResultSet을 얻습니다. 테이블은 위에서 만든 Board 입니다. Board.sql을 사용하여 테이블을 만들고 insert.sql 을 사용하여 데이타를 먼저 입력해놓겠습니다.(위의 첨부파일을 참조하세요)
<%   
   PreparedStatement ps = null;
   ResultSet rs = null;      
   String query = "select * from Board";
   try {
      ps = con.prepareStatement(query);
      rs = ps.executeQuery();
%>

이제 ResultSet을 사용하여 화면에 리스트를 구성하도록 하겠습니다.
<html>
   <body>
      <table border="1">
         <tr>
            <td>번호</td>
            <td>제목</td>
            <td>이름</td>
            <td>등록일</td>
         </tr>
<%
      while (rs.next()) {            
         String num = rs.getString("num");
         String subject = rs.getString("subject");
         String name = rs.getString("name");
         String regiDate = rs.getString("regiDate");
%>         
         <tr>
            <td><%=num%></td>
            <td><%=subject%></td>
            <td><%=name%></td>
            <td><%=regiDate%></td>
         </tr>
<%
      } 
%>
      </table>
   </body>
</html>

자, 이제 남은건 커넥션을 닫기만 하면 됩니다.
<%
   } catch (SQLException e) {
      out.println(e);
   } finally {
      try {
         if(rs != null) rs.close();         
         if(ps != null) ps.close();         
         if(con != null) con.close();               
      } catch(SQLException e) {
         out.println(e);      
      }
   }
%>

이제 브라우저에서 http://localhost:8080/List.jsp 를 호출하면 다음화면처럼 나올겁니다.


다음 강좌에서는 MVC기법으로 소스를 변경해보도록 하겠습니다.(물론 화면에 나타나는 결과물은 동일할겁니다)

 

MVC 두번째강좌 - MVC 기법으로 게시판 리스트 만들기(컨트롤러)

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

이전강좌에서는 전통적인 방식으로 화면을 만들었습니다. 그동안 다들 이렇게 코딩하셨다구요^^..

상관없습니다. 저도 그렇게 해왔었으니까요.

먼저 MVC로 들어가기전에 페이지가 호출되는 순서에 대해서 살펴보겠습니다. 모델1은 그냥 jsp파일을 직접 호출합니다. 하지만 MVC는 컨트롤러 개념이 들어갑니다. 그래서 먼저 컨트롤러를 호출하고 모델에서 데이타를 구성합니다. 마지막으로 jsp를 호출하죠.

이해가 되시나요? 다시 얘기하자면 컨트롤러 -> 모델 -> 뷰 의 순서로 호출됩니다.

그렇다면 컨트롤러를 가장 먼저 만들어야겠죠. 자 이제부터 MVC에 본격적으로 들어갑니다.

컨트롤러는 쉽게 얘기해서 중개자 역할입니다. 일종의 관문인데 모든 호출은 컨트롤러를 거칩니다. 컨트롤러는 서블릿으로 만들겠습니다. jsp로 만들어도 되지만 서블릿이 좀더 컨트롤러가 하는 역할에 적합하다고 볼수있습니다.

이제 이클립스로 가서 MvcBoard->src 에서 팩키지를 하나 만들겠습니다. 팩키지명은 javaforum.board 로 합니다.

javaforum.board 에서 클래스를 하나 만듭니다. 클래스명은 Controller 로 합니다.

다음에 나오는 순서대로 Controller 클래스에 내용을 채우겠습니다.

먼저 필요한 클래스들을 import합니다.
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import java.io.IOException;

Controller클래스를 HttpServlet으로 상속받도록 변경합니다.
public class Controller extends HttpServlet {

이제 Controller 클래스에 들어갈 함수를 작성합니다.
   public void init(ServletConfig config) throws ServletException {
      super.init(config);            
   }
   
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {         
      doProcess(request, response);
   }
   
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {         
      doProcess(request, response);      
   }
   
   public void doProcess(HttpServletRequest request, HttpServletResponse response) {
   }

이것으로 서블릿이 하나 완성되었습니다. 물론 하는일은 없습니다^^.. 단, 여기서 살펴볼 부분이 doGet, doPost함수에서 doProcess를 호출하도록 했다는겁니다. get방식이든 post방식이든 doProcess함수에서 처리하겠다는 의미가 되겠죠...

근데 doProcess에 아무것도 없다구요? 이제부터 컨트롤러의 실제 내용이 들어가게 될겁니다.

일단 서블릿이 제대로 작동되는지 테스트를 해봐야되니깐 doProcess에 System.out.println("컨트롤러 호출"); 만 입력하겠습니다.

여기서 한가지 환경설정부분이 필요합니다. src에 있는 파일이 컴파일될때 기본적으로 bin폴더로 들어가게 됩니다. 이 경로를 바꿔야되겠습니다.

먼저 www폴더에서 WEB-INF 폴더를 새로 만듭니다. 그리고 WEB-INF 폴더에 classes 폴더를 만듭니다.

다 만드셨으면 MvcBoard->특성을 누릅니다. 왼편에서 Java 빌드 경로를 선택합니다. 기본출력폴더 에서 /MvcBoard/bin 을 /MvcBoard/www/WEB-INF/classes 로 변경합니다.

이제부터 src에는 파일을 저장시 컴파일됨과 동시에 WEB-INF/classes 폴더로 클래스파일이 들어가게됩니다.

서블릿은 만들었고 남은건 web.xml을 만들고 서블릿을 맵핑하면 됩니다. WEB-INF 폴더에 web.xml 파일을 하나 만드세요.

web.xml에 다음과 같은 내용을 입력하세요. 톰캣이 서블릿을 인식하도록 맵핑해주는 부분이 들어가있습니다..
<?xml version="1.0"?> 
<!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>   
   <servlet>
        <servlet-name>Controller</servlet-name>
        <servlet-class>javaforum.board.Controller</servlet-class>        
    </servlet>
       
    <servlet-mapping>
        <servlet-name>Controller</servlet-name>
        <url-pattern>/servlet/Controller</url-pattern>
    </servlet-mapping>
</web-app>

맵핑하는 방법은 다양하지만 지금은 /servlet/Controller 로 하겠습니다.

자, 톰캣을 재시작합니다. 브라우저에서 http://localhost:8080/servlet/Controller 를 호출해봅니다.
이클립스 콘솔창에 컨트롤러 호출 메시지가 나오면 정상적으로 서블릿이 호출된 상태입니다.


이제 doProcess함수를 다듬어보겠습니다. 컨트롤러에서 파라미터를 하나 받도록 하겠습니다. 파라미터명은 action 으로 합니다.

String action = request.getParameter("action");

action에 대해서 조건문으로 구분합니다. 여기서는 list 일 경우만 넣었습니다.

      if(action.equals("list")) {
      }

여기까지 하고 www 폴더에서 MvcList.jsp 파일을 만듭니다. 내용은 MvcList 라고만 입력합니다.

이제 컨트롤러에서 조건문내에 MvcList.jsp를 호출하는 부분을 넣도록 하겠습니다.

먼저 import를 합니다.
import javax.servlet.ServletContext;
import javax.servlet.RequestDispatcher;

그리고 조건문내에 다음에 나오는 부분을 입력합니다.
         ServletContext sc = getServletContext();   
         RequestDispatcher rd = sc.getRequestDispatcher("/MvcList.jsp");
         try {
            rd.forward(request, response);
         } catch(ServletException se) {
            se.printStackTrace();               
         } catch(IOException ie) {
            ie.printStackTrace();
         }

여기서는 forward를 사용했는데 페이지를 호출하는 방식에는 2가지가 있습니다, forward, sendRedirect 가 있는데 forward는 서버(웹서버)상에서 직접 페이지를 호출합니다. sendRedirect는 서버에서 클라이언트(웹브라우저)에게 해당 페이지를 요청해달라고 요구하면 클라이언트가 다시 페이지를 호출하는 방식입니다. 즉 sendRedirect는 서버와 클라이언트간의 통신을 한번 더 하는 개념입니다.

이제 브라우저에서 http://localhost:8080/servlet/Controller?action=list 로 호출해보세요.


컨트롤러의 개념을 잡기위하여 먼저 뷰를 호출해보았습니다. 순서상으로는 모델호출이 먼저와야 하지만 편의상 뷰를 어떤식으로 호출하는지에 대해서 살펴보았습니다.

이제 데이타를 구성하고 화면에 뿌리는 일만 남았군요. 다음강좌에서 모델부분과 뷰를 완성해보도록 하겠습니다. 그럼 다음강좌에서.....

 

MVC 세번째강좌 - MVC 기법으로 게시판 리스트 만들기(모델, 뷰)

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

2장에 이어서 계속 진행하겠습니다. MVC에서 모델의 역할은 데이타를 구성하고 편집하고 결과물을 만드는 역할을 합니다.

일단 아주 간단하게 생각해서 쿼리부분이 들어가는곳이 모델단인데 DB에 접속해서 쿼리후 데이타를 가져오는 부분을 DAO(Data Access Object) 라고 부르겠습니다.

DAO에서 쿼리의 결과물을 어딘가에 담아야하겠죠. 이걸 VO(Value Object) 에 담겠습니다.

그럼 먼저, VO 클래스를 하나 만듭니다. MvcBoard->src->javaforum.board 에서 신규->클래스를 선택합니다. 클래스명은 ListVO 라고 하세요.
ListVO에 4개의 멤버변수를 만듭니다.
   private int num;
   private String subject;
   private String name;
   private String regiDate;

멤버변수하나를 선택한후 마우스 오른쪽버튼을 눌러서 소스->Getter 및 Setter 생성메뉴를 누릅니다. 팝업화면에서 모두선택하고 확인을 누릅니다.

결과물을 담을 객체를 만들었습니다. 이제 DAO에서 쿼리결과를 ListVO에 담으면 됩니다.

이제, DAO클래스를 만들겠습니다. MvcBoard->src->javaforum.board 에서 신규->클래스를 선택합니다. 클래스명은 BoardDAO 라고 하세요.

상단에 import문을 추가합니다.
import java.sql.*;
import java.util.Vector;

커넥션을 얻는 함수를 하나 만들겠습니다.
   public Connection getConnection() {
      String url = "jdbc:mysql://db주소:3306/db명";
      String username = "유저명";
      String password = "암호";
      Connection con = null;
      try {
         Class.forName("org.gjt.mm.mysql.Driver");
         con = DriverManager.getConnection(url, username, password);
      } catch (ClassNotFoundException e) {
         System.out.println("드라이버를 찾을수 없습니다.");
      } catch (SQLException ex) {
         System.out.println("접속실패");
      }
      return con;      
   }

다음에 쿼리한 결과물을 ListVO에 담고 로우수만큼 ListVO를 벡터에 담는 부분입니다.
   public Vector getList() {
      Connection con = this.getConnection();
      PreparedStatement ps = null;
      ResultSet rs = null;      
      String query = "select * from Board";
      try {
         ps = con.prepareStatement(query);
         rs = ps.executeQuery();
         Vector values = new Vector();
         while(rs.next()) {
            ListVO vo = new ListVO();
            vo.setNum(rs.getInt("num"));
            vo.setSubject(rs.getString("subject"));
            vo.setName(rs.getString("name"));
            vo.setRegiDate(rs.getString("regiDate"));
            
            values.addElement(vo);
         }
         return values;
      } catch (SQLException e) {
         e.printStackTrace();
         return null;
      } finally {
         try {
            if(rs != null) rs.close();                                 
            if(ps != null) ps.close();         
            if(con != null) con.close();   
         } catch(SQLException e) {                        
         }
      }      
   }

Board테이블에 5개의 데이타가 들어가있기때문에 ListVO는 5개 만들어지게 됩니다.

이것으로 DAO는 끝났습니다. 그럼 이 벡터를 컨트롤러에서 받아야겠죠. 다시 컨트롤러로 가겠습니다.

import를 하나 추가합니다. import java.util.Vector;

if(action.equals("list")) { 조건문내에 다음부분을 추가하세요.
         BoardDAO dao = new BoardDAO();
         Vector listValues = dao.getList();
         request.setAttribute("listValues", listValues);


dao.getList() 함수를 호출해서 결과를 받았습니다. 그 결과를 request에 저장합니다. setAttribute()의 의미는 서버상의 request메모리영역에 변수를 임시 저장하는 역할을 담당합니다. 물론 나중에 쓸려고 저장하는겁니다.

어디서 쓰냐구요? MvcList.jsp에서 사용해야겠죠. 이제 남은건 MvcList.jsp에서 결과물을 화면으로 구성하면 됩니다.

MvcList.jsp로 다시 이동하겠습니다.

import 와 contentType을 설정합니다.
<%@ page language="java" import="java.util.Vector, javaforum.board.ListVO" contentType="text/html; charset=euc-kr" %>

request에서 getAttribute로 결과값을 다시 꺼냅니다.
<%
   Vector listValues = (Vector) request.getAttribute("listValues");
%>

마지막으로 화면에 뿌려주기만 하면 됩니다.
<html>
   <body>
      <table border="1">
         <tr>
            <td>번호</td>
            <td>제목</td>
            <td>이름</td>
            <td>등록일</td>
         </tr>
<%
      for(int i = 0; i < listValues.size(); i++) {
         ListVO vo = (ListVO) listValues.elementAt(i);
         int num = vo.getNum();
         String subject = vo.getSubject();
         String name = vo.getName();
         String regiDate = vo.getRegiDate();
%>         
         <tr>
            <td><%=num%></td>
            <td><%=subject%></td>
            <td><%=name%></td>
            <td><%=regiDate%></td>
         </tr>
<%
      } 
%>
      </table>
   </body>
</html>

브라우저에서 http://localhost:8080/servlet/Controller?action=list 를 호출합니다.


이상 MVC형태로 게시판 리스트를 만들어보았습니다. 대충 감이 잡히시나요? 다음강좌에서는 둘의 차이점을 비교분석하고 MVC 소스를 약간 변형해보겠습니다.

그럼 다음강좌에서...

 

MVC 네번째강좌 - 모델1과 MVC 소스 비교분석하기, MVC 소스 약간 변경해보기

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

이제 모델1과 MVC사이에 어떠한 변화가 일어났는지 살펴볼 시간입니다. 가장 큰 변화는 무엇일까요?

모델1의 List.jsp 에는 커넥션을 맺고 데이타를 가져오는 부분이 있지만 MVC의 MvcList.jsp에는 그 부분이 빠져있습니다.
훨씬 보기가 좋아진것 같나요. 겉으로 보기에도 소스가 간결해진것을 느낄수가 있습니다.

웹프로그래밍이 아닌 전통적인 어플리케이션 개발에서는 모듈화를 해야만 개발이 용이하고 유지보수도 쉽습니다. 하지만 웹으로 넘어오면서 로직이나 화면처리등을 하나의 파일(jsp)에서 처리하는게 익숙해졌고 또 그렇게 해왔습니다. 하지만 이러한 방식은 상당히 소스를 어지럽게 만들기 때문에 유지보수도 어려울뿐더러 코드의 재사용성에도 문제가 됩니다.
물론 모델1기법이 단점만 있는것은 아닙니다. 소규모프로젝트라면 개발기간면에서 mvc보다는 생산성이 높다고 할 수 있습니다.

여하튼 이러한 문제점을 보완하기위해 나온게 MVC인데 요지는 jsp에 있는 소스를 각모듈이 하는 역할에 맞게 분리하자는 겁니다.

1.view : jsp가 됩니다. 단지 화면에 관련된 사항만 처리합니다.
2.controller : jsp에서 넘어오는 파라미터처리후 해당 로직이나 DAO에 연결한 다음 결과값 받아서 jsp에 넘겨주는 역할을 담당합니다.
3.model : 로직이나 DAO는 controller에서 요구한 데이타를 구성해서 결과값을 넘겨주는 역할을 합니다.

자, 그럼 MVC에 좀 더 깊이 들어가보겠습니다. jsp는 화면처리만 담당한다고 했는데 파라미터처리 부분은 어디로 갔을까요? 컨트롤러에서 그부분이 들어갑니다. 바로 String action = request.getParameter("action"); 이 부분이죠.

근데 한가지 짚고 넘어가야할 부분이 있습니다. 서블릿을 호출할때 /servlet/Controller?action=list 이렇게 했습니다. 즉 이것은 MvcList.jsp를 호출하기 위해서죠. 그렇다면 좀더 세련되게 호출할수 없을까라는 의문이 드는군요.

web.xml에서 서블릿을 다르게 맵핑해보겠습니다. url-pattern 에서 /servlet/Controller -> *.action 로 고칩니다.
<url-pattern>*.action</url-pattern>

이제 Controller 로 갑니다. doProcess에서 다음처럼 변경합니다.
      //String action = request.getParameter("action");
      String servletPath = request.getServletPath();
      String actionName = servletPath.substring(servletPath.lastIndexOf("/") + 1);
      if(actionName.equals("MvcList.action")) {


기존의 파라미터는 쓰지 않기때문에 주석처리하고 서블릿경로에서 액션명을 파싱하는 내용입니다. 이렇게해서 컨트롤러를 호출할때 액션명으로 구분하는게 가능하게됩니다.
이제 MvcList.action 으로 호출해야겠죠^^.

그럼 톰캣을 재시작하고 브라우저에서 http://localhost:8080/MvcList.action 이라고 입력합니다.

MvcList.action 을 호출하게 되면 MvcList.jsp를 호출하게 되는것이죠. 컨트롤러를 약간 수정해보았습니다.

이번에는 view로 가볼까요^^.. MvcList.jsp를 에디터에서 여세요. 물론 간결해지기는 했지만 눈에 거슬리는게 한가지 있군요. 태그사이에 스크립틀릿이 들어가서 일관성이 떨어져보입니다.

바로 스크립틀릿을 태그로 바꿀려고 합니다. 아니 태그라니.. 무슨 말인지 이해가 안되신다구요?

커스텀태그를 사용하면 간단하게 해결이 됩니다. 그중에서도 표준인 jstl(jsp standard tag library)을 사용해서 변경해보겠습니다.

변경하기전에 환경부터 갖추도록 하겠습니다. jstl관련 jar파일을 다운받습니다. 자료실에 보면 톰캣4점대, 톰캣5점대용 jstl.jar, standard.jar 가 있습니다.

2개의 파일을 다운받으셨으면 MvcBoard->www->WEB-INF 로 가서 lib 폴더를 만듭니다. jar파일을 lib폴더로 옮겨놓으세요.

MvcList.jsp 로 가서 상단에 다음부분을 추가합니다. jstl core 관련 태그를 사용하겠다는 의미입니다.
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

jstl 설정은 마쳤습니다. 이제 core 에 들어있는 태그를 사용해서 스크립틀릿 부분을 대체하면 됩니다.
일단 어떻게 변화가 되는지 보여드리겠습니다.
         <c:forEach items="${listValues}" var="data">      
         <tr>
            <td><c:out value="${data.num}"/></td>
            <td><c:out value="${data.subject}"/></td>
            <td><c:out value="${data.name}"/></td>
            <td><c:out value="${data.regiDate}"/></td>
         </tr>
         </c:forEach>


다시 톰캣을 재시작하고 브라우저에서 http://localhost:8080/MvcList.action 을 호출해보세요. 같은결과가 나올겁니다.

변화된 소스를 보면 listValues 를 가져오는 부분이 없습니다. 그리고 for문이 jstl의 forEach 태그로 변했습니다. 마지막으로 출력부분이 c:out 태그를 사용해서 data.num 과 같은 형식으로 변했습니다.

훨씬 보기가 좋군요^^. 어떤가요 소스도 간결해지고 태그화 되어있기때문에 영역구분이 명료해졌습니다.
지금은 core 태그중에 반복문을 표현하는 forEach와 출력문에 사용되는 out태그만을 사용했습니다. jstl에 대한 사용법은 별도의 강좌(커스텀태그와 jstl 강좌)를 통해서 여러분에게 알려드릴 예정입니다.

다음강좌에서는 모델쪽의 DAO클래스에 변화를 줘보도록 하죠. 그럼 다음강좌에서....

MVC 다섯번째강좌 - MVC패턴에서 모델영역에 속하는 DAO클래스 약간 변경하기

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

이번 시간에는 DAO클래스에서 DB의 데이타를 가져오는 부분을 변경해보도록 하겠습니다.

getList() 함수를 보면 커넥션을 하나 가져와서 PreparedStatement와 ResultSet을 이용하여 검색된 로우수만큼 컬럼의 값을 가져오는 부분입니다. 하지만 이러한 부분은 중복이 생기는 경우가 많습니다. 그렇기 때문에 이러한 db처리부분을 공통함수화할 필요가 생겼습니다.

그럼 ResultSet과 같은 역할을 하는 MyResultSet을 만들어보죠. MyResultSet에는 로우수만큼 데이타를 가지는 변수가 필요합니다. 그리고 next, getInt, getString 함수를 만들겠습니다.

package javaforum.board;
import java.util.*;
/**
 * @author wwwoong
 */
public class MyResultSet {
   private Vector rowData;
   private int rowPos = -1;
   
   public void setRowData(Vector rowData) {
      this.rowData = rowData;
   }
   
   public int getInt(String columnName) {
      String columnValue = this.getString(columnName);
      try {
         int val = Integer.parseInt(columnValue);
         return val;
      } catch(Exception e) {
         return -1;            
      }
   }
   
   public String getString(String columnName) {
      Hashtable columnData = (Hashtable) this.rowData.elementAt(this.rowPos);
      if(columnData.containsKey(columnName)) {
         String columnValue = (String) columnData.get(columnName);
         return columnValue;
      } else {
         System.out.println("컬럼명이 존재하지 않습니다.");
         return "";   
      }      
   }
   
   public boolean next() {
      if(this.rowPos == this.rowData.size() - 1) {
         return false;
      } else {
         this.rowPos++;
         return true;
      }      
   }
}

MyResultSet은 ResultSet을 흉내낸것이기 때문에 기능이 같습니다. 여러분들이 직접 분석해보시기 바랍니다.

BoardDAO 로 가서 함수 하나를 만들겠습니다. 함수의 내용은 rowData에 쿼리결과를 집어넣고 MyResultSet에 rowData를 넣습니다.
   public MyResultSet selectMultiRow(String query) {         
      Connection con = null;   
      PreparedStatement ps = null;
      ResultSet rs = null;
      ResultSetMetaData rmd = null;
      int columnCount = 0;
      
      MyResultSet myResultSet = new MyResultSet();
      Vector rowData = new Vector();
      try {
         con = getConnection();
         ps = con.prepareStatement(query);
         rs = ps.executeQuery();
         rmd = rs.getMetaData();
         columnCount = rmd.getColumnCount();
         while (rs.next()) {                        
            Hashtable columnData = new Hashtable();
            for(int i = 1; i <= columnCount; i++) {
               String columnName = rmd.getColumnName(i);
               columnData.put(columnName, rs.getString(i));               
            }
            rowData.addElement(columnData);
         } 
         myResultSet.setRowData(rowData);
      } catch (SQLException e) {
         System.out.println("select sql : " + e);
         e.printStackTrace();
      } finally {
         try {
            if(rs != null) rs.close();                                 
            if(ps != null) ps.close();         
            if(con != null) con.close();         
         } catch(SQLException e1) {
            e1.printStackTrace();         
         }
      }
      return myResultSet;
   }

selectMultiRow 는 여러개의 로우결과를 갖기때문에 이렇게 이름지었습니다. 이 함수를 이용해서 getList()를 고쳐보도록 하겠습니다.
   public Vector getList() {
      String query = "select * from Board";
      MyResultSet myResultSet = this.selectMultiRow(query);
      
      Vector values = new Vector();
      while(myResultSet.next()) {          
           ListVO vo = new ListVO(); 
          vo.setNum(myResultSet.getInt("num")); 
          vo.setSubject(myResultSet.getString("subject")); 
          vo.setName(myResultSet.getString("name")); 
          vo.setRegiDate(myResultSet.getString("regiDate")); 
         
          values.addElement(vo); 
      }
      
      return values;
   }

이전의 getList() 함수와 차이가 느껴지나요? 위아래로 반복되는 불필요한 부분을 제거했습니다.

다음강좌에서는 컨트롤러부분을 좀 더 살펴보도록 하죠. 지금까지는 list만으로 예제를 해왔지만 detail, insert, update 부분도 만들어보도록 하겠습니다.

그럼 다음강좌에서...

 

MVC 여섯번째강좌 - MVC기법으로 입력 게시판 만들기

작성자 : 김시웅
테스트환경 : 이클립스2.1.2, mysql, tomcat4.1.30

지금까지는 리스트화면만으로 강좌를 해왔습니다. 이제부터는 나머지화면도 만들어보도록 하겠습니다.

먼저 Controller.java 로 갑니다. doProcess함수에서 jsp로 forward하는 부분을 함수로 만들겠습니다. 함수명은 forward 입니다.
   public void forward(HttpServletRequest request, HttpServletResponse response, String pageName) {
      ServletContext sc = getServletContext();   
      RequestDispatcher rd = sc.getRequestDispatcher(pageName);
      try {
         rd.forward(request, response);
      } catch(ServletException se) {
         se.printStackTrace();               
      } catch(IOException ie) {
         ie.printStackTrace();
      }
   }

그리고 액션명을 얻는 부분도 함수로 만들어보죠. 함수명은 getActionName 입니다.
   public String getActionName(HttpServletRequest request) {
      String servletPath = request.getServletPath();
      String actionName = servletPath.substring(servletPath.lastIndexOf("/") + 1);
      return actionName;
   }

이와같이 2개의 함수를 추가한뒤의 doProcess함수는 다음과 같습니다.
   public void doProcess(HttpServletRequest request, HttpServletResponse response) {
      System.out.println("컨트롤러 호출");
      String actionName = this.getActionName(request);
      if(actionName.equals("MvcList.action")) {
         BoardDAO dao = new BoardDAO();
         Vector listValues = dao.getList();
         request.setAttribute("listValues", listValues);
         
         this.forward(request, response, "/MvcList.jsp");
      }
   }

이제 doProcess함수도 어느정도 정리된 느낌이군요^^. 그럼 insert액션을 추가해보죠. MvcInsert.action 으로 하겠습니다.
      } else if(actionName.equals("MvcInsert.action")) {
      }

조건문내에 DAO를 생성하고 함수를 호출하면 되는데 그전에 한가지 준비해야할게 있습니다. 리스트에서 VO(View Object)를 만들었듯이 인서트에서는 TO(Transact Object)가 필요합니다.
TO는 테이블의 컬럼수와 같다고 보시면 됩니다. DB에 들어갈 오브젝트니까요. InsertTO를 만들겠습니다.
package javaforum.board;

/**
 * @author wwwoong
 */
public class InsertTO {
   private int num;
   private String name;
   private String subject;
   private String content;
   private String regiDate;
}

이와같이 만든후에 getter, setter로 함수를 만드세요.

그리고 DAO에 가서 함수를 하나 만들어야됩니다. insert(InsertTO to) 즉 컨트롤러에서 TO를 만든후 DAO의 insert함수에 건네주는 형태입니다. insert함수를 만들기전에 transact 함수를 먼저 만들겠습니다. 이것 역시 selectMultiRow함수와 마찬가지로 중복을 피하기 위해서 만드는겁니다.
   //insert, update, delete 문 형태
   public boolean transact(String query) {         
      Connection con = null;
      PreparedStatement ps = null;
      try {
         con = getConnection();
         con.setAutoCommit(false);
         ps = con.prepareStatement(query);
         ps.executeUpdate();      
         con.commit();
         return true;    
      } catch (SQLException e) {
         try {
            con.rollback();
         } catch(SQLException re) {
            re.printStackTrace();
         }
         System.out.println("query : " + query);
         System.out.println("transact sql : " + e);
         e.printStackTrace();
         return false;
      } finally {
         try {                              
            if(ps != null) ps.close();         
            if(con != null) con.close();      
         } catch(SQLException e1) {
            e1.printStackTrace();         
         }
      }
   }
   
   //insert, update, delete 문 형태(다중 트랜잭션처리)
   public boolean transact(String querys[]) {         
      Connection con = null;
      PreparedStatement ps = null;
      String query = null;
      try {
         con = getConnection();
         con.setAutoCommit(false);
         for(int i = 0; i < querys.length; i++) {
            query = querys[i];            
            ps = con.prepareStatement(query);
            ps.executeUpdate();
         }                        
         con.commit();
         return true;    
      } catch (SQLException e) {
         try {
            con.rollback();
         } catch(SQLException re) {
            re.printStackTrace();
         }
         System.out.println("query : " + query);
         System.out.println("transact sql : " + e);
         e.printStackTrace();
         return false;
      } finally {
         try {                        
            if(ps != null) ps.close();         
            if(con != null) con.close();      
         } catch(SQLException e1) {
            e1.printStackTrace();         
         }
      }
   }

쿼리가 하나일때와 다수일때에 대한 DB transact함수입니다. 내용은 금방 이해되실겁니다.

마지막으로 Board 테이블의 키인 num의 맥스값을 얻어오는 함수가 필요합니다.
   public int getMaxNum() {
      String query = "select max(num) from Board";      
      String maxStr = this.selectOneCol(query);
      int max = 0;
      if(maxStr != null && !maxStr.equals("")) {
         max = Integer.parseInt(maxStr);
      }               
      max++;
      return max;
   }
   
   //select문 형태(하나의 데이타)
   public String selectOneCol(String query) {
      String resultStr = null;
      Connection con = null;   
      PreparedStatement ps = null;
      ResultSet rs = null;
      ResultSetMetaData rmd = null;
      int columnCount = 0;
      try {
         con = getConnection();
         ps = con.prepareStatement(query);
         rs = ps.executeQuery();
         rmd = rs.getMetaData();
         columnCount = rmd.getColumnCount();
         if (rs.next()) {                        
            resultStr = rs.getString(1);                     
         } 
      } catch (SQLException e) {
         System.out.println("select sql : " + e);
         e.printStackTrace();
      } finally {
         try {
            if(rs != null) rs.close();                                 
            if(ps != null) ps.close();         
            if(con != null) con.close();               
         } catch(SQLException e1) {
            e1.printStackTrace();         
         }
      }
      return resultStr;
   }

getMaxNum 은 맥스값을 얻어서 1증가시킵니다. selectOneCol 은 하나의 데이타만을 얻어오는 함수입니다. 휴 사전공작 힘들군요.
이제 insert함수를 만들수 있습니다^^. 결과값은 boolean으로 넘어옵니다.
   public boolean insert(InsertTO to) {
      String query = 
         "insert into Board values(" +
            to.getNum() + ", " + 
            "'" + to.getName() + "'," +
            "'" + to.getSubject() + "'," +
            "'" + to.getContent() + "'," +
            to.getRegiDate() + ")"; 
      return this.transact(query);
   }

BoardDAO에서 할일은 다 한것같군요. Controller로 가서 redirect 함수를 만들겠습니다.
   public void redirect(HttpServletResponse response, String page) {
      try {
         response.sendRedirect(page);
      }         
      catch(IOException ie) {      
         System.out.println("sendRedirect IOException 에러 : " + ie);
         ie.printStackTrace();
      } catch(Exception e) {
         e.printStackTrace();
      }   
   }

redirect를 쓰게되면 클라이언트로 부터 요청을 받기때문에 이전의 url이 브라우저에 남지 않습니다.
이제 MvcInsert.action 조건문으로 갑니다. 다음을 추가합니다.
         BoardDAO dao = new BoardDAO();
         InsertTO to = new InsertTO();
         boolean isTrue = dao.insert(to);
         if(isTrue) {
            this.redirect(response, "/MvcList.action");
         }          

내용을 살펴보면 InsertTO를 만들고 insert함수를 호출한이후에 결과가 참이면 "/MvcList.action"으로 forward하는군요. 에러가 났다면 현재화면을 보여주면 되니깐 이동할 필요가 없겠죠^^.
아^^. 뭔가 빠진것같다구요? 맞습니다, to에 아무것도 입력하지 않았네요. 다음을 추가해줍니다.
         to.setNum(dao.getMaxNum());
         to.setName(request.getParameter("name"));
         to.setSubject(request.getParameter("subject"));
         to.setContent(request.getParameter("content"));
         to.setRegiDate("now()");

어디에 삽입해야할지는 아실겁니다. 완성된 doProcess함수를 보여드리죠^^.
   public void doProcess(HttpServletRequest request, HttpServletResponse response) {
      System.out.println("컨트롤러 호출");
      String actionName = this.getActionName(request);
      if(actionName.equals("MvcList.action")) {
         BoardDAO dao = new BoardDAO();
         Vector listValues = dao.getList();
         request.setAttribute("listValues", listValues);
         
         this.forward(request, response, "/MvcList.jsp");
      } else if(actionName.equals("MvcInsert.action")) {
         BoardDAO dao = new BoardDAO();
         InsertTO to = new InsertTO();         
         to.setNum(dao.getMaxNum());
         to.setName(request.getParameter("name"));
         to.setSubject(request.getParameter("subject"));
         to.setContent(request.getParameter("content"));
         to.setRegiDate("now()");
         boolean isTrue = dao.insert(to);
         if(isTrue) {
            this.redirect(response, "/MvcList.action");
         }          
      }
   }

근데 한가지 문제가 있군요. 인서트는 초기에 입력화면이 나오는 부분과 submit후에 입력내용을 DB에 넣는 부분이 구별되야합니다. 그래서 MvcInsert.action 을 호출할때 transact 파라미터를 추가하겠습니다. 즉 transact파라미터를 안쓰거나 transact="false" 일때는 초기입력화면이고 transact="true" 일때만 트랜잭션처리를 하도록 변경해야겠습니다.
         String transact = request.getParameter("transact");
         if(transact == null || transact.equals("false")) {
            this.forward(request, response, "/MvcInsert.jsp");
         } else if(transact.equals("true")){
            BoardDAO dao = new BoardDAO();
            InsertTO to = new InsertTO();         
            to.setNum(dao.getMaxNum());
            to.setName(request.getParameter("name"));
            to.setSubject(request.getParameter("subject"));
            to.setContent(request.getParameter("content"));
            to.setRegiDate("now()");
            boolean isTrue = dao.insert(to);
            if(isTrue) {
               this.redirect(response, "/MvcList.action");
            }          
         }

지금까지 insert를 추가하기 위해서 컨트롤러와 DAO의 내용을 변경했습니다. 이제 화면 MvcInsert.jsp만 만들면 됩니다.
<%@ page language="java" contentType="text/html; charset=euc-kr" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<script language="javascript">
   function insert() {
      form = document.insertForm;   
      form.submit();         
   }
</script>   
<html>
   <body>
      <form name="insertForm" method="post" action="/MvcInsert.action">
      <input type="hidden" name="transact" value="true">
      <table border="1">
         <tr>
            <td>이름</td><td><input type="text" name="name"></td>
         </tr>
         <tr>
            <td>제목</td><td><input type="text" name="subject"></td>
         </tr>
         <tr>
            <td>내용</td><td><input type="textarea" name="content"></td>
         </tr>
         <tr>
            <td align="center"><a href="javascript:insert()">입력</a></td>
         </tr>
      </table>
      </form>
   </body>
</html>

그리고 MvcList.jsp에 <a href="/MvcInsert.action">글쓰기</a>를 추가합니다.

글입력이 잘되는지 테스트해보시기 바랍니다. 이것으로 MVC기초강좌를 마치겠습니다. 나머지 detail, update, delete는 여러분들이 직접해보시면 좀더 MVC에 대한 이해가 빠를거로 생각됩니다.

앞으로 MVC중급강좌, 커스텀태그와 jstl강좌, 아파치 digester강좌 등등을 준비하고 있습니다.
새로운 강좌에서 뵙겠습니다. 그럼 전 이만.....

'개발도 하냐?' 카테고리의 다른 글

전자세금계산서/세금계산서 업체 정보리스트  (0) 2009.10.29
Anyframe Doc  (0) 2009.09.16
Eclipse + JEUS  (0) 2009.08.19
약도 만들기  (0) 2009.08.14
아키텍쳐에 대한 정의  (0) 2009.08.07
필수 파일
1. eclipse3.2
-http://www.eclipse.org

2. JMaker 3.2 plug-in
-http://technet.tmax.co.kr

3. JMaker license
-http://technet.tmax.co.kr

4. JEUS5.0

5. 이클립스에서 제우스 서버 구동하기
※ JMaker 3.2 plug-in 삽입
- 압축 풀기 후 eclipse3.2/  폴더 안에
   features 폴더와 plugins 폴더를 덮어쓰기 한다.

※ JMaker license 삽입
   신청하여 받은 license 파일을
   eclipse3.2/  폴더 안에 license 폴더를 생성하여 해당 파일을 추가한다.

※ Local JEUS Server 설정 및 실행
- eclipse를 실행하여 Servers View를 선택하고
   오른쪽 마우스를 클릭하여 New -> Server를 선택한다.

- Server's host name 은 'localhost' 삽입 후 Next

- JRE 와 JEUS Home Directory 확인 후 Next

- Node Name 은 '로컬 PC의 hostname',
  WebHome Directory는  JEUS의 'webhome'까  지 설정,
  유저 이름과 비밀번호를 작성한후 Finish

- JEUS Server를 start하여 jboot 확인한다.

- Ant Build(Alt + Shift + X + Q)를 시켜 jeus 서버로 컴파일한다.


[WebtoB, JEUS and Eclipse]

이번 포스트에서는 TmaxSoft 사의 JEUS와 WebtoB, 그리고 대표적인 자바 개발 툴인 Eclipse와 연동하는 방법에 대해 얘기하기 위해 필요사항을 정리하고, 설치하는 방법까지 알아보도록 하자.

    * 요구사항
          o JEUS 5.0 Fix#14 이상(http://technet.tmax.co.kr/)
          o WebtoB 4.1 이상(http://technet.tmax.co.kr/)
          o Eclipse 3.2(http://www.eclipse.org/)
          o JMaker 3.2 plugin(http://technet.tmax.co.kr/)

    이번 포스트에서는 MyEclipse나 TmaxSoft 사의 JMaker 3.2 SDK를 이용하지 않고, 오리지널 Eclipse과의 연동을 하므로 JMaker 3.2 plugin만 있으면 된다.

    JEUS, WebtoB, JMaker plugin은 TmaxSoft Technet 가입 후, 다운로드를 받아야 한다. 또한, 라이센스가 필요한데, 이 또한, Technet에서 신청 가능하다. 신청 즉시, 이메일로 발송되므로 기다리지 않아도 된다.

    각 제품 별로 데모 기간이 다르므로 라이센스 페이지의 '제품별 발급 라이센스 정보'를 잘 참조하도록 하자. 한가지 설명을 덧붙이자면, 라이센스 신청 시, Host ID 혹은 Host Name을 입력하도록 되어 있는데, 이는 윈도우 콘솔(윈도우키 + R)에서 각각 vol 명령과 hostname 명령으로 확인 가능하다. 단, vol명령의 경우, 해당 제품이 설치되는 디스크 드라이브으로 이동한 뒤, 확인해야 한다.(디스크 드라이브는 각자 고유의 volume이 존재한다.)

    * WebtoB 설치
          o 다운로드 받은 설치 파일을 실행하여 원하는 위치에 설치 하도록 한다.
          o 설치 중간, WebtoB + Servlet 설치 혹은 WebtoB 설치를 물어보는데 Servlet은 필요없으므로 WebtoB만 설치해도 무방하다.
          o 발급받은 라이센스 파일(license.dat)을 license 밑에 복사하여 옮긴다.
          o WebtoB 설정은 WebtoB 기동과 함께 JEUS와의 연동 부분에서 설명하도록 하겠다.
    * JEUS 설치
          o 다운로드 받은 설치 파일을 실행하여 원하는 위치에 설치 하도록 한다.
          o 발급받은 라이센스 파일의 확장자를 제거하고 license 밑에 복사하여 옮긴다.
          o JEUS를 설치하고 나면, Quick Start를 기동할 수 있는데, Quick Start에서 서버를 기동해 볼 수 있다. 정상적으로 서버가 기동되면 설치가 정상적으로 이루어진 것이다.
    * Eclipse 설치
          o Eclipse의 경우, 따로 설치가 필요하지 않고, 압축을 풀어놓기만 하면 된다.
    * JMaker 3.2 plugin 설치
          o JMaker 3.2 plugin은 Eclipse용 plugin이다. 압축 파일을 Eclipse 폴더에 풀기만 하면 설치가 된다.
          o JMaker 3.2 plugin에도 라이센스가 필요하다. Eclipse 폴더에 license 폴더를 새로 만들고 발급된 라이센스 파일을 확장자(dat)를 제거하고 옮겨놓도록 한다.
          o 설치 후, Eclipse를 기동해서, 아무런 경고 메세지가 발생하지 않는다면 정상적으로 설치된 것이다.

'개발도 하냐?' 카테고리의 다른 글

Anyframe Doc  (0) 2009.09.16
JSP_MVC 형식  (0) 2009.09.16
약도 만들기  (0) 2009.08.14
아키텍쳐에 대한 정의  (0) 2009.08.07
허드슨(Hudson)을 이용한 지속적인 통합(Continuous integration with Hudson)  (0) 2009.07.31

회사 약도

http://map.creation.net/ 에서 자신만의 지도를 만들어서 사용할 수 있다.



출처 : http://www.swarchitect.org/

소프트웨어 아키텍처에 대한 정의

위의 정의들을 요약하여 소프트웨어 아키텍처를 다음과 같이 정의한다.

소프트웨어 아키텍처는 시스템의 핵심 구성 요소와 구성 요소들 사이의 연결 관계로 이루어진다. 핵심 구성 요소는 시스템이 가지고 있는 모듈, 모듈 사이의 연결, 시스템의 변경, 진화하기 위한 기술적인 원칙, 모듈들 사이의 상호작용, 시스템이 동작하기 위한 기술을 포함한다.

소프트웨어 아키텍처는 구현할 시스템에 대한 top-down view이며 시스템에 대한 기술적인 명세서이며 공학적인 청사진이다.

소프트웨어 아키텍처의 구성 요소

소프트웨어 아키텍처는 다음과 같은 구성 요소로 이루어져 있다.

  • 시스템의 구성요소와 구성 요소 들 사이의 연결 관계
  • 시스템의 설계와 진화를 통제하는 원리와 가이드라인
  • 시스템 구성 요소들의 collaboration
  • 시스템이 어떻게 확장되고 수정될 것인가에 대한 결정
  • 시스템의 구성 요소들이 가지고 있는 기술

 

아키텍트의 역할

개발 프로젝트에서 초기에 기술적인 부분에 대하여 의사결정을 진행한다. 또한 프로젝트가 진행될 수 있도록 기술적인 이슈들을 해결한다. 아키텍트가 프로젝트의 각 단계마다 해결하는 문제는 다음과 같다.

표 Ⅱ-1. 프로젝트의 각 단계마다 아키텍트가 수행하는 역할

단계

아키텍트가 수행하는 역할

  • Inception 
  • Architecture prototyping
  • Make/buy trade-offs
  • Primary scenario definition
  • Archtecture evaluation
  • CASE tool, 개발 툴 등 각종 툴 사용 방안
  • 설계 문서 템플릿 결정
  • 설계자와 개발자의 작업 규칙 결정
  • Elaboration 
  • Architecture baselining
  • Primary scenario demonstration
  • Make/buy trade-off baselining  
  • Construction 
  • Architecture maintenance
  • Multiple-component issue resolution
  • Performance tuning
  • Quality improvements 
  • Transition 
  • Architecture maintenance
  • Multiple-component issue resolution
  • Performance tuning
  • Quality improvements 

개발 프로젝트에서 아키텍트가 하는 역할은 다음과 같다.

아키텍트는 아키텍처를 만들고 컴포넌트와 컴포넌트 사이의 관계를 파악하고 인터페이스를 설계해야 한다. 프로젝트 관리자는 아키텍트가 아키텍처 문서를 생산하도록 관리해야 한다.

프로젝트에서는 아키텍처에 대한 일차 문서가 만들어지면 아키텍처 팀이 해체되고 각 subsystem에 대한 개발 리더로서 역할을 할 경우가 많다. 이 경우 시스템 전체를 보고 아키텍처를 upgrade하는 역할이 없어진다. 아키텍처가 일차 완성된 후에도 아키텍처는 자주 수정된다. 개발자들은 아키텍처 팀이 만든 문서를 받아들이지 않고 새로운 요구사항이 들어오면 아키텍처의 본래 목적에서 벗어난 방식으로 나름대로 개발하려 한다. 따라서 아키텍처 팀은 프로젝트 끝까지 해체되지 않고 아키텍처에 대한 수정 및 업그레이드에 대한 책임을 져야 한다.

또한 아키텍트는 개발자들이 아키텍처를 이해하도록 도와야 하고 아키텍처 밑에 숨은 결정 사항을 설명해야 한다. 즉 아키텍트는 개발자들에게는 컨설턴트로서 리더로서의 역할을 해야 한다.

 

아키텍트의 역량

아키텍트가 가져야 역량

  • 기술 관점
 아키텍트가 알아야 할 것  아키텍트는 무엇을 해야 하는가?  갖춰야 할 자질
 
  • 도메인과 관련 기술에 대한 이해
  • 어떤 기술적인 이슈가 프로젝트 성공의 핵심인지
  • 개발 기술과 설계 기술
 
  • 모델링
  • Tradeoff analysis
  • Prototype/experiment/simulation
  • 아키텍처 문서, 교육 자료, 프레젠테이션 준비
  • 기술적인 트렌드와 roadmap 분석
 
  • 창조적
  • 실용적
  • 탐구적/분석적
  • 추상적인 단계에서 작업하는 것을 즐겨야 함
  • 모호함이 발견되었을 때 새로운 솔루션을 구하는 자세


 

  • 컨설팅 관점

아키텍트가 알아야 할 것

아키텍트는 무엇을 해야 하는가?

갖춰야 할 자질

  • 압축하여 전달하는 기술
  • 컨설팅 프레임워크
  • 신뢰할 수 있는 어드바이져로서 관계 형성
  • 개발자들이 아키텍처를 통해 무엇을 원하는지 파악해야 함
  • 개발자들이 아키텍처의 가치를 이해하고 아키텍처를 어떻게 사용할 지를 알도록 도와야 함.
  • 주니어 아키텍트에 대한 멘터링
  • 다른 사람의 성공을 돕는 능력
  • 호소력이 있어야 함
  • 작업 방식을 변경하도록 돕고 작업 절차에 정통해야 함
  • 좋은 멘터, 교사로서의 능력

+ Recent posts