java DateUtil

Program/JAVA 2010.06.18 11:32

package common;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
* <b>기능</b> : <p>날짜 및 시간을 시스템으로부터 연산하는 클래스입니다. 
*
* @author Administrator
* @since 1.0
* @see java.util.Date
*/
public class DateUtil {

    public static final  int YEAR       = 1;
    public static final  int MONTH      = 2;
    public static final  int DATE       = 3;
    public static final  int MONTHFIRST = 4;
    public static final  int MONTHEND   = 5;
    
/**
  * <p>현재 날짜와 시각을  yyyyMMdd 형태로 변환 후 return.
     *
  * @param null
  * @return yyyyMMdd
  * 
  * <pre> 
  *  - 사용 예
  * String date = DateUtil.getYyyymmdd()
  * </pre>
  */
public static String getYyyymmdd(Calendar cal) {
     Locale currentLocale = new Locale("KOREAN", "KOREA");
     String pattern = "yyyyMMdd";
     SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale);
     return formatter.format(cal.getTime());
}

    /**
     * <p>GregorianCalendar 객체를 반환함.
  * 
  * @param yyyymmdd 날짜 인수
  * @return GregorianCalendar
     * @see java.util.Calendar 
     * @see java.util.GregorianCalendar
     * <p><pre>
     *  - 사용 예
     * Calendar cal = DateUtil.getGregorianCalendar(DateUtil.getCurrentYyyymmdd())
     * </pre>
  */
public static GregorianCalendar getGregorianCalendar(String yyyymmdd) {

     int yyyy = Integer.parseInt(yyyymmdd.substring(0, 4));
     int mm = Integer.parseInt(yyyymmdd.substring(4, 6));
     int dd = Integer.parseInt(yyyymmdd.substring(6));

     GregorianCalendar calendar = new GregorianCalendar(yyyy, mm - 1, dd, 0, 0, 0);

     return calendar;

}

    /**
    * <p>현재 날짜와 시각을  yyyyMMddhhmmss 형태로 변환 후 return.
    * 
  * @param null
* @return yyyyMMddhhmmss
* @see java.util.Date
    * @see java.util.Locale
    * <p><pre> 
    *  - 사용 예
    * String date = DateUtil.getCurrentDateTime()
    * </pre>
    */
    public static String getCurrentDateTime() {
        Date today = new Date();
        Locale currentLocale = new Locale("KOREAN", "KOREA");
        String pattern = "yyyyMMddHHmmss";
        SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale);
        return formatter.format(today);
    }

    /**
    * <p>현재  시각을  hhmmss 형태로 변환 후 return.
    * 
  * @param null
* @return hhmmss
* @see java.util.Date
    * @see java.util.Locale
    * <p><pre>
    *  - 사용 예
    *   String date = DateUtil.getCurrentDateTime()
    * </pre>
    */
    public static String getCurrentTime() {
        Date today = new Date();
        Locale currentLocale = new Locale("KOREAN", "KOREA");
        String pattern = "HHmmss";
        SimpleDateFormat formatter = new SimpleDateFormat(pattern, currentLocale);
        return formatter.format(today);

    }

    /**
    * <p>현재 날짜를 yyyyMMdd 형태로 변환 후 return.
    * 
  * @param null
* @return yyyyMMdd * 
    * <p><pre> 
    *  - 사용 예
    * String date = DateUtil.getCurrentYyyymmdd()
    * </pre>
    */
    public static String getCurrentYyyymmdd() {
        return getCurrentDateTime().substring(0, 8);
    }

/**
     * <p>주로 일자를 구하는 메소드.
     *
     * @param yyyymm 년월
     * @param week 몇번째 주
     * @param pattern 리턴되는 날짜패턴 (ex:yyyyMMdd)
     * @return 연산된 날짜
     * @see java.util.Calendar
     * <p><pre>
     *  - 사용 예
     * String date = DateUtil.getWeekToDay("200801" , 1, "yyyyMMdd")
     * </pre>
     */
    public static String getWeekToDay(String yyyymm, int week, String pattern) {

  Calendar cal = Calendar.getInstance(Locale.FRANCE);

  int new_yy = Integer.parseInt(yyyymm.substring(0,4));
  int new_mm = Integer.parseInt(yyyymm.substring(4,6));
  int new_dd = 1;

  cal.set(new_yy,new_mm-1,new_dd);
  
  // 임시 코드
  if (cal.get(cal.DAY_OF_WEEK) == cal.SUNDAY) {
   week = week - 1;
  }  
  
  cal.add(Calendar.DATE, (week-1)*7+(cal.getFirstDayOfWeek()-cal.get(Calendar.DAY_OF_WEEK)));

        SimpleDateFormat formatter = new SimpleDateFormat(pattern, Locale.FRANCE);
        
        return formatter.format(cal.getTime());
        
    }

    /**
     * <p>지정된 플래그에 따라 연도 , 월 , 일자를 연산한다.
     *
     * @param field 연산 필드
     * @param amount 더할 수
     * @param date 연산 대상 날짜
     * @return 연산된 날짜
     * @see java.util.Calendar
     * <p><pre>
     *  - 사용 예
     * String date = DateUtil.getOpDate(java.util.Calendar.DATE , 1, "20080101")
     * </pre>
     */
public static String getOpDate(int field, int amount, String date) {

     GregorianCalendar calDate = getGregorianCalendar(date);

     if (field == Calendar.YEAR) {
         calDate.add(GregorianCalendar.YEAR, amount);
     } else if (field == Calendar.MONTH) {
         calDate.add(GregorianCalendar.MONTH, amount);
     } else {
         calDate.add(GregorianCalendar.DATE, amount);
     }

     return getYyyymmdd(calDate);

}

/**
     *  <p>입력된 일자를 더한 주를 구하여 return한다
     *  
     * @param yyyymmdd 년도별 
     * @param addDay 추가일 
     * @return 연산된 주
     * @see java.util.Calendar
     * <p><pre>
     *  - 사용 예
     * int date = DateUtil.getWeek(DateUtil.getCurrentYyyymmdd() , 0)
     * </pre>
     */
public static int getWeek(String yyyymmdd, int addDay){
  Calendar cal = Calendar.getInstance(Locale.FRANCE);
  int new_yy = Integer.parseInt(yyyymmdd.substring(0,4));
  int new_mm = Integer.parseInt(yyyymmdd.substring(4,6));
  int new_dd = Integer.parseInt(yyyymmdd.substring(6,8));

  cal.set(new_yy,new_mm-1,new_dd);
        cal.add(Calendar.DATE, addDay);

  int week = cal.get(Calendar.DAY_OF_WEEK);
  return week;
}

    /** 
     * <p>입력된 년월의 마지막 일수를 return 한다.
     * 
     * @param year
     * @param month
     * @return 마지막 일수 
     * @see java.util.Calendar
     * <p><pre>
     *  - 사용 예
     * int date = DateUtil.getLastDayOfMon(2008 , 1)
     * </pre>
     */
    public static int getLastDayOfMon(int year, int month) { 

        Calendar cal = Calendar.getInstance();
        cal.set(year, month, 1);
        return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
     
    }//:

    /** 
     * <p>입력된 년월의 마지막 일수를 return한다
     * 
     * @param year
     * @param month
     * @return 마지막 일수  
     * <p><pre>
     *  - 사용 예
     * int date = DateUtil.getLastDayOfMon("2008")
     * </pre>
     */ 
    public static int getLastDayOfMon(String yyyymm) {

        Calendar cal = Calendar.getInstance();
        int yyyy = Integer.parseInt(yyyymm.substring(0, 4));
        int mm = Integer.parseInt(yyyymm.substring(4)) - 1;

        cal.set(yyyy, mm, 1);
        return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
    }
    
    /** 
     * <p>입력된 날자가 올바른지 확인합니다. 
     * 
     * @param yyyymmdd
     * @return boolean 
     * <p><pre>
     *  - 사용 예
     * boolean b = DateUtil.isCorrect("20080101")
     * </pre>
     */ 
    public static boolean isCorrect(String yyyymmdd)
    {     
     boolean flag  =  false;
     if(yyyymmdd.length() < 8 ) return false; 
     try
     {
      int yyyy = Integer.parseInt(yyyymmdd.substring(0, 4));
      int mm   = Integer.parseInt(yyyymmdd.substring(4, 6));
      int dd   = Integer.parseInt(yyyymmdd.substring(6));
      flag     = DateUtil.isCorrect( yyyy,  mm,  dd);
     }
     catch(Exception ex)
     {
      return false; 
     }
     return flag;
    }//:
    
    /** 
     * <p>입력된 날자가 올바른 날자인지 확인합니다. 
     * 
     * @param yyyy
     * @param mm
     * @param dd
     * @return boolean
     * <p><pre>
     *  - 사용 예
     * boolean b = DateUtil.isCorrect(2008,1,1)
     * </pre>
     */
    public static boolean isCorrect(int  yyyy, int mm, int dd)
    {
     if(yyyy < 0 || mm < 0 || dd < 0) return false;
     if(mm > 12 || dd > 31) return false; 
     
     String year     = "" + yyyy; 
     String month    = "00" + mm;
     String year_str = year + month.substring(month.length() - 2);
     int endday      = DateUtil.getLastDayOfMon(year_str);
     
     if(dd > endday) return false; 
     
     return true; 
     
    }//:
    
    /** 
     * <p>현재 일자를 입력된 type의 날짜로 반환합니다.
     * 
     * @param type
     * @return String
     * @see java.text.DateFormat
     * <p><pre>
     *  - 사용 예
     * String date = DateUtil.getThisDay("yyyymmddhhmmss")
     * </pre>
     */    
    public static String getThisDay(String type)
    {
        Date date = new Date();
        SimpleDateFormat sdf = null;
        
        try{
         if(type.toLowerCase().equals("yyyymmdd"))
         {
             sdf = new SimpleDateFormat("yyyyMMdd");
             return sdf.format(date);
         }
         if(type.toLowerCase().equals("yyyymmddhh"))
         {
             sdf = new SimpleDateFormat("yyyyMMddHH");
             return sdf.format(date);
         }
         if(type.toLowerCase().equals("yyyymmddhhmm"))
         {
             sdf = new SimpleDateFormat("yyyyMMddHHmm");
             return sdf.format(date);
         }
         if(type.toLowerCase().equals("yyyymmddhhmmss"))
         {
             sdf = new SimpleDateFormat("yyyyMMddHHmmss");
             return sdf.format(date);
         }
         if(type.toLowerCase().equals("yyyymmddhhmmssms"))
         {
             sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
             return sdf.format(date);
         } 
         else
         {
          sdf = new SimpleDateFormat(type);
             return sdf.format(date);
         }
        }catch(Exception e){
            return "[ ERROR ]: parameter must be 'YYYYMMDD', 'YYYYMMDDHH', 'YYYYMMDDHHSS'or 'YYYYMMDDHHSSMS'";
        }
    }

    /** 
     * <p>입력된 일자를 '9999년 99월 99일' 형태로 변환하여 반환한다.
     * 
     * @param yyyymmdd
     * @return String
     * <p><pre>
     *  - 사용 예
     * String date = DateUtil.changeDateFormat("20080101")
     * </pre>
     */      
public static String changeDateFormat(String yyyymmdd)
    {
     String rtnDate=null;    

  String yyyy = yyyymmdd.substring(0, 4);
  String mm   = yyyymmdd.substring(4,6);
  String dd   = yyyymmdd.substring(6,8);
  rtnDate=yyyy+" 년 "+mm + " 월 "+dd + " 일";  
     
     return rtnDate;
     
    }

    /** 
     * <p>두 날짜간의 날짜수를 반환(윤년을 감안함)
     * 
  * @param startDate 시작 날짜
  * @param endDate 끝 날짜
  * @return 날수
     * @see java.util.GregorianCalendar 
     * <p><pre>
     *  - 사용 예
     * long date = DateUtil.getDifferDays("20080101","20080202")
     * </pre>
     */ 
public static long getDifferDays(String startDate, String endDate) {

     GregorianCalendar StartDate = getGregorianCalendar(startDate);
     GregorianCalendar EndDate = getGregorianCalendar(endDate);
     long difer = (EndDate.getTime().getTime() - StartDate.getTime().getTime()) / 86400000;
     return difer;

    }

    /** 
     * <p>현재의 요일을 구한다.
     * 
  * @param
  * @return 요일
     * @see java.util.Calendar 
     * <p><pre>
     *  - 사용 예
     * int day = DateUtil.getDayOfWeek()
     *  SUNDAY    = 1
     *  MONDAY    = 2
     *  TUESDAY   = 3
     *  WEDNESDAY = 4
     *  THURSDAY  = 5
     *  FRIDAY    = 6
     * </pre>
     */
    public static int getDayOfWeek(){
        Calendar rightNow = Calendar.getInstance();
        int day_of_week = rightNow.get(Calendar.DAY_OF_WEEK);
        return day_of_week;
    }

    /** 
     * <p>현재주가 올해 전체의 몇째주에 해당되는지 계산한다. 
     * 
  * @param
  * @return 요일
     * @see java.util.Calendar 
     * <p><pre>
     *  - 사용 예
     * int day = DateUtil.getWeekOfYear()
     * </pre>
     */    
    public static int getWeekOfYear(){
     Locale LOCALE_COUNTRY = Locale.KOREA;
        Calendar rightNow = Calendar.getInstance(LOCALE_COUNTRY);
        int week_of_year = rightNow.get(Calendar.WEEK_OF_YEAR);
        return week_of_year;
    }
    
    /** 
     * <p>현재주가 현재월에 몇째주에 해당되는지 계산한다. 
     * 
  * @param
  * @return 요일
     * @see java.util.Calendar 
     * <p><pre>
     *  - 사용 예
     * int day = DateUtil.getWeekOfMonth()
     * </pre>
     */     
    public static int getWeekOfMonth(){
     Locale LOCALE_COUNTRY = Locale.KOREA;
        Calendar rightNow = Calendar.getInstance(LOCALE_COUNTRY);
        int week_of_month = rightNow.get(Calendar.WEEK_OF_MONTH);
        return week_of_month;
    }
    
    /** 
     * <p>해당 p_date날짜에 Calendar 객체를 반환함.
     * 
  * @param p_date
  * @return Calendar
     * @see java.util.Calendar 
     * <p><pre>
     *  - 사용 예
     * Calendar cal = DateUtil.getCalendarInstance(DateUtil.getCurrentYyyymmdd())
     * </pre>
     */ 
    public static Calendar getCalendarInstance(String p_date){
     //Locale LOCALE_COUNTRY = Locale.KOREA;
     Locale LOCALE_COUNTRY = Locale.FRANCE;
        Calendar retCal = Calendar.getInstance(LOCALE_COUNTRY);

        if(p_date != null && p_date.length() == 8){
            int year  = Integer.parseInt(p_date.substring(0,4));
            int month = Integer.parseInt(p_date.substring(4,6))-1;
            int date  = Integer.parseInt(p_date.substring(6));

            retCal.set(year, month, date);
       }
       return retCal;
    }

}
저작자 표시 비영리 변경 금지
신고

'Program > JAVA' 카테고리의 다른 글

java DateUtil  (0) 2010.06.18
tomcat 5.5 버전에서의 server.xml 설정하기 context path 추가하기  (0) 2008.05.19
tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19

tomcat 5.5 버전에서의 server.xml 설정하기 context path 추가하기

Program/JAVA 2008.05.19 11:10
5.5 부터 기존 server.xml 에 context path 추가 하지 말라네요..

해보니 기존처럼 해도 되긴 되는데.. 뭐 보안상의 이유로 그렇게 하지 말라고 하네요.

인터넷 찾아보니 간단하긴 합니다

방식은 아래와 같다.


우선 server.xml 의 Host name 에다가 자신이 만들고 싶은 host name 을 기술한다.

그다음 tomcat 설치디렉토리/conf/Catalina/ 디렉토리 밑에 host name 에 기술한 이름의 디렉토리를 만든다.

그리고 그 디렉토리안에 ROOT.xml 파일을 만들어서 context path 를 지정하는 형식이다.


예)

톰캣 설치디렉토리 : C:\web\Tomcat

웹 서비스들 페이지가 있는 디렉토리 : D:\work_nio

웹 서비스 페이지 1 : D:\work_nio\swing.naver.com\WEB-INF\src

웹 서비스 페이지 2 : D:\work_nio\me.naver.com\WEB-INF\src


즉, 톰캣이 설치된 디렉토리에서 웹페이지들 및 소스를 나두는것이 아니고

별도의 디렉토리를 만들어서 이곳에서 웹페이지들 및 소스들 넣고 싶은것이다.

보통 이렇게들 많이 운영을 할것이다. apache 의 virtualhost 를 생각하면 될것이다.


위는 swing.naver.com , me.naver.com 으로 웹 서버를 운영하고 싶은 예를 둔것이다.



< 단계 1 >

C:\web\Tomcat\conf\server.xml 편집


   <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false"

     xmlNamespaceAware="false">
   </Host>
   

이렇게만 있는 부분 바로 아래에 다음과 같이 추가를 해준다.


   <Host name="swing.naver.com" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false"

     xmlNamespaceAware="false">
   </Host>


   <Host name="me.naver.com" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false"

     xmlNamespaceAware="false">
   </Host>


그리고 기본적으로 port 는 8080 으로 되어있는데 이렇게 되면 http://swing.naver.com:8080 이런식으로 주소를 넣어야하니

불편하기 그지없다. port="8080" 을 port="80" 으로 변경을 하여 http://swing.naver.com 으로 접속할 수 있도록 해준다.



< 단계2 >

C:\web\Tomcat\conf\Catalina 디렉토리 밑에

server.xml 파일에서 입력해준 host name 으로 디렉토리를 만들어준다.


아마 기본적으로 localhost 라는 디렉토리는 있을 것이다.

즉,

C:\web\Tomcat\conf\Catalina\swing.naver.com

C:\web\Tomcat\conf\Catalina\me.naver.com



< 단계3 >

만들어준 디렉토리밑에 ROOT.xml 파일을 각각 만들어준다.

즉,

C:\web\Tomcat\conf\Catalina\swing.naver.com\ROOT.xml

C:\web\Tomcat\conf\Catalina\me.naver.com\ROOT.xml



< 단계4 >

이렇게 만들어준 각각의 ROOT.xml 에 바로 context path 를 기술해 주면 된다.


C:\web\Tomcat\conf\Catalina\swing.naver.com\ROOT.xml 의 내용


<?xml version='1.0' encoding='utf-8'?>
<Context crossContext="true" docBase="D:/work_nio/swing.naver.com" path="" reloadable="true">
</Context>



C:\web\Tomcat\conf\Catalina\me.naver.com\ROOT.xml 의 내용


<?xml version='1.0' encoding='utf-8'?>
<Context crossContext="true" docBase="D:/work_nio/me.naver.com/" path="" reloadable="true">
</Context>



< 단계 5 >

톰캣을 stop 한 후 start 한다.


이제 웹에서 http://swing.naver.com/index.html 하면 나올거에요~


단, D:/work_nio/swing.naver.com/WEB-INF\src 밑에 index.html 파일이 있어야겠고

이런 도메인 주소를 가지고 있어야겠죠.


만약에 지금 내 PC에서 테스트를 하고 싶다면 충분히 localhost 가지고만 하실 수 있습니다.

하지만 자신 PC의 IP로 주위사람들이 웹에서 ip 주소를 입력하여 들어오고 싶을때는

ip로 host name 을 지정하여 위의 단계처럼 만드시면 되겠죠~

신고

'Program > JAVA' 카테고리의 다른 글

java DateUtil  (0) 2010.06.18
tomcat 5.5 버전에서의 server.xml 설정하기 context path 추가하기  (0) 2008.05.19
tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19

tomcat web.xml

Program/JAVA 2008.05.19 11:05

web.xml파일의 구성

1. x파일은 다음과 같이 구성된다.

- xml정의와 스키마 선언부

- 웹 애플리케이션 전체 설정

- jsp, 서블릿 관련 설정

- tag library 관련 설정

- 기타설정

2. xml정의와 스키마 선언부 : xml정의와 스키마 선언부는 xml문서에서 공통으로 필요한 xml 버전 선언과 스키마를 정의하는 부분으로 다음과 같이 공통된 버전 정의와 스키마를 가진다.

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

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

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

3. 웹 애플리케이션 전체 설정

<web-app>

        <display-name>애플리케이션 이름</display-name>

        <description>애플리케이션에 대한 설명</description>

        <welcome-file-list>

               <welcome-file>처음 시작할 파일 이름</welcome-file>

               <welcome-file>두번재로 시작할 파일 이름</welcome-file>

        </welcome-file-list>

</web-app>

4. jsp, 서블릿 관련 설정

        <servlet>

               <servlet-name>서블릿이름</servlet-name>

               <jsp-page>jsp페이지 경로</jsp-page>

               <servlet-class>서블릿클래스 경로</servlet-class>

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

               <init-param>

                       <description>인자설명</description>

                       <param-name>인자이름</param-name>

                       <param-value>인자값</param-value>

               </init-param>

        </servlet>

        <servlet-mapping>

               <servlet-name>매핑할 서블릿이름</servlet-name>

               <url-pattern>매핑 패턴</url-pattern> 

        </servlet-mapping>

 

<load-on-startup>1</load-on-startup> : 0보다 큰값이면 배포 또는 서버실행시에 초기화하게 된다.

개발자가 설정하지 않으면 최초요청시에 초기화하게 되므로 시간이 소요됨..

5. tag library 관련 설정

<web-app>

        <taglib>

               <taglib-uri>태그라이브러리 경로</taglib-uri>

               <taglib-location>TLD(Tag Library Descriptor)</taglib-location>

        </taglib>

</web-app>

6. 기타설정

<web-app>

        <context-param>

               <description>설명</description>

               <param-name>인자이름</param-name>

               <param-value>인자값</param-value>

        </context-param>

</web-app>

 

 

 

또하나의 예제

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

[Tomcat] web.xml에 대한 예제..

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>


<!-- 웹 어플리케이션의 일반적 설명 -->

<display-name>My Web Application</display-name>
<description>
이것은 와일드하고 훌륭한 작업을 수행하는 servlet과 JSP
기반한 애플리케이션의 X.X 버전입니다. 이 문서는 개발자
Dave 가 작성했고, 더 자세한 정보를 원하시면
dave@mycompany.com 으로 연락할 수 있습니다.
</description>


<!-- Context 초기 파라메터: 어플리케이션에서 사용되는 공유
된 문자열 상수들을 선언합니다. 이것은 애플리케이션을
설치하는 시스템 관리자가 변경할 수 있습니다. 이들 파
라메터에 실질적으로 할당된 값들은 servlet 과 JSP page
에서 다음과 같이 불러올 수 있습니다:

String value =
getServletContext().getInitParameter("name");

여기서 "name" 은 <param-name> 이들 초기 파라메터 중에
하나의 엘리먼트와 같습니다.

컨텍스트 초기 파라메터의 갯수는 제한이 없고, 아무것도
없어도 됩니다.
-->

<context-param>
<param-name>webmaster</param-name>
<param-value>myaddress@mycompany.com</param-value>
<description>
The EMAIL address of the administrator to whom questions
and comments about this application should be addressed.
</description>
</context-param>


<!-- 초기 파라메터를 포함해, 웹 애플리케이션을 구성하는
servlet 에 대한 정의. Tomcat 에서, 브라우저에서 servlet
요청시 아래와 같이 함으로 web.xml 파일에 등록안된 것도
부를 수 있습니다:

http://localhost:8080/{context-path}/servlet/{classname}

그러나 이런 사용법은 유동성을 보장하지 못합니다. 또한
servlet이 이미지나 다른 자원에 접근하기 위해서는 상대 경로
를 지정해야 되는 등 servlet이 매우 복잡하게 됩니다. 그래서
모든 servlet 을 정의해 주는 것을 (그리고 servlet-매핑 요소
로 정의하는 것) 권장합니다.

Servlet 초기 파라메터는 servlet 과 JSP page 에서 다음과 같
이 불러올 수 있습니다:

String value =
getServletConfig().getInitParameter("name");

여기서 "name" 은 <param-name> 이들 초기 파라메터 중에
하나의 엘리먼트와 같습니다.

servlet 갯수는 제한이 없고, 아무것도 없어도 됩니다.
-->

<servlet>
<servlet-name>controller</servlet-name>
<description>
이 어플리케이션에 사용된 MVC 구조에서 이 servlet은 "controller"
역할을 합니다. 보통 <servlet-mapping> 엘리먼트와 함께 ".do" 파일
확장자로 매핑됩니다. 그리고 이 애플리케이션에서 사용되는 모든
form은 요청하는 주소가 "saveCustomer.do" 처럼 지정됩니다. 이
servlet에 매핑된 servlet입니다.

이 servlet에 대한 초기 파라메터 명은 (파일 확장자가 제거된 후에)
이 servlet 이 받는 "servlet path" 입니다. 상응하는 값은 이 요청을
처리하는 데 사용할 action class 의 이름입니다.
</description>
<servlet-class>com.mycompany.mypackage.ControllerServlet</servlet-class>
<init-param>
<param-name>listOrders</param-name>
<param-value>com.mycompany.myactions.ListOrdersAction</param-value>
</init-param>
<init-param>
<param-name>saveCustomer</param-name>
<param-value>com.mycompany.myactions.SaveCustomerAction</param-value>
</init-param>
<!-- 시동할 때 이 servlet을 서버에 로딩한다 -->
<load-on-startup>5</load-on-startup>
</servlet>

<servlet>
<servlet-name>graph</servlet-name>
<description>
이 servlet 은 동적으로 생성된 그래프 GIF 이미지를 생성합니다.
이 요청에 포함된 입력된 파라메터값을 갖고 생성합니다. 보통
"/graph" 라는 구별된 URI 요청에 매핑되어 있습니다.
</description>
</servlet>


<!-- 특정한 요청 URI (context-상대적인)를 특정한 servlet으로 해석
하는 servlet 컨테이너에 의해 사용되는 매핑을 선언하기.
아래 예제는 위에 있는 servlet 설명과 관계있습니다. 그러므로,
요청 URI 는 다음과 같습니다:

http://localhost:8080/{contextpath}/graph

주소는 "graph" servlet 에 매핑됩니다. 한편:

http://localhost:8080/{contextpath}/saveCustomer.do

은 "controller" servlet 에 매핑됩니다.

servlet 매핑의 갯수는 제한이 없고, 아무것도 없어도 됩니다.
원한다면 하나의 servlet 에 한 개 이상의 매핑을 해주어도 됩니다.
-->

<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>graph</servlet-name>
<url-pattern>/graph</url-pattern>
</servlet-mapping>


<!-- 어플리케이션의 기본 세션 타임아웃 시간을 분단위로 설정합
니다. servlet 이나 JSP page 에서, 동적으로 특정한 session
에 대해 시간을 조정할 수 있습니다.
HttpSession.getMaxInactiveInterval() 을 사용하면 됩니다.
-->

<session-config>
<session-timeout>30</session-timeout> <!-- 30 minutes -->
</session-config>


</web-app>

<error-page>
<error-code>
500
</error-code>
<location>
/errorPage.jsp
</location>
</error-page>
<error-page>
<exception-type>
javax.servlet.ServletException
</exception-type>
<location>
/servlet/ErrorDisplay
</location>
</error-page>

신고

'Program > JAVA' 카테고리의 다른 글

java DateUtil  (0) 2010.06.18
tomcat 5.5 버전에서의 server.xml 설정하기 context path 추가하기  (0) 2008.05.19
tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19

tomcat 6.0 host 추가

Program/JAVA 2008.05.19 11:03

[www.test.com 을 추가하는 예]

<Host name=www.test.com  appBase="D:/Development/web/dwr"

         unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
         <Context docBase="/" path="" reloadable="true"/>

</Host>

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


Host.name : 추가할 호스트이름

Host.appBase : 서비스할 기본 디렉토리

                       디렉토리 구분자는 '/'와 '\' 모두 사용 가능함

                       예) D:/Development/web/dwr

                            D:/Development/web/dwr/

                            C:\temp

                            C:\temp\

Context.docBase : 기본 디렉토리를 기준으로 서비스할 상대 경로

                           디렉토리 구분자는 '/'와 '\' 모두 사용 가능함

                           예) /

                                /test

                               \temp\test

Context.path : 추가할 호스트이름 뒤에 붙을 디렉토리명

                     예) "" -> www.test.com

                          "/test" -> www.test.com/test

Context.reloadable : 클래스의 변경여부를 주기적으로 체크해서 서비스에 반영할지를 결정하는 속성

                             개발시에는 true, 운영시에는 false가 권장됨

신고

tomcat server.xml

Program/JAVA 2008.05.19 11:01

server.xml는 다음과 같은 구조로 구성되어있습니다.

-. Top level Elements : <server>는 설정파일 전체에서 Root Element이며 반면에

    <service>는 하나의 Engine과 연관된 Connector들의 집합을 말합니다.

    top level elements에는 <server>, <service>등이 있습니다.


-. Connector : 외부 Client와 요청을 주고 응답을 받는 Interface를 말합니다.

    connector에는 <HTTP>, <AJP>등이 있습니다. 오호~ 프로토콜과 관계된 것들이군요


-. Containers : 요청을 받아 응답을 처리하는 기능들의 Component를 말합니다.

     하나의 Engine은 하나의 Service에대한 모든 요청을 처리하며,

     하나의 Host는 하나의 Virtual Host에 대한 모든 요청을 처리하며,

     하나의 Context는 하나의 Web Appliction에 대한 모든 요청을 처리합니다.

    container에는 <Context>, <Engine>, <Host>등이 있습니다.


-. Nested Component : Nested Component는  Container의 어느 Element안에 중첩될 수도

    있으며 어떤 Element들은 Container안에도 중첩될 수 있는 반면에 다른것들은

     Context안에만 중첩될 수 있다.

    <Logger>, <Realm>, <Resources>, <Loader>등이 있습니다.


위에서 보니 볼것이 생각외로 많습니다.

하지만 머니머니 해도 젤 중요한건 Context이겠죠. 요 Context만 살작 보겠습니다.


Context가 그럼 멀까요?

Context는 특별한 Viertual Host에서 작동하는 하나의 Web Application입니다.

각 Web Application은 하나의 Web Application Archive(WAR) file나,

이에 대응하는 unpacked된 Content를 가지는 directory를 말합니다.


Tomcat 4.x 대 까지만 해도 context는 server.xml에 기술할 수 있었습니다.

하지만 Tomcat 5.x대 부터는 달라졌더군요.

<Host> elements안에 contenxt를 추가할 수 있지만 xml형식의 개별적인 파일로 저장 할 수도 있습니다.

개별적으로 저장하려면 위치는 $CATALINA_HOME/conf/[enginename]/[hostname]/ directory 가 됩니다.

실제로 이 위치에 가보면 admin.xml등의 파일이 있는 것을 볼 수 있습니다.

디폴트로 된 context의 xml를 만들려면 ROOT.xml로 만드시면 됩니다.

참고로 tomcat문서에서는 <Context>를 server.xml에 직접 기술하는것을 강력히 비추천 하는군요 -ㅠ-


예제) ROOT.xml 입니다. (reloadable="true"를 추가했군요~)

<Context path="" docBase="${catalina.home}/webapps/ROOT"
        debug="0" privileged="true" reloadable="true">

  <Logger className="org.apache.catalina.logger.FileLogger"
                 directory="logs"  prefix="localhost_log." suffix=".txt"
            timestamp="true"/>

</Context>

Logger를 잠시보면 로거로 FileLogger라는 클래스를 사용할 것이며

디렉토리는 톰캣의 logs디렉토리를, 파일명은 localhost_log.yyyy-mm-dd.txt로 하겠다는 겁니다.


여기에 test라는 Context를 하나 더 추가해 봅시다.

우선 test.xml을 다음과 같이 만들어 봅시다.

<Context path="/test" docBase="${catalina.home}/webapps/test"
        debug="0" privileged="true" reloadable="true">

  <Logger className="org.apache.catalina.logger.FileLogger"
                 directory="logs"  prefix="localhost_log." suffix=".txt"
            timestamp="true"/>

</Context>

path에는 context 경로를 적습니다. 각 요청 URI의 시작부분이 context 경로와 같을 때 해당 웹어플리케이션이 그 요청을 처리하게 됩니다. docBase는 이 웹어플리케이션에 대한 파일 경로입니다

설정 끝~

http://localhost:8080/test 를 요청하게 되면 해당 /webapps/test 밑에 있는 파일을 요청하게 됩니다


그럼 Context의 속성을 알아봅시다.


속성 설명
backgroundProcessorDelay 이 값은 컨텍스트와 그 자식 컨테이너에서 background process method가 invoke되는 delay 시간을 나타낸다.
이 값을 양수로 설정하면 어떤 쓰레드가 분기되어 일정 시간 후에 이 쓰레드가 해당 host와 자식 컨테이너에서 background process method를 실행시킵니다
만약 설정하지 않으면 디폴트값인 -1을 가지며 음수의 값은 부모 host의 background processing 정책을 사용한다는 것입니다.
참고로 컨텍스트는 세션을 종료하거나 클래스 리로딩을 위한 모니터링등을 위해 background processing을 사용합니다.
className

사용할 Java 구현체 클래스의 이름. 이 클래스는 반드시 org.apache.catalina.Context 인터페이스를 구현해야 합니다. 지정하지 않으면 표준값 (아래에 정의됩니다)이 사용됩니다

cookies

true (디폴트)로 지정하면 클라이언트가 쿠키를 지원하는 경우 세션확인의 통신수단(session identifier communication)으로 쿠키를 사용합니다. false로 지정하면 세션확인의 통신수단으로 쿠키 사용을 하지 않고, 어플리케이션에 의한 URL 다시쓰기(URL rewriting)에만 의존한다는 의미입니다.

crossContext

true 로 지정하면 이 어플리케이션에서 ServletContext.getContext() 호출을 통해, 이 가상호스트에서 실행중인 다른 웹어플리케이션에 대한 요청디스패쳐(request dispatcher)를 성공적으로 얻을 수 있습니다. 보안상의 이유로 false(디폴트)로 지정하면 getContext()는 언제나 null을 반환하게 됩니다.

docBase

이 웹어플리케이션에 대한 Document Base (Context Root로도 알려져 있습니다) 디렉토리, 또는 웹어플리케이션 아카이브 파일의 경로명(웹어플리케이션을 WAR 파일로 직접 실행하는 경우)을 나타냅니다. 이 디렉토리나 WAR 파일에에 대한 절대경로명을 지정할 수도 있고, 이 Context가 정의된 Host의 appBase 디렉토리에 대한 상대경로명을 지정할 수도 있습니다

override true로 설정하면 DefaultContext element를 관련된 host에서 명백하게 상속받아 사용합니다
기본값으로 Defaultcontext element가 사용됩니다
privileged

true로 설정하면 이 컨텍스트는 관리자서블릿(manager servlet) 같은 컨테이너 서블릿을 사용할 수 있습니다.

path

이 웹어플리케이션의 컨텍스트 경로(context path)를 나타내며, 각 요청 URI의 시작부분이 컨텍스트 경로와 같을 때 해당 웹어플리케이션이 그 요청을 처리하게 됩니다. 하나의 특정 Host 내의 컨텍스트 경로들은 모두 각각 유일해야 합니다. 만약 컨텍스트 경로를 빈 스트링("")으로 지정하면, 이 Context는 이 Host에 대한 디폴트 웹어플리케이션으로 정의된 것입니다. 디폴트 웹어플리케이션은 다른 Context 들에 해당되지 않는 모든 요청을 처리할 것입니다.

reloadable

true 로 지정하면, Catalina는 /WEB-INF/classes/와 /WEB-INF/lib 안 클래스 들의 변경여부를 감시하다가, 변경이 발견되면 웹어플리케이션을 자동으로 재적재(reload)합니다. 이 기능은 개발중에는 매우 유용하지만 얼마간의 실행부하(runtime overhead)가 발생하므로, 실제 운영할 용도로 어플리케이션을 배치(deploy)할 때는 사용하지 않도록 합니다. 그러나 이미 배치가 끝난 어플리케이션이라도 Manager 웹어플리케이션을 이용하면 필요할 때 재적재 하도록 할 수 있습니다

wrapperClass

이 Context로 관리할 서블릿 들에 대해 사용할 org.apache.catalina.Wrapper 구현체 클래스의 Java 클래스명입니다. 지정하지 않으면 표준값이 사용됩니다


from http://jakarta.apache.org

신고

'Program > JAVA' 카테고리의 다른 글

tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19
java :코드성데이터의 클래스생성  (0) 2008.05.19
java로 연관배열  (0) 2008.05.14

Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용

Program/JAVA 2008.05.19 11:00
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용 이미 눈치 채셨겠지만, 요즘 내가 RDBMS 배우기에 열을 올리고 있다. 지금까지는 JSP/Servlet에서 직접 커넥션을 맺거나, 웹 컨텍스트내에 커넥션 풀 라이브러리를 두고 호출에서 사용했는데, 좀 바꿔야겠다. JNDI를 통한 커넥션 풀 사용은 J2EE 표준이고, 현존하는 거의 모든 웹 컨테이너가 지원한다고 한다. JNDI를 서버에 설정하는 방법은 각 WAS 별로 다르지만, 사용하는 것은 모두 동일하므로 호환성에 문제도 없다. 이 글은 Jakarta의 DBCP 커넥션 풀과 Tomcat JNDI 설정을 통해 데이터베이스 커넥션 풀을 사용하는 방법이다. JNDI와 커넥션 풀에 관한 자세한 설명이 JavaServer Pages 3rd ed.에 실려있다. 이 책 너무 좋다. 꼭 읽어보라고 강력하게 권하고 싶다.

기본적으로 필요한 라이브러리

  • commons-dbcp.jar
  • commons-collections.jar
  • commons-pool.jar

예제 JDBC 드라이버

  • Oracle 9i classes12.jar

JNDI Naming Resource 설정

1.       라이브러리들을 $CATALINA_HOME/common/lib 복사한다. 이외 디렉토리에 두면 안된다. ZIP 파일은 JAR 확장자를 바꿔야 한다. 톰캣은 JAR파일만 클래스패스에 추가한다.

2.       Connection 풀을 이용할 경우에는 ResultSet Connection 객체를 필히 직접 닫아 줘야만 한다.

3.       $CATALINA_HOME/conf/server.xml 혹은 컨텍스트별 XML 파일의 <Context> 자식 요소로 다음을 추가한다.

4.                <Resource name="jdbc/forumDb" auth="Container" type="javax.sql.DataSource"/>

5.                <!-- Resource name 속성을 이용해서 어플리케이션에서

6.                                javax.sql.DataSource 객체를 얻어가게 된다. -->

7.               

8.               

9.                <!-- 자세한 파라미터 설정은

10.               http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html 참조 -->

11.            <ResourceParams name="jdbc/forumDb">

12.              <parameter>

13.                <name>factory</name>

14.                <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

15.              </parameter>

16.           

17.              <parameter>

18.                <name>maxActive</name>

19.                <value>100</value>

20.              </parameter>

21.           

22.              <parameter>

23.                <name>maxIdle</name>

24.                <value>30</value>

25.              </parameter>

26.           

27.              <parameter>

28.                <name>maxWait</name>

29.                <value>10000</value>

30.              </parameter>

31.           

32.                              <!-- DB 사용자명과 비밀번호 설정 -->

33.              <parameter>

34.               <name>username</name>

35.               <value>dbuser</value>

36.              </parameter>

37.              <parameter>

38.               <name>password</name>

39.               <value>dbpasswd</value>

40.              </parameter>

41.           

42.                              <!-- JDBC 드라이버 클래스 -->

43.              <parameter>

44.                 <name>driverClassName</name>

45.                 <value>oracle.jdbc.driver.OracleDriver</value>

46.              </parameter>

47.             

48.                              <!-- JDBC 접속 URL -->

49.              <parameter>

50.                <name>url</name>

51.                <value>jdbc:oracle:thin:@dbhost:1521:ORA</value>

52.              </parameter>

53.           

54.                  <!-- 커넥션에 문제 없는지 테스트하는 쿼리 -->

55.              <parameter>

56.                <name>validationQuery</name>

57.                <value>select sysdate</value>

58.              </parameter>

59.            </ResourceParams>

 

60.    어플리케이션의 web.xml파일에 다음을 추가하여 JNDI 리소스를 사용할 있도록 한다.

61.                              <resource-ref>

62.                                                   <description>Forum DB Connection</description>

63.                                                   <!-- 다음이 바로 리소스의 이름 -->

64.                                                   <res-ref-name>jdbc/forumDb</res-ref-name>

65.                                                   <res-type>javax.sql.DataSource</res-type>

66.                                                   <res-auth>Container</res-auth>

67.                              </resource-ref>

 

JSP/Servlet 에서 사용하기

이제 다음과 같이 JNDI 이용해 DataSource 객체를 얻고, 객체에서 커넥션을 얻어오면 된다.

 

다음은 서블릿을 작성하고, 서블릿에서 DB커넥션을 얻고, 쿼리를 날린 , 결과를 JSP 파일에 포워딩하여 JSTL 이용해 출력하는 것이다.

 

1.       예제 테이블과 데이터 SQL - 오라클 계정으로 다음과 같은 데이터를 생성했다고 가정하면

2.              create table test (

3.                                  num NUMBER NOT NULL,

4.                                  name VARCHAR2(16) NOT NULL

5.              );

6.               

7.              truncate table test;

8.               

9.              insert into test values(1,'영희');

10.          insert into test values(2, '철수');

11.          insert into test values(3, '미숙');

12.          commit;

 

13.    test.JndiDataSourceTestServlet 소스

14.          package test;

15.           

16.          import java.io.IOException;

17.          import java.sql.Connection;

18.          import java.sql.ResultSet;

19.          import java.sql.SQLException;

20.          import java.sql.Statement;

21.          import java.util.ArrayList;

22.          import java.util.HashMap;

23.          import java.util.List;

24.          import java.util.Map;

25.           

26.          import javax.naming.Context;

27.          import javax.naming.InitialContext;

28.          import javax.naming.NamingException;

29.          import javax.servlet.RequestDispatcher;

30.          import javax.servlet.ServletException;

31.          import javax.servlet.http.HttpServlet;

32.          import javax.servlet.http.HttpServletRequest;

33.          import javax.servlet.http.HttpServletResponse;

34.          import javax.sql.DataSource;

35.           

36.          public class JndiDataSourceTestServlet extends HttpServlet {

37.           

38.              protected void doGet(HttpServletRequest request,

39.                      HttpServletResponse response) throws ServletException, IOException {

40.           

41.                  Connection conn = null;

42.                  ResultSet rs = null;

43.                  Statement stmt = null;

44.           

45.                  try {

46.                      // 커넥션을 얻기 위한 전초작업. 부분을 메소드화 하면 되겠다. ------------

47.                      Context initContext = new InitialContext();

48.                      Context envContext = (Context)initContext.lookup("java:/comp/env");

49.                      DataSource ds = (DataSource)envContext.lookup("jdbc/forumDb");

50.                     

51.                      // 커넥션 얻기

52.                       conn = ds.getConnection();

53.                      //------------------------------------------------------------------

54.                     

55.                      String sql = "SELECT * from test";

56.                      stmt = conn.createStatement();

57.                     

58.                      rs = stmt.executeQuery(sql);

59.                     

60.                      List results = new ArrayList();

61.                     

62.                      while (rs.next()) {

63.                          Map row = new HashMap();

64.                         

65.                          row.put("num", rs.getString("num"));

66.                          row.put("name", rs.getString("name"));

67.                         

68.                          results.add(row);

69.                      }

70.                     

71.                      request.setAttribute("results", results);

72.                     

73.                      RequestDispatcher rd = request.getRequestDispatcher("/dbtest.jsp");

74.                      rd.forward(request, response);

75.                     

76.                  } catch (NamingException e) {

77.                      throw new ServletException("JNDI 부분 오류", e);

78.                  } catch (Exception e) {

79.                      throw new ServletException("뭔가 다른 부분 오류", e);

80.                  } finally {

81.                      // 리소스를 필히 반환할 !

82.                      if (rs != null) { try { rs.close(); } catch (Exception ignored) {} }

83.                      if (stmt != null) { try { stmt.close(); } catch (Exception ignored) {} }

84.                      if (conn != null) { try { conn.close(); } catch (Exception ignored) {} }

85.                  }

86.              }

87.          }

88.    web.xml 서블릿 등록

89.                              <servlet>

90.                                                   <servlet-name>dbtest.svl</servlet-name>

91.                                                   <servlet-class>test.JndiDataSourceTestServlet</servlet-class>

92.                              </servlet>

93.                              <servlet-mapping>

94.                                                   <servlet-name>dbtest.svl</servlet-name>

95.                                                   <url-pattern>/dbtest.svl</url-pattern>

96.                              </servlet-mapping>

97.    /dbtest.jsp 소스

98.          <%@ page contentType="text/html" pageEncoding="EUC-KR" %>

99.          <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

100.       <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>

101.        

102.       <!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">

103.       <html>

104.       <head>

105.       <title>JNDI DataSource Test</title>

106.       </head>

107.                        <body                  bgcolor="#FFFFFF">

108.                           <h2>Results</h2>

109.                          

110.                           <c:forEach var="row" items="${results}">

111.                                                                    NUM : ${row.num}<br />

112.                                                                    Name : ${row.name}<br />

113.                                                                    <hr />

114.                           </c:forEach>

115.       </body>

116.       </html>

 

117.이제 브라우저에서 "/dbtest.svl" 호출해보면 결과를 있다.

 

전역적인 JNDI 리소스 이용

<Resource> <ResourceParams> 요소를 server.xml <GlobalNamingResources> 자식노드로 옮기면 특정 어플리케이션이 아니라, 톰캣에 설치된 전체 어플리케이션에서 사용 있게 된다. 하지만 어플리케이션 "<Context>" 다음과 같은 설정을 해야 한다.

                    <ResourceLink

                                         name="jdbc/forumDb"

                                         global="jdbc/forumDb"

                                         type="javax.sql.DataSource"

                      />

 

아니면 server.xml에서 <Host> 요소의 자식으로 다음을 추가하면 컨텍스트별 설정 필요없이 전체 어플리케이션 컨텍스트에서 GlobalNamingResources 지정된 JNDI 리소스를 사용할 있다.

 

                    <DefaultContext>

                                         <ResourceLink

                                                             name="jdbc/forumDb"

                                                             global="jdbc/forumDb"

                                                             type="javax.sql.DataSource"

                                           />

        </DefaultContext>

 

문제가 생겼어요!

1.       DB 커넥션이 간혹 끊어져요.
Tomcat
작동중인 JVM 가비지 컬렉션을 , 시간이 JNDI Resource 파라미터로 설정한 maxWait보다 길게 경우 DB 커넥션이 끊어질 있다.
CATALINA_OPTS=-verbose:gc
옵션을 주면 $CATALINA_HOME/logs/catalina.out 가비지 컬렉션 상황이 기록된다. 거기에 GC 작업에 걸린 시간도 나오니 그것을 참조로 maxWait 파라미터를 늘려주면 된다. 보통 10~15초로 주면 된다.
GC
시간은 거의 99% 이상 1 이내에 끝나야 하나보다..

2.       무작위로 커넥션이 close 되요.
그건.. Connection 객체를 이상 close 했기 때문이다.
DB Connection Pool
close() 호출할 정말로 닫는 것이 아니라, 단지 재사용할 있다고 표시만 뿐이다.
커넥션을 사용하다가 close()하면 다른 쓰레드이서 커넥션을 있는데, 이걸 현재 쓰레드에서 계속 잡고 있다가 다시 close() 해버리면, 다른 쓰레드에서 사용중에 close()됐다고 나와 버리게 되는 거다.

3.                  conn.close();

4.                  conn = null;

위와 같이 커넥션을 close() 뒤에 바로 null 설정하여 절대로 다시 사용할 없게 만들면 이런 실수는 생기지 않을 것이다.

Tomcat 5.5 예제

        <Resource name="jdbc/myDbResource" auth="Container" type="javax.sql.DataSource"

               maxActive="10" maxIdle="5" maxWait="10000"

               username="ao" password="ao"

               driverClassName="com.mysql.jdbc.Driver"

               url="jdbc:mysql://localhost:3306/myWebApp"

 

               removeAbandoned="true"

               removeAbandonedTimeout="60"

               logAbandoned="true"

               validationQuery="select 1"

               testOnBorrow="true"

               testWhileIdle="true"

               timeBetweenEvictionRunsMillis="10000"

               minEvictableIdleTimeMillis="60000"

       />

 

저기서 removeAbandoned 리소스 반환에 실패한 (혹은 안한) 커넥션을 자동으로 닫아주는 것이다.

 

validationQuery 커넥션이 살아 있는지 테스트하는 코드이다.

 

MySQL, Connector/J Tomcat 5 예제

http://dev.mysql.com/doc/connector/j/en/cj-tomcat-config.html 나온 내용임.

<Context ....>

 

  ...

 

  <Resource name="jdbc/MySQLDB"

               auth="Container"

               type="javax.sql.DataSource"/>

 

  <!-- The name you used above, must match _exactly_ here!

 

       The connection pool will be bound into JNDI with the name

       "java:/comp/env/jdbc/MySQLDB"

  -->

 

  <ResourceParams name="jdbc/MySQLDB">

    <parameter>

      <name>factory</name>

      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

    </parameter>

 

    <!-- Don't set this any higher than max_connections on your

         MySQL server, usually this should be a 10 or a few 10's

         of connections, not hundreds or thousands -->

 

    <parameter>

      <name>maxActive</name>

      <value>10</value>

    </parameter>

 

        <!-- You don't want to many idle connections hanging around

         if you can avoid it, onl    y enough to soak up a spike in

         the load -->

 

    <parameter>

      <name>maxIdle</name>

      <value>5</value>

    </parameter>

 

    <!-- Don't use autoReconnect=true, it's going away eventually

         and it's a crutch for older connection pools that couldn't

         test connections. You need to decide if your application is

         supposed to deal with SQLExceptions (hint, it should), and

         how much of a performance penalty you're willing to pay

         to ensure 'freshness' of the connection -->

 

    <parameter>

      <name>validationQuery</name>

      <value>SELECT 1</value>

    </parameter>

 

   <!-- The most conservative approach is to test connections

        before they're given to your application. For most applications

        this is okay, the query used above is very small and takes

        no real server resources to process, other than the time used

        to traverse the network.

 

        If you have a high-load application you'll need to rely on

        something else. -->

 

    <parameter>

      <name>testOnBorrow</name>

      <value>true</value>

    </parameter>

 

   <!-- Otherwise, or in addition to testOnBorrow, you can test

        while connections are sitting idle -->

 

    <parameter>

      <name>testWhileIdle</name>

      <value>true</value>

    </parameter>

 

    <!-- You have to set this value, otherwise even though

         you've asked connections to be tested while idle,

         the idle evicter thread will never run -->

 

    <parameter>

      <name>timeBetweenEvictionRunsMillis</name>

      <value>10000</value>

    </parameter>

 

    <!-- Don't allow connections to hang out idle too long,

         never longer than what wait_timeout is set to on the

         server...A few minutes or even fraction of a minute

         is sometimes okay here, it depends on your application

         and how much spikey load it will see -->

 

    <parameter>

      <name>minEvictableIdleTimeMillis</name>

      <value>60000</value>

    </parameter>

 

    <!-- Username and password used when connecting to MySQL -->

 

    <parameter>

     <name>username</name>

     <value>someuser</value>

    </parameter>

 

    <parameter>

     <name>password</name>

     <value>somepass</value>

    </parameter>

 

    <!-- Class name for the Connector/J driver -->

 

    <parameter>

       <name>driverClassName</name>

       <value>com.mysql.jdbc.Driver</value>

    </parameter>

 

    <!-- The JDBC connection url for connecting to MySQL, notice

         that if you want to pass any other MySQL-specific parameters

         you should pass them here in the URL, setting them using the

         parameter tags above will have no effect, you will also

         need to use & to separate parameter values as the

         ampersand is a reserved character in XML -->

 

    <parameter>

      <name>url</name>

      <value>jdbc:mysql://localhost:3306/test</value>

    </parameter>

 

  </ResourceParams>

</Context>

 

Oracle 만을 위한 JNDI 설정

원문 : http://www.microdeveloper.com/html/JNDI_Orcl_Tomcat1p.html

 

1) Modify the server.xml file
In<CATALINA_HOME>/conf/server.xml between <GlobalNamingResources> and </GlobalNamingResources> add the following

   <Resource name="jdbc/<alias>"

   auth="Cont   ainer"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@<host>:<port>:<sid>"

   [user=<user>]

   [password=<password>]

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

   

 

Example

<!-- Global JNDI resources -->

 <GlobalNamingResources>

 

 <!-- Test entry for demonstration purposes -->

 <Environment name="simpl   eVal   ue" type="java.lang.Integer" value="30"/>

 

 <!-- Editable user database that can also be used by

   UserDatabaseRealm to authenticate users -->

 <Resource name="UserDatabase" auth="Container"

   type="org.apache.catalina.UserDatabase"

   description="User database that can be updated and saved"

   factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

   pathname="conf/tomcat-users.xml" />

    <!-- Every connection to 'db1' uses the same user -->

 <Resource name="jdbc/db1"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db1"

   user="scott"

   password="tiger"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

    <!-- Every connection to 'db2' must provide a username and password -->  <Resource name="jdbc/db2"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db2"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

</GlobalNamingResources>

 

2) Modify the context.xml file
In <CATALINA_HOME>/conf/context.xml between <Context> and </Context> add the following for each entry in the JNDI resource list:

<ResourceLink global="jdbc/<alias>" name="jdbc/<alias>" type="oracle.jdbc.pool.OracleDataSource"/>

 

Example

<!-- The contents of this file will be loaded for each web application -->

 <Context>

 

 <!-- Default set of monitored resources -->

 <WatchedResource>WEB-INF/web.xml</WatchedResource>

 <WatchedResource>META-INF/context.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->

 <!--

 <Manager pathname="" />

   -->

 <ResourceLink global="jdbc/db1" name="jdbc/db1" type="oracle.jdbc.pool.OracleDataSource"/>

 <ResourceLink global="jdbc/db2" name="jdbc/db2" type="oracle.jdbc.pool.OracleDataSource"/>

 </Context>

 

3) Modify the context's web.xml file (5.0.x step only - not necessary for 5.5.x)
In the <CONTEXT>/WEB-INF/web.xml between <web-app> and </web-app> add the following:

<resource-ref>

   <description><Your Description></description>

   <res-ref-name>jdbc/<alias></res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

Example

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db1</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db2</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

 

4) Restart Tomcat

신고

'Program > JAVA' 카테고리의 다른 글

tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19
java :코드성데이터의 클래스생성  (0) 2008.05.19
java로 연관배열  (0) 2008.05.14

java :코드성데이터의 클래스생성

Program/JAVA 2008.05.19 10:31



















프로젝트 실무 컨설팅
제목 :코드성데이터의 클래스생성..
간단한 프로젝트를 수행중인데..
일단 DB에는 코드성 테이블 생성을 하지 못하게되었습니다.
(DB관리자가 그런것은 낭비라고 생각하는 경향이 있어서..)

암무튼 저와 다른 개발자가 클래스를 가지고 하기로 했는데...
저같은 경우는 어떤 코드를 상수형태로 가지고 쓰자고 하고 있으며
다른 개발자는 해쉬테이블 형태로 가지고 가자고 하고 있습니다.

해쉬테이블로 가자는 이유는...DB의 구조를 그대로 
클래스로 옮기자라는 건데 그래야만 해쉬테이블내에

코드 코드에 대한 한글명 <--이런 데이터들이 다 관리된다는 이유입니다.
즉..
A01(해쉬키값) A01 신규생성 <--이런식의 데이터를 해쉬테이블로 유지하겠다는 뜻..
A02(해쉬키값) A02 확정 

반면 저같은 경우는 
아래와 같은 형태의 클래스를 가지고 가자고 하고 있습니다.

class Code{
 public static final String A01="A01";
 public static final String A02="A02";

 //이 케소드는 원래는 생각에 없었으나
 //다른 개발자와 언쟁 중에 한글설명(?)에 대한 관리에 대한 얘기가 나와서
 //이런 방식을 추가하자고 제안했습니다.
 public String getXX(String field){
  if(field.equals(A01)){
    return "신규생성";
  }
 }
}

그리고 만일 해쉬테이블로 굳이 가겠다면 일단 위의 클래스를 바탕으로
따로 확장해서 해쉬테이블로 구현하라고 하려합니다.

현제 제가 지적하고 싶은 해쉬테이블로 구현되었을 때의 문제는..
그 안의 데이터 하나를 얻어오려면 일단 키로서 A01 A02등이 주어져야 하는데
문제는 그것이 get메소드내에 하드코딩이 되어야 한다는거겠죠..

그걸방지하려면 역시 제가 제안한 코드클래스를 가지고 써야할 듯 보이구요..


제목 :힘드시겠네요.
제 생각은 다음과 같습니다.

-> DB에는 코드성 테이블 생성을 하지 못하게 되었습니다.
-> (DB관리자가 그런것은 낭비라고 생각하는 경향이 있어서..)

실환경 서비스 후에 입력된 데이터들을 점검하다 보면
생기지 말아야 할 데이터들이 입력되어 있는걸 보게 됩니다.

예를 들면 DEL_YN 이라는 필드가 있고
'Y' 일때는 삭제 'N' 일때는 삭제아님 이라는 의미를 부여했는데
엉뚱하게 null 이나 '*','&' 코드가 들어가는 경우가 발견이 됩니다.

여기서 뭐가 문제일까요? 
프로그램의 오류 문제? 
개발자간 커뮤니케이션 문제?

위의 것들이 근본적으로 해결이 될 문제는 아니라고 생각합니다.
오류는 항상 있는 것이고, 완벽한 커뮤니케이션은 불가능 한 것이기 때문이죠.

따라서 근본적인 문제점을 해결해야 하는데 
요점은 DB 상에서 해결해야 한다는 것입니다.

DEL_YN 은 not null 이라는 속성을 주고

아래 테이블을 만든 후에 

   create table T_DEL_YN AS 
   SELECT 'Y' CODE,'삭제' CODE_NAME from dual
   union all
   SELECT 'N' CODE,'삭제아님' CODE_NAME from dual

   ALTER TABLE T_DEL_YN ADD CONSTRAINT PK_CODE PRIMARY KEY (CODE);

DEL_YN 과 T_DEL_YN.CODE 의 관계를 설정하면
DEL_YN 에는 항상 'Y', 'N' 이 들어간다는 것이 
이론적으로 물리적으로 들어갈 데이터는 확정이 된다고 할 수 있습니다.

위와 같은 방법을 통해 
프로그램 오류나 커뮤니케이션 오류에 따른 
이상한 데이터가 입력되는 것을 방지할 수 있다고 생각합니다.

따라서 DB 관리자분에게 코드성 테이블이 단순히 데이터를 보관하는 관점을
버리라는 말을 하고 싶습니다.

2. 코드값을 위해 
   Code 클래스나 HashMap을 사용하는 것은 효율적이지이 않다고 생각됩니다.
   이유는

   신규 코드 추가시 컴파일을 해야지 사용할 수 있다.
     컴파일을 해야지만 그 코드를 사용할 수 있습니다.
     극단적으로 실환경에서 작업을 할 경우
     서비스를 중단해야 하는 불편이 따르게 됩니다. 

   코드에 대한 공유가 안된다.
     A와 B 의 개발자가 작업을 할 경우 
     A가 만든 코드와 B가 만든 코드가 충돌할 경우가 많습니다.
     바꾸어 말하면 서로 다른 의미의 "0001"의 코드를 만들어 사용할 수 있고
     A가 만든 코드 클래스를 B가 바꾸어 사용할 수 있다는 의미입니다.
     
   따라서 DB 관리자분을 설득할 수 없다면
   xml와 같이 공유가 가능하고 컴파일 없이 추가나 삭제가 가능한
   저장소를 사용하라고 권하고 싶습니다.


   
제목 : 아.. 그런식으로 관리가 되는군요~
아마 DB에 반영되긴 힘들겠지만...
잘 몰랐던 것을 알게 되네요..(나만몰랐나.. DB쪽은 깊이 모르니..)

지금건은 아니더라도 앞으로 하게 될 건에 대해서 염두에 두어야 할 것 같습니다.

그리고 코드공유관련해서는 두 사람이 공유할 클래스..를 가지고 하니..
충돌이 나지는 않을 듯합니다..

제목 : 코드 테이블 관리
XML을 코드 저장소로 사용하는 것은 좋은 생각입니다만, 어차피 그 내용을 불러 쓰기 위해서는
자바 객체로 담고 있어야 하겠죠? 물론 DOM 객체를 그대로 메모리에 담고 핸들링할 수도
있겠지만 어차피 키-값 구조로 담아야하는 거라면 HashMap이 낫다고 생각됩니다.

get 메소드에서 키값이 하드코딩되는 건 별 문제가 아니라고 봅니다. 어차피 DB에 코드테이블을
유지할 경우에도 코드값이 sql 문에 하드코딩되지 않겠습니까? sql에서 하드코딩을 피할 수
있다면 map에서도 피할 수 있고 map에서 피할 수 없다면 sql에서도 피할 수 없는 문제일 겁니다.

코드 클래스를 쓰는 것이 나쁜 생각은 아닙니다만, 님의 지적처럼 동적으로 변경하기가
아주 힘들겠죠. 게다가,
    public static final String A01="A01";
이런 식으로 쓰는 것은 좋지 않습니다. 차라리 쓰려면
    public static final String 신규생성="A01";
이렇게 쓰는 게 맞겠죠. 중요한 것은 사용하는 코드의 의미가 소스에도 기술되어야한다는 것입니다.
A01이라고 쓰면 코드 명세서를 찾아보지 않으면 이게 뭘 뜻하는 건지 알 수가 없죠.
실제 소스에는 신규생성이란 말이 들어가고 오히려 A01이 가려져야합니다.
제목 : Re: 저두 한글변수를 즐겨쓰는편입니다만..
저같은 경우엔 내부적으로 쓰는 코드에서만 한글변수를 즐겨사용합니다..
외부로 이용되는 코드의 경우 한글변수를 쓰면.. 왠만해서는 문제가 없지만
가령 poi나 jexcel등을 쓰지않고 그냥 jsp상으로 엑셀다운로드기능을 했을 경우
(헤더만변경해서)..
오류가 발생하게됩니다.. 원인은 역시..한글변수...(영문은 사용못하니 논외~)
(jrun상에서만 그런지도..저희회사는 jrun을 씁니다..)

그리고 그 코드성 테이블의 상태라는것을 가지고 프로그램내부적으로 제어할일이
발생합니다..
즉 현재A01상태를 A02란 상태로 바꾸는 경우가 생기는데 단순히 현재 row데이터만 A02로 
바꾸는 것이아니라 다른 테이블의 데이터역시 이 상태를 가지고 변경되어야합니다.
프로그램내부적으로 현재 변경하려는 상태가 A02인지 아니면..A01인지를 판단하려면
내부적으로 그 상태를 비교해야합니다.
또한 A01이란데이터만 A02로 바뀔 수가 있는 경우라면
만일 A03을 A02로 바꾸려했을 때는 오류가 발생해야 합니다..
그렬려면 역시 내부적으로 현재 row가 A03인지를 판단해야하는데..
해쉬테이블에 들어있는 값은 단순히 데이터들의 집합의 의미이지 특별한 의미가
있을거라고 보이진 않습니다.(우리가 생각하기엔 의미가 있겠지만..컴퓨터로서는
이것이 어떤의미를 가지는지 모른다는뜻이랄까..)

그래서 프로그램상으로..해쉬테이블상에 들어가면...
아래와같이되지만..(해당기능과 유사한모든프로그램에서)
if(field.equals("A03")){
 throw Exception~ 
}

코드성테이블을 유지하게 되면..
->
if(field.equals(Code.A03)){
 throw Exception~ 
}
위와같이 적어도 데이터가 한군데에서 유지되는 장점이 존재합니다.
(코드클래스의 값과 비교를 하게 되면 되므로 ..물론 field에서 넘어온 값은
 해쉬테이블 혹은 디비상에서 얻어온 값이 될 수 있습니다)

그리고 또한가지로서는..

저희 회사솔류션이 외국솔류션입니다..
거기의 데이터베이스내부에서 상태를 나타내는 코드 등이 삽입되어 있는데
이 코드 등은 또 별도로 자바클래스내에도 들어가 있습니다.
물론 확장을 위한 코드를 체계를 별도로 제공해서 몇가지 상태는 확장가능하지만
역시 그에 대한 코드도 자바클래스내에 내장되어서 그것과 
데이터베이스상의 상태를 바탕으로 프로그램이 움직이게 됩니다.


흠.. 정리가 잘 안되네염..^^) ... 



제목 : 왜 hashmap보다 dom이 나은가에 대해서..
글을 보다가 긁적입니다. hashmap이 dom보다 낫다.. 
a=b란 1대1식의 단순한 맵핑이상도 이하도 아닐 경우에는 hashmap이 나을 수도 있습니다만,
우리가 보아야 할 것은 그것이 모델을 표현하는데 적정한가 여부입니다.

님이 말씀하신 바와 같이 '어차피..'로 시작해서 구현한
프로젝트 중에 흔히 구현하는 code, value성 동적 리파지토리서버만 보더라도..
결국은 확장되어 a=b와 c=d에서 a=(a1,b1) b1=(c1,d1,e1)이런 것을 
포함할 수 있어야 하고 그것들 간의 관계나 데이터를 모델로써 수용할 수 있어야 합니다.
그렇다고 클래스를 동적으로 리로딩하는 것은 그리 좋은 방법은 아니라 생각됩니다..
직관적이지 않고, 모델자체가 한번 더 덧씌워져있기 때문에..

따라서 모델을 정의가능한 메타데이터인 dom은 매우 좋은 선택입니다.
'어차피'로 시작한 hashmap때문에 나중에 확장된 모델과 관계를 
결국은 하드코딩해서 쓰는 경우가 많고 자주 봐와서 긁적여봅니다..
제목 : 고민많이됩니다..^^
다 맞는 말씀같습니다.. 고민이 더 늘어버린듯..
제가 있는회사에서 그런 고민을 할 일이 별로 없었다는것이 참 지금생각하니
안타깝네요.. 이런건 실제 겪어봐야 느끼겠지요~ ^^

제목 : 박성덕
code, value의 1차원 구조라면 

다차원의 dom보다는 hash로 쓰는게 더 간단하리라 봅니다.


그런데 문제의 핵심은 code값을 hard코딩 하지 않고 

soft 코딩하고자 하시는 것 같군요

그렇다면 제 생각에는 아래의 방법을 추천합니다.

핵심은 Bean클래스와 Factory 그리고 value는 파일에 존재합니다.


아래와 같은 간단한 Bean 클래스를 만듭니다.

class CodeBean
{
  public String A01;
  public String A02;
  // 
  public getXX();
  이하 생략
}

그런 다음 사용하고자 하는 클래스에서

가령 

class XXXUsage
{
  public void xxx()
  {
     CodeBean myCode= CodeBeanFactory.getCodeBean();
     
     String mag= myCode.getA01();
     System.out.println(msg);
     // 결과는 "제고없음"

  }
}

이렇게 하면 하드코딩을 하지 않을 수 있습니다.

그리고 향후 value의 값을 변경 시킬 수 있습니다.

그럼 문제는 CodeBeanFactory를 어떻게 만드냐

두가지 방법이 있습니다. 

Factory 내 getCodeBean()메소드를 하드 코딩하는 방법....
가장 쉽죠.... 

두번째 방법.... 
java.lang.reflect 패키지를 사용해서 CodeBean클래스의 field를 

동적으로 접근하여 값을 할당하는 방법....









제목 : 어쨌든..
1차원이 다차원으로 확장되는 것은 자명한 사실이라는 점을 염두하시기 바랍니다..

code간의 관계를 1차원으로 명시하게 되면 XXXUsage, CodeBean은 수정, 확장,

관계들을 관리하는 새로운 클래스를 정의해야 될겁니다..

이런 점을 염두하시고 구현하시길.. 

추가로, reflect는 느리고 클래스 자체 접근방법 자체를 추천드리고 싶진 않습니다.
제목 : reflect ... proxy... code성 data
reflect의 경우 runtime에 동작해야 하는는 관계로 

내부적으로 복잡한 처리를 거치기 때문에

속도가 느린 것은 사실입니다. 

compiletime의 경우보다 수천배 느렸던 것 같습니다.

(replytime을 체크한 적이 있는데 수백~수천배였던 기억이)



그러나 다행인 것은 문제의 특성이 code성 데이터란 것입니다.

code성 데이터는 특성상 update 주기가 무척 깁니다.

따라서 이 주기에 비례하여 

매 요청시마다 value값을 다시 파일(혹은 db)로 부터 불러오지 않고

application이 초기 loding시 메모리에 올리는 것이 좋다고 봅니다.

loding시 약간의 시간이 걸릴 수 있으나 처음뿐이니 

실 이용시간인 그 이후의 시간에서는 문제가 되지 않으면 

동작 중에 update시킬 경우에 한해서만 값을 재적재 하도록

refresh(), invalidate() 등의 메소드를 관리자 프로그램에서 실행시키면 되리라 생각됩니다.

아 그리고 proxy를 사용하면 메소드 매 호출시마다 시간이 걸리더군요...

실제로 성격은 좀 다르겠지만 대부분의 framework가 제공하는 

configuration이 이와 비슷한 예라 생각됩니다 

carbon이란 framework은 정확히 proxy를 사용해서 이런 문제를 해결합니다만 

매요청시 속도가 느렸고 apache avalon의 경우는 dom처럼 메모리상에 tree를 

형성하지만 코딩시 key값을 hard코딩해야만 합니다.

편의상 vm이 하나라면 간단히 singleton을 사용하면 쉽게 해결되리라 봅니다.



제목 : Re: 하드코딩을 줄이고자 하는군요.
하드 코딩을 줄이고자 한다면 상수의 개념이 필요하겠지요.
효율성과 단순성에 대한 두가지 고민을 함께 해야 할것 같습니다.

아래의 요구조건이라면,

키들이 상수로 정의되어야 하고, 그것을 기준으로 각 한글이름을 반환하는 메소드
가 필요하다고 보여지는 경우

저는, properties를 이용하겠습니다.

public static final String A01="A01"; 
...

public String getName(String key)
{
   String name = "null";
   try{
     name = (String)getProperties().get(key);
   }catch(Exception e){}
   return name;
}

어차피 키의 추가는 상수의 추가를 의미하므로, 추가가 있다는 가정을 
하지 않는다면, 효율적인 방법이 아닐까 생각합니다.

menu.cfg 파일의 일부 내용이 아래처럼 될것으로 보입니다.
----------------------
A01 = 신규생성
A03 = 확정
...

제목 : 프로젝트 진행시 무지 고민하셨던 부분일 것입니다~~
1년 반전에 모 통신사의 업무시스템의 담당자로 참여한 적이 있었습니다
기존 A 업무의 모바일버젼으로 A업무를 조금 더 보완하며 대부분 
모바일 파트를 개발하는 프로젝트였습니다

A 업무가 기업의 기본 업무여서 연동되는 테이블들이 무지 많더군요
기초코드는 모두 DB에 구성되어 있었는데 기존의 시스템에서 
정보 추출시 필요한 모든 테이블들을 조인해서 가져오도록 되어있어
어떤 로직은 로직테이블 1 개에 기초코드 테이블을 10개를 
조인해서 가져오는 경우도 있었습니다 -.-;

문제는 모든 로직처리가 DB에 있다보니 무지 복잡해 진다는 것입니다
쿼리를 A4용지에 복사해 넣으면 쿼리만 12 라인이 입니다
물론 복잡한 로직인경우 이렇게 되는경우가 있긴하지만 굳이 이렇게 할 필요가 없다고 
생각했습니다
그래서 여러가지 테스트 후 고민끝에 새로 구성하는 부분은 
기존과 다르게 가기로 했습니다

사용하는 코드테이블만 15개 였는데 이를 더미빈이나 hashmap 으로 만들고
시스템 시작시 로딩하도록 하였으며 코드정보는 거의 수정되지 않기는 하지만
관련 데이블 수정시 RMI 로 저희 시스템의 코드처리 함수를 호출하도록 구성했습니다
DB가 oracle 이였기때문에 트리거로 RMI 함수를 호출하도록 했습니다
mssql 도 외부 프로그램을 호출할수 있으니 위처럼 하실수 있습니다

이렇게 구성하니 로직과 프리젠테이션의 구성이 무지 가벼워졌습니다

이 프로젝트하면서 느낀점은 
모든 로직을 DB 딴에서 처리하도록 구성하면 상상외로 복잡해진다는 것입니다
DB 에서의 처리와 구현부의 처리를 적절히 혼합해 사용하면 
쉽게 개발할 수 있다는 것이었습니다 
이 프로젝트 이후로 코드관련된 부분은 모두 이렇게 구성해 사용하고 있습니다
신고

'Program > JAVA' 카테고리의 다른 글

tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19
java :코드성데이터의 클래스생성  (0) 2008.05.19
java로 연관배열  (0) 2008.05.14

java로 연관배열

Program/JAVA 2008.05.14 17:55
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
...........
.........

        Map map = new HashMap();
        
        map.put("ID_a", new String[]{null, "A%3d", null} );
        map.put("ID_b", new String[]{null, "P%03d", null} );
        
        /* Key로 가져오기 */
        String[] arr = (String[])map.get("ID_a");
        System.out.println(arr[0] + " , " + arr[1] + " , " + arr[2]);
        
        /* 전체 */
        Iterator i = map.keySet().iterator();
        while( i.hasNext() ){
            String key = (String)i.next();
            String[] array = (String[])map.get(key);
            
            System.out.println("\nKEY : " + key);
            if( array==null ) continue;
            for( int idx = 0; idx<array.length; idx++ ){
                System.out.print(array[idx] + " ");
            }
        }
신고

'Program > JAVA' 카테고리의 다른 글

tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19
java :코드성데이터의 클래스생성  (0) 2008.05.19
java로 연관배열  (0) 2008.05.14


티스토리 툴바