달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

이거 원 만들때 마다 새로 만드니 당췌ㅡㅡ

 

Tomcat 4.1.30 + window XP SP2 단독 테스트

Tomcat 4.1.24 + Apache 2.0.43(맞나??) + linux  테스트.

 

IE 6.0 / Firefox 만 딱 두번씩 테스트 했네 ㅡㅡ

 


package com.javarush.util;

 

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

 

/**
 * @author Tornado
 */
public class DownloadUtil {
   
    private File file;
    private HttpServletRequest req;
    private HttpServletResponse res;
   
    public DownloadUtil(){   }
   
    public DownloadUtil(File file, HttpServletRequest req, HttpServletResponse res ){
       
        this.file = file;
        this.req = req;
        this.res = res;
       
    }
     
    public void sendFile() throws Exception{
       
        if(!(file.isFile() && file.exists())){
           
            throw new Exception("file.not.found");
           
        }
 
        if(!initResponse()){
           
            throw new Exception("download.failure");
           
        }
       
        FileInputStream fin = null;
       
        FileChannel inputChannel = null;
       
        WritableByteChannel outputChannel = null;
       
        try{
           
            fin = new FileInputStream(file);
           
            inputChannel = fin.getChannel();
           
            outputChannel = Channels.newChannel(res.getOutputStream());
           
            inputChannel.transferTo(0, fin.available(), outputChannel);
           
        }catch(Exception e){
           
            throw e;
           
        }finally{
           
            try{
               
                if(fin != null) fin.close();
            
             if(inputChannel.isOpen()) inputChannel.close();
            
             if(outputChannel.isOpen()) outputChannel.close();
            
            }catch(Exception e){
               
            }
           
        }
       
    }
       
    public boolean initResponse() throws Exception{
        
        if(res == null || req == null) return false;
       
        if(file == null)  return false;
       
        res.setContentType("appliction/octet-stream");
       
        res.setHeader("Accept-Ranges","bytes");
       
  if (req.getHeader("User-Agent").indexOf("MSIE 5.5") > -1) {
      // IE 6.0 Test Ok
   res.setHeader("Content-Disposition", "filename=" + java.net.URLEncoder.encode(file.getName(), "UTF-8") + ";");
   
  } else if(req.getHeader("User-Agent").indexOf("Mozilla/5.0") > -1){
      // firefox Test Ok
      if(req.getServerPort() == 8080){
         
          res.setHeader("Content-Disposition", "filename=" + new String(file.getName().getBytes("KSC5601"), "ISO-8859-1") + ";");
         
      }else{
         
          res.setHeader("Content-Disposition", "filename=" + new String(file.getName().getBytes(), "KSC5601" ) + ";");
         
      }
     
  } else {
     
   res.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(file.getName(), "UTF-8") + ";");
   
  }
  
  res.setContentLength((int)file.length());
       
        return true;
       
    }
   
}

 

 

사용법 :


<%@ page contentType="text/html; charset=euc-kr" import="java.io.*, java.net.*, com.javarush.util.*" %><%
        request.setCharacterEncoding("euc-kr");
        String fileName = request.getParameter("fileName");

        if(fileName != null){
                //fileName = URLDecoder.decode(fileName, "euc-kr");

                // get 으로 넘어오건.. POST 로 넘어오건.. .

                // DB 에서 파일이름을 읽어오건..

                // 한글로 된 파일 이름이 콘솔에 제대로 나와야

                // 다운로드가 제대로 됨

                System.out.println("fileName : " + fileName);


                File dir = new File(request.getContextPath() + "upload");
                File file = new File(dir, fileName);
                DownloadUtil downUtil = new DownloadUtil(file, request, response);

                downUtil.sendFile();
        }


%>

 


 

 

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

[펌] http RFC  (0) 2005.01.17
[펌]Single Sign On...  (0) 2005.01.17
헐.. 죽이넹  (0) 2004.12.21
얼... 좋은걸~  (0) 2004.12.17
Converting JDBC Result Sets to XML  (0) 2004.12.09
Posted by tornado
|

[link] 자바 검색 봇~

JAVA/JSE 2005. 1. 11. 15:44

http://www.nutch.org/docs/en/

 

lucene 도 봐야 허고.. 이거도 봐야하고..

간단한 게시판에 역인덱스 구조도 만들어 봐야 하고

할꺼 디지게 많은데.. 와우가 나를 부른다.. ㅡㅡ

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

[nio] Channels 클래스  (0) 2005.01.17
[펌] Sorting Algorithm  (0) 2005.01.15
[펌] [Collection Framework ] List, Set and Map  (0) 2004.12.29
소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
[허가없는 링크^^] 패턴  (0) 2004.10.25
Posted by tornado
|

Collection(List, Set) 과 Map.. 기억하자 기억하자 다짐하면서 번번히 차이점을 잊어버리곤 한다.

 

이번엔 절대로!! 잊지 않겠다는 신념으로  "Head First 자바" 부록을 참고해서 확실하게 정리해 보았다. -_-+

 

 

1. Collection

Collection 은 여러개의 객체를 하나의 유닛으로 다루기 위한 최상위 인터페이스이다.

 

객체 집합을 하나의 객체로 다루는 방법에 따라서 두가지로 나뉘는데, List 는 객체들이 들어온 순서대로 참조를 유지하기 위한 목적을 가지고 있고 Set 은 중복된 참조를 허용하지 않는 목적을 가진다.

 

 

2. List

Collection 인터페이스를 상속한 List는 객체들이 들어온 순서대로 참조를 관리한다.

 

들어온 순서가 중요하기 때문에 객체들에게 index(색인)을 부여하고 이를 통해서 각각의 객체에 접근한다.

 

List 에서 중요한 것은 객체들의 순서를 관리하는 것이다. 즉, List 는 index 로 순서를 추적하는데에 관심이 있을 뿐, 같은 객체의 참조가 여러번 들어오거나 null 참조가 들어오는 것은 조사하지 않는다.

 

만일 List에 참조가 여러개 존재하지 않아야 하는 상황이라면 List 보다는 Set 계열의 클래스를 이용하는 것이 좋다.

 

 

a. Vector

 

자바 1.0 부터 수많은 개발자들로부터 사랑받아오던 원년 멤버이지만 Collection 프레임워크가 등장하고 나서 List 인터페이스를 구현하면서 Collection 프레임워크로 편입됐다. Vector는 멀티 쓰레드 환경에서도 사용될 수 있도록 객체의 삽입, 삭제 시에 동기화를 보장하도록 되어있다.

 

하지만 Multi Thread 환경이 아니라면 ArrayList 보다 성능이 떨어지므로 Single Thread 에서 접근한다면 ArrayList 를 대신 사용하는 것이 효율적이다.

 

b. ArrayList

 

Collection 을 상속한 클래스들 중에서 add 메소드의 실행이 가장 빠르고 배열의 크기를 자유자재로 늘릴 수 있다. 하지만 Vector 처럼 동기화 과정은 제공하지 않는다. Collection 계열 클래스들은 (Vector를 제외하고) 여러개의 쓰레드가 동시에 접근하는 상황에 대한 대비책은 없기 때문에 주의할 필요가 있다. (이에 관한 추가 사항은 6.Collections 에서 다룬다.)

 

c. LinkedList

 

List 인터페이스의 기본적인 구현 외에도 추가적으로 몇개의 메소드를 넣어서 사용의 편리성을 도모했다. 이 몇개의 메소드란 addFirst(), addLast(), removeFirst(), removeLast() 등이다. LinkedList는 자체로서 사용되기 위해서라기 보다는 스택, 큐 등 사용자가 ADT를 구축할 때 내부에서 사용되기 위한 측면이 강하다.

 

따라서 단순히 객체에 대한 참조를 넣고 빼기 위해서라면 LinkedList 를 쓰기보다는 Vector나 ArrayList 를 사용하는 것이 바람직하다.(쓰더라도 문제될 건 없다.)

 

 

3. Set

List 가 항목의 순서를 관리하는데 비해 Set 는 중복된 항목을 방지하는데 관심이 있다. 이를 위해서 Set 에 의해서 관리되는 객체는 equals() 메소드를 구현해야 한다.

 

자바에서 == 는 단순히 객체의 주소에 근거해서 비교 결과를 반환하기 때문에 equals() 메소드에서 객체의 "내용"을 비교하는 과정을 적어넣아야 Set 에서 equals() 메소드를 통해서 이미 존재하는 항목인지 아닌지를 확인할 수 있다.

 

a. HashSet

 

HashSet 은 가장 빠른 접근을 보장한다. HashSet은 내부적으로 HashMap 을 이용한다. HashSet에 추가되는 항목은 HashMap의 키값으로 저장이 되기 때문에 HashSet이 하는 일이란 HashMap과 사용자 사이의 중계 역할만을 할 뿐이다. 

 

HashSet에서는 항목의 순서를 확인할 수 없다.새로운 객체가 HashSet 에 들어오게 되면 내부에서 객체의 참조 위치가 바뀔 수도 있는데, 이는 HashSet 내부에서 이용하는 HashMap의 특성때문이다.

 

b. LinkedHashSet

 

Set 에 순서를 부여하기 위해서 java 1.4에서 LinkedHashSet 클래스가 등장했다. 이 클래스는 내부에서 double-link 를 이용해서 linked list 를 구현함으로써 원소가 추가된 순서를 유지한다.  LinkedHashSet도 HashSet과 마찬가지로 내부에서 LinkedHashMap 인스턴스를 사용하고 있다.

 

TreeSet 은 Set의 항목들을 정렬된 순서대로 보관한다. 항목을 정렬하기 위해서 TreeSet이 하는 일이란 SortedMap 인스턴스에 작업을 위임하는 것 뿐이다. TreeSet 에 추가되는 항목은 SortedMap 인스턴스의 키값으로 등록이 된다. (키값의 정렬은 Map 인터페이스의 역할이다.)

 

위에서 살펴본대로 Set 계열의 클래스들은 자신의 작업을 Map 계열의 클래스들에게 전적으로 위임하고 있다. Set 에서 중복된 원소를 허용하지 않는 정책은 Map에서 중복된 키값이 존재해서는 안되는 정책이므로, Set에서 삽입되는 원소는 모두 Map 인스턴스에서 키값으로 추가가 된다.

 

이러한 이유 때문에 Set 계열의 클래스들과 Map 계열의 클래스들의 이름이 비슷하게 된 것이 아닌가 싶다.

 

 

 

4. Map

 

 

구조적으로 볼 때 Map 인터페이스는 Collection 인터페이스와 피한방울 섞이지 않은 남남이다. Map 인터페이스는 키와 값을 대응시키기 위해서 사용된다. 여기서 키(key)라 함은 하나의 Map 에 담기는 객체들을 유일하게 식별할 수 있는 객체를 의미하는데, 이는 하나의 Map 내에서 같은 값을 가지는 key 는 존재할 수 없음을 뜻한다.

 

주어진 키에 대응 하는 값을 빠르게 찾기 위한 탐색의 측면에서 Map 계열 클래스들의 의미가 있다고 하겠다.

 

*Collection 은 객체들을 넣고 빼는데 있어서 어떻게 이 객체들을 관리할 것인가를 다루고 있고 Map 은 키를 통해서 실제 객체에 접근한다.*

 

 

5. Collections

 

Collections 클래스는 Collection 인터페이스를 구현한 하위 클래스들에게 다양한 오퍼레이션을 제공할 목적으로 모든 메소드가 static 메소드이다. 따라서 모든 Collection 계열의 인스턴스에 대해서 필요에 따라 다양한 작업을 할 수 있다.

 

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html

 

a. 동기화 지원

 

위에서 언급한 ArrayList 뿐만이 아니라, Collection 을 구현하는 클래스들은 모두 ArrayList 처럼 동기화에 대한 대비책이 없다. 따라서 Vector와 Hashtable 을 제외한 모든 Collection 객체들이 Multi Thread 환경에서 사용되기 위해서는 별도의 기능을 갖춰야 하는데, 이를 위한 메소드가 Collections 클래스에 존재한다.

 

static CollectionsynchronizedCollection(Collection c)
          Returns a synchronized (thread-safe) collection backed by the specified collection.
static ListsynchronizedList(List list)
          Returns a synchronized (thread-safe) list backed by the specified list.
static MapsynchronizedMap(Map m)
          Returns a synchronized (thread-safe) map backed by the specified map.
static SetsynchronizedSet(Set s)
          Returns a synchronized (thread-safe) set backed by the specified set.
static SortedMapsynchronizedSortedMap(SortedMap m)
          Returns a synchronized (thread-safe) sorted map backed by the specified sorted map.
static SortedSetsynchronizedSortedSet(SortedSet s)
          Returns a synchronized (thread-safe) sorted set backed by the specified sorted set.

 

다음과 모든 Collection 계열의 객체에 대해서 synchronized...(..) 메소드로 Multi Thread 환경에서 이용가능하도록 전환할 수 있다. 

 

List list = Collections.synchronizedList(new ArrayList(...));

List list = Collections.synchronizedList(new LinkedList(...));

 

SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

Set s = Collections.synchronizedSet(new HashSet(...));

Set s = Collections.synchronizedSet(new LinkedHashSet(...));

 

 

Map m = Collections.synchronizedMap(new HashMap(...));

Map m = Collections.synchronizedMap(new TreeMap(...));
Map m = Collections.synchronizedMap(new LinkedHashMap(...));

 

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

[펌] Sorting Algorithm  (0) 2005.01.15
[link] 자바 검색 봇~  (0) 2005.01.11
소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌] JAVA application 성능향상..  (0) 2004.10.07
Posted by tornado
|

헐.. 죽이넹

JAVA/JSP_Servlet 2004. 12. 21. 15:14

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

[펌]Single Sign On...  (0) 2005.01.17
JSP 다운로드시 헤더 ㅡㅡ  (0) 2005.01.13
얼... 좋은걸~  (0) 2004.12.17
Converting JDBC Result Sets to XML  (0) 2004.12.09
[펌] requestmon - 톰캣과의 사투중 발견한 유용한 정보..  (0) 2004.11.10
Posted by tornado
|

얼... 좋은걸~

JAVA/JSP_Servlet 2004. 12. 17. 11:00
Posted by tornado
|
Posted by tornado
|
Linux(RedHat), FreeBSD, Windows에 Java Path 설정 조회 35 | 추천 | 스크랩
IT 상식 | 2004-11-16 00:08:04  
PATH 지정의 목적 : 현재 디랙토리가 어디이던 JDK의 "bin"폴더에 있는java.exe, javac.exe등을 실행시키기 위한 경로를 지정
 
 
 
Linux
=====
 
 .bash_profile 또는 .bashrc에서
export PATH=$JAVA_HOME/bin을 지정
 
#설치 위치 : /usr/local/j2sdk1.4.2_02/ (/usr/local/jdk 로 심볼릭 링크)
#export JAVA_HOME=/usr/local/jdk
#export CLASSPATH=$JAVA_HOME/classes12.zip:/root/j2sdk1.4.2_02/lib
#export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/lib
 
 
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
 . ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
BASH_ENV=$HOME/.bashrc
USERNAME="root"
export USERNAME BASH_ENV PATH
export PATH=$PATH:$usr/java/j2re1.4.2_06/bin/
 
 
 

 

 
FreeBSD
========
 
/etc/profile 또는 $HOME/.bash_profile $HOME/.bashrc, .cshrc
(env 명령으로 쉘을 확인한 후 어떤 쉘을 쓰는지 확인)
 
# tcsh 쉘의 설정(.cshrc)
----------------------
# alias
alias l  ls -alF
alias ns netstat -nr
alias pp ps -aux
 
# path
set path = (/sbin /bin /user/sbin /usr/bin /usr/local/sbin /usr/local/bin /usr/X11R6/bin)
set path = ($path $HOME/bin)
 
# 환경변수
setenv LANG ko_KR.EUC
 
# 쉘 프롬프트
set prompt = "$user %c2> "
set prompt = "$user $cwd> "
set prompt = "`hostname -s`> "
 
# jdk
setenv JDK /usr/local/jdk1.1.8
set path = ($path $JDK/bin)
setenv CLASSPATH $JDK/lib/classes.zip:.
setenv LD_LIBRARY_PATH $JDK/lib/i386
 
# stty
stty erase ^H

 
# Bourne Shell의 설정(.profile)
-----------------------------
# alias
alias l='ls -alF'
 
# 로케일
LANG="ko_KR.EUC"; export LANG
 
#path
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$HOME/bin; export PATH
 

 
Windows
========

도스창을 열고 set path=...... 명령을 넣으면 그 도스창을 띄운 프로세스에만 적용
 
autoexec.bat에 아래 내용 추가후 Rebooting
예) set path=%path%;c:JDK설치위치bin
설명 ) path라는 변수를 셋팅하는데 "기존의 path 변수에 있는 설정값"을 가져오고(%path%) , 추가로(;) "c:j2sebin"라는 폴더를
패스를 잡아서 어디서든지 그 안에 있는 명령어들을 쓸수있게 한다
 
환경변수를 아래와 같이 수정
예) '시작' > '설정' > '제어판' > '시스템' 으로 가서... '고급'tab > '환경변수' 버튼 클릭
     > '시스템 변수'에 "path" 더블 클릭 >  ;c:JDK설치위치bin 내용 추가
Posted by tornado
|

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

[link] 자바 검색 봇~  (0) 2005.01.11
[펌] [Collection Framework ] List, Set and Map  (0) 2004.12.29
[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌] JAVA application 성능향상..  (0) 2004.10.07
[펌 http://raytrust.pe.kr/] signed applet  (0) 2004.09.06
Posted by tornado
|

톰캣과 사투를 벌이던중 자바서비스넷에서 발견한 유용한 정보가 있어서 공유해 드리겠습니다.

requestmon은 자바서비스넷의 이원영씨가 제작한 것으로 서블렛엔진이나 WAS에서 서비스중인

servlet 이나 JSP의 목록을 실시간으로 보여주고, 필요한 경우, 응답이 느린 서비스들만 대상으로 하여 특별한 로그파일에 기록해 주는 기능을 가지고 있습니다.

장애진단및 디버깅을 하기 위해 각 서비스들을 관찰 하는데 유용하게 사용하고 있습니다.

다음과 같은 클래스를 만든후 컴파일해서

/WEB-INF/classes/filters 에 둔후..


package filters;

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;

public class RequestMonFilter implements Filter {
    protected FilterConfig filterConfig = null;

    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
throws IOException, ServletException {

        org.jdf.requestmon.ServiceTrace trace =
             org.jdf.requestmon.ServiceTrace.getInstance();
        trace.startTrace((HttpServletRequest)request);
        try {
        chain.doFilter(request, response);
        }finally {
         trace.endTrace((HttpServletRequest)request);
        }
    }

    public void destroy() {
        this.filterConfig = null;
    }
   
    public void init(FilterConfig filterConfig) throws ServletException { }
}

requestmon3.5.2-4.jar를 /WEB-INF/lib 폴더아래에 둡니다.

물론 jar파일은 filter 컴파일에도 필요합니다.

requestmon.jsp는 다른 JSP두는 적당한 곳에 두시구요.

/WEB-INF/web.xml을 열고 다음을 추가합니다.

    <filter>
        <filter-name>Request Monitor Filter</filter-name>
        <filter-class>filters.RequestMonFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>Request Monitor Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

이제 톰캣을 구동시키고 /requestmon.jsp 를 호출해보면 결과를 볼 수 있습니다.

실행속도가 3초이상 걸리는 서비스인 경우에는

%tomcat_home%/bin 디렉토리에 trace.log에 로그가 남겨집니다.

일단 제가 톰캣에 적용시켜서 잘 돌아가는걸 확인했구요..

다른 서블릿엔진에서도 문제없이 돌아가리라고 생각합니다..

 

출처 : 자바서비스넷

Posted by tornado
|

Thomas Risberg
July, 2003


This is a step-by-step account of how to develop a web application from scratch using the Spring Framework. It is divided into a number of parts. You can read them in sequence or skip one if you are already familiar with the concepts covered in it.


Part 1 - Basic Application and Environment Setup


Part 2 – Developing and Configuring the Application


Part 3 – Adding Unit Tests and a Form to the Application


Part 4 – Implementing Database Persistence





Copyright © 2003, Thomas Risberg

Posted by tornado
|
Posted by tornado
|

URL 남겨놓고 시간날때 좀 자세히 봐둬야 것다...

 

http://kr.sun.com/developers/tech_docs/wireless_web06/wireless02.html

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

소스포지.. 디컴파일해두 소스 안보여주는  (0) 2004.11.23
[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌 http://raytrust.pe.kr/] signed applet  (0) 2004.09.06
[펌] javadoc 유틸리티  (0) 2004.09.01
[nio] 기초 정리 잘된곳  (0) 2004.08.09
Posted by tornado
|

나만 몰랐나?? 아래처럼 하니까 되네여 ㅋ

 

struts 제공 태그는 사용안함...

 

 

<input type="text" name="work" onclick="goCalendar('work','0')" style="cursor:hand" />

 

위와 같은 태그가 한개 있을 경우 Struts FormBean 에서는 아래와 같이 코딩하면 받을 수 있다.

 

private String work;

 

public void setWork(String work){ .... }

public String getWork(){  return work;  }

 

그런데 work 라는 TextField 가 여러개 있을 경우에는???

 

<input type="text" name="work[]" onclick="getDate('work','0')" style="cursor:hand" />

<input type="text" name="work[]" onclick="getDate('work','1')" style="cursor:hand" />

<input type="text" name="work[]" onclick="getDate('work','2')" style="cursor:hand" />

<input type="text" name="work[]" onclick="getDate('work','3')" style="cursor:hand" />

 

위와 같은 형식으로 사용해도 된다.

 

또는...

 

<input type="text" name="work" onclick="getDate('work','0')" style="cursor:hand" />

<input type="text" name="work" onclick="getDate('work','1')" style="cursor:hand" />

<input type="text" name="work" onclick="getDate('work','2')" style="cursor:hand" />

<input type="text" name="work" onclick="getDate('work','3')" style="cursor:hand" />

 

위에처럼 배열표시를 빼도.. 알아 듣는다..

 

배열로 쓸때의 Struts FormBean 은 아래처럼 배열처리해줘야 하겠쥐~~

 

private String[] work = new String[10];

 

public void setWork(String[] work){ this.work = work; }

public String[] getWork(){   return this.work; }

 

일케 하믄 되더만 ㅡㅡ 허무 ......

 

 

 

Posted by tornado
|

Best practices to improve performance in JDBC

This topic illustrates the best practices to improve performance in JDBC with the following sections:

 

Feed back

We appreciate and welcome your comments on this section. Email comments@precisejava.com

<@NHN@LINEBREAKER@NHN@>

Overview of JDBC

JDBC defines how a Java program can communicate with a database. This section focuses  mainly on JDBC 2.0 API.  JDBC API provides two packages they are java.sql and javax.sql . By using JDBC API, you can connect virtually any database, send SQL queries to the database and process the results.

JDBC architecture defines different layers to work with any database and java, they are JDBC API interfaces and classes which are at top most  layer( to work with java ), a driver which is at middle layer (implements the JDBC API interfaces that maps java to database specific language) and a database which is at the bottom (to store physical data). The following figure illustrates the JDBC architecture.

JDBC API provides interfaces and classes to work with databases. Connection interface encapsulates database connection functionality, Statement interface encapsulates SQL query representation and execution functionality and ResultSet interface encapsulates retrieving data which comes from execution of SQL query using Statement.

The following are the basic steps to write a JDBC program

        1. Import java.sql and javax.sql packages

        2. Load JDBC driver

        3. Establish connection to the database using Connection interface

        4. Create a Statement by passing SQL query

        5. Execute the Statement

        6. Retrieve results by using ResultSet interface

        7. Close Statement and Connection

We will look at these areas one by one, what type of driver you need to load, how to use Connection interface in the best manner, how to use different Statement interfaces, how to process results using ResultSet and finally how to optimize SQL queries to improve JDBC performance.

Note1: Your JDBC driver should be fully compatible with JDBC 2.0 features in order to use some of the suggestions mentioned in this section.

Note2: This Section assumes that reader has some basic knowledge of JDBC.

 

Choosing right Driver

Here we will walk through initially about the types of drivers, availability of drivers, use of drivers in different situations, and then we will discuss about which driver suits your application best.

Driver is the key player in a JDBC application, it acts as a mediator between Java application and database. It implements JDBC API interfaces for a database, for example Oracle driver for oracle database, Sybase driver for Sybase database. It maps Java language to database specific language including SQL.

JDBC defines four types of drivers to work with. Depending on your requirement you can choose one among  them.

Here is a brief description of each type of driver :

 

Type of driverTierDriver mechanismDescription
1TwoJDBC-ODBC This driver converts JDBC calls to ODBC calls through JDBC-ODBC Bridge driver which in turn converts to database calls. Client requires ODBC libraries.
2TwoNative API - Partly - Java driver This driver converts JDBC calls to database specific native calls. Client requires database specific libraries.
3ThreeJDBC - Net -All Java driverThis driver passes calls to proxy server through network protocol which in turn converts to database calls and passes through database specific protocol. Client doesn't require any driver.
4TwoNative protocol - All - Java driverThis driver directly calls database. Client doesn't require any driver.

 

Obviously the choice of choosing a driver depends on availability of driver and requirement. Generally all the databases support their own drivers or from third party vendors. If you don't have driver for your database, JDBC-ODBC driver is the only choice because all most all the vendors support ODBC. If you have tiered requirement ( two tier or three tier) for your application, then you can filter down your  choices, for example if your application is three tiered, then you can go for Type three driver between client and proxy server shown below. If you want to connect to database from java applet, then you have to use Type four driver because it is only the driver which supports that feature. This figure shows the overall picture of drivers from tiered perspective.

 

 

This figure illustrates the drivers that can be used for two tiered and three tiered applications. For both two and three tiered applications, you can filter down easily to Type three driver but you can use Type one, two and four drivers for both tiered applications. To be more precise, for java applications( non-applet) you can use Type one, two or four driver. Here is exactly where you may make a mistake by  choosing a driver without taking performance into consideration. Let us look at that perspective in the following section.

Type 3 & 4 drivers are faster than other drivers because Type 3 gives facility for optimization techniques provided by application server such as connection pooling, caching, load balancing etc and Type 4 driver need not translate database calls to ODBC or native connectivity interface. Type 1 drivers are slow because they have to convert JDBC calls to ODBC through JDBC-ODBC Bridge driver initially and then ODBC Driver converts them into database specific calls. Type 2 drivers give average performance when compared to Type 3 & 4 drivers because the database calls have to be converted into database specific calls. Type 2 drivers give better performance than Type 1 drivers.

Finally, to improve performance

1. Use Type 4 driver for applet to database communication.

2. Use Type 2 driver for two tiered applications for communication between java client and the database that gives better performance when compared to Type1 driver

3. Use Type 1 driver if your database doesn't support a driver. This is rare situation because almost all major databases support drivers or you will get them from third party vendors.

4.Use Type 3 driver to communicate between client and proxy server ( weblogic, websphere etc) for three tiered applications that gives better performance when compared to Type 1 & 2 drivers.

 

Optimization with Connection

java.sql package in JDBC provides Connection interface that encapsulates database connection functionality. Using Connection interface, you can fine tune the following operations :

        1. Set optimal row pre-fetch value

        2. Use Connection pool

        3. Control transaction

        4. Choose optimal isolation level

        5. Close Connection when finished

Each of these operations effects the performance. We will walk through each operation one by one.

1. Set optimal row pre-fetch value

We have different approaches to establish a connection with the database, the first type of approach is :

        1. DriverManager.getConnection(String url)

        2. DriverManager.getConnection(String url, Properties props)

        3. DriverManager.getConnection(String url, String user, String password)

        4. Driver.connect(String url, Properties props)

When you use this approach, you can pass database specific information to the database by passing properties using Properties object to improve performance. For example, when you use oracle database you can pass default number of rows that must be pre-fetched from the database server and the default batch value that triggers an execution request. Oracle has default value as 10 for both properties. By increasing the value of these properties, you can reduce the number of database calls which in turn improves performance. The following code snippet illustrates this approach.

        java.util.Properties props = new java.util.Properties();

        props.put("user","scott");

        props.put("password","tiger");

        props.put("defaultRowPrefetch","30");

        props.put("defaultBatchValue","5");

        Connection con = DriverManger.getConnection("jdbc:oracle:thin:@hoststring", props);

You need to figure out appropriate values for above properties for better performance depending on application's requirement. Suppose, you want to set these properties for search facility, you can increase defaultRowPrefetch so that you can increase performance significantly.

The second type of approach is to get connection from DataSource.

You can get the connection using javax.sql.DataSource interface. The advantage of getting connection from this approach is that the DataSource works with JNDI. The implementation of DataSource is done by vendor, for example you can find this feature in weblogic, websphere etc. The vendor simply creates DataSource implementation class and binds it to the JNDI tree. The following code shows how a vendor creates implementation class and binds it to JNDI tree.

        DataSourceImpl dsi = new DataSourceImpl();

        dsi.setServerName("oracle8i");

        dsi.setDatabaseName("Demo");

        Context ctx = new InitialContext();

        ctx.bind("jdbc/demoDB", dsi);

This code registers the DataSourceImpl object to the JNDI tree, then the programmer can get the DataSource reference from JNDI tree without knowledge of the underlying technology.

        Context ctx = new InitialContext();

        DataSource ds = (DataSource)ctx.lookup("jdbc/demoDB");

        Connection con = ds.getConnection();

By using this approach we can improve performance. Nearly all major vendor application servers like weblogic, webshpere implement the DataSource by taking connection from connection pool rather than a single connection every time. The application server creates connection pool by default. We will discuss the advantage of connection pool to improve performance in the next section.

2. Use Connection pool

Creating a connection to the database server is expensive. It is even more expensive if the server is located on another machine. Connection pool contains a number of open database connections with minimum and maximum connections, that means the connection pool has open connections between minimum and maximum number that you specify. The pool expands and shrinks between minimum and maximum size depending on incremental capacity. You need to give minimum, maximum and incremental sizes as properties to the pool in order to maintain that functionality. You get the connection from the pool rather directly .For example, if you give properties like min, max and incremental sizes as 3, 10 and 1 then pool is created with size 3 initially and if it reaches it's capacity 3 and if a client requests a connection concurrently, it increments its capacity by 1 till it reaches 10 and later on it puts all its clients in a queue. 

There are a few choices when using connection pool.

1. You can depend on application server if it supports this feature, generally all the application servers support connection pools. Application server creates the connection pool on behalf of you when it starts. You need to give properties like min, max and incremental sizes to the application server.

2. You  can use JDBC 2.0 interfaces, ConnectionPoolDataSource and PooledConnection if your driver implements these interfaces

3. Or  you can create your own connection pool if you are not using any application server or JDBC 2.0  compatible driver.

By using any of these options, you can increase performance significantly. You need to take care of properties like min, max and incremental sizes. The maximum number of connections to be given depends on your application's  requirement that means how many concurrent clients can access  your database and also it depends up on your database's capability to provide maximum number of connections.

3. Control transaction

In general, transaction represents one unit of work or bunch of code in the program that executes in it's entirety or none at all. To be precise, it is all or no work. In JDBC, transaction is a set of one or more Statements that execute as a single unit.

java.sql.Connection interface provides some methods to control transaction they are

        public interface Connection {

            boolean getAutoCommit();

            void        setAutoCommit(boolean autocommit);

            void        commit();

            void        rollback();

        }

JDBC's default mechanism for transactions:

By default in JDBC transaction starts and commits after each statement's  execution on a connection. That is the AutoCommit mode is true. Programmer need not write a commit() method explicitly after each statement.

Obviously this default mechanism gives good facility for programmers if they want to execute a single statement. But it gives poor performance when multiple statements on a connection are to be executed because commit is issued after each statement by default, that in turn reduces performance by issuing unnecessary commits. The remedy is to flip it back to AutoCommit mode as false and issue commit() method after a set of statements execute, this is called as batch transaction. Use rollback() in catch block to rollback the transaction whenever an exception occurs in your program. The following code illustrates the batch transaction approach.

try{

    connection.setAutoCommit(false);

    PreparedStatement ps = connection.preareStatement( "UPDATE employee SET Address=? WHERE name=?");

    ps.setString(1,"Austin");

    ps.setString(2,"RR");

    ps.executeUpdate();

    PreparedStatement ps1 = connection.prepareStatement( "UPDATE account SET salary=? WHERE name=?");

    ps1.setDouble(1, 5000.00);

    ps1.setString(2,"RR");

    ps1.executeUpdate();

    connection.commit();

    connection.setAutoCommit(true);

    }catch(SQLException e){ connection.rollback();}

    finally{

             if(ps != null){ ps.close();}

             if(ps1 != null){ps1.close();}

   if(connection != null){connection.close();}

    }

This batch transaction gives good performance by reducing commit calls after each statement's execution.

4. Choose optimal isolation level

Isolation level represent how a database maintains data integrity against the problems like dirty reads, phantom reads and non-repeatable reads which can occur due to concurrent transactions. java.sql.Connection interface provides  methods and constants to avoid the above mentioned problems by setting different isolation levels.

public interface Connection {

        public static final int  TRANSACTION_NONE                             = 0

        public static final int  TRANSACTION_READ_COMMITTED         = 2

        public static final int  TRANSACTION_READ_UNCOMMITTED     = 1

        public static final int  TRANSACTION_REPEATABLE_READ       = 4

        public static final int  TRANSACTION_SERIALIZABLE                 = 8

        int          getTransactionIsolation();

        void        setTransactionIsolation(int isolationlevelconstant);

}

You can get the existing isolation level with getTransactionIsolation() method and set the isolation level with setTransactionIsolation(int isolationlevelconstant) by passing above constants to this method.

The following table describes isolation level against the problem that it prevents :

 

Transaction Level                            Permitted Phenomena Performance impact
     Dirty reads   Non  Repeatable readsPhantom reads 
TRANSACTION_NONE N/AN/AN/AFASTEST
TRANSACTION_READ_UNCOMMITEDYESYESYESFASTEST
TRANSACTION_READ_COMMITEDNO YESYESFAST
TRANSACTION_REPEATABLE_READNONOYESMEDIUM
TRANSACTION_SERIALIZABLENONO NOSLOW

YES means that the Isolation level does not prevent the problem

NO means that the Isolation level prevents the problem

By setting isolation levels, you are having an impact on the performance as mentioned in the above table. Database use read and write locks to control above isolation levels. Let us have a look at each of these problems and then look at the impact on the performance.

Dirty read problem :

The following figure illustrates Dirty read problem  :

 

 

Step 1:     Database row has PRODUCT = A001 and PRICE = 10

Step 2:    Connection1 starts  Transaction1 (T1) .

Step 3:    Connection2 starts  Transaction2 (T2) .

Step 4:    T1 updates PRICE =20 for PRODUCT = A001

Step 5:    Database has now PRICE = 20 for PRODUCT = A001

Step 6:    T2 reads PRICE = 20 for PRODUCT = A001

Step 7:    T2 commits transaction

Step 8:    T1 rollbacks the transaction because of some problem

The problem is that T2 gets wrong PRICE=20 for PRODUCT = A001 instead of 10 because of uncommitted read. Obviously it is very dangerous in critical transactions if you read inconsistent data. If you  are sure about not accessing data concurrently  then you can allow this problem by setting TRANSACTION_READ_UNCOMMITED or TRANSACTION_NONE that in turn improves performance otherwise you have to use TRANSACTION_READ_COMMITED to avoid this problem.

 

Unrepeatable read problem :

The following figure illustrates Unrepeatable read problem  :

 

Step 1:     Database row has PRODUCT = A001 and PRICE = 10

Step 2:    Connection1 starts  Transaction1 (T1) .

Step 3:    Connection2 starts  Transaction2 (T2) .

Step 4:    T1 reads PRICE =10 for PRODUCT = A001

Step 5:    T2 updates PRICE = 20 for PRODUCT = A001

Step 6:    T2 commits transaction

Step 7:    Database row has PRODUCT = A001 and PRICE = 20

Step 8:    T1 reads PRICE = 20 for PRODUCT = A001

Step 9:    T1 commits transaction

Here the problem is that Transaction1 reads 10 first time and reads 20 second time but it is supposed to be 10 always whenever it reads a record in that transaction. You can control this problem by setting isolation level as TRANSACTION_REPEATABLE_READ.

Phantom read problem :

The following figure illustrates Phantom read problem  :

Step 1:     Database has a row PRODUCT = A001 and COMPANY_ID = 10

Step 2:    Connection1 starts  Transaction1 (T1) .

Step 3:    Connection2 starts  Transaction2 (T2) .

Step 4:    T1 selects a row with a condition SELECT PRODUCT WHERE COMPANY_ID = 10

Step 5:    T2 inserts a row with a condition INSERT PRODUCT=A002  WHERE

                   COMPANY_ID= 10

Step 6:    T2 commits transaction

Step 7:    Database has 2 rows with that condition

Step 8:    T1 select again with a condition SELECT PRODUCT WHERE COMPANY_ID=10            

                and gets 2 rows instead of 1 row

Step 9:    T1 commits transaction

Here the problem is that T1 gets 2 rows instead of 1 row up on selecting the same condition second time. You can control this problem by setting isolation level as TRANSACTION_SERIALIZABLE

Choosing a right isolation level for your program:

Choosing a right isolation level for your program depends upon your application's requirement. In single application itself the requirement generally changes, suppose if you write a program for searching a product catalog from your database then you can easily choose TRANSACTION_READ_UNCOMMITED because you need not worry about the problems that are mentioned above, some other program can insert records at the same time, you don't have to bother much about that insertion. Obviously this improves performance significantly.

If you write a critical program like bank or stocks analysis program where you want to control all of the above mentioned problems, you can choose TRANSACTION_SERIALIZABLE for maximum safety. Here it is the tradeoff between the safety and performance. Ultimately we need safety here.

If you don't have to deal with concurrent transactions your application, then the best choice is TRANSACTION_NONE to improve performance.

Other two isolation levels need good understanding of your requirement. If your application needs only committed records, then TRANSACTION_READ_COMMITED isolation is the good choice. If your application needs to read a row exclusively till you  finish your work, then TRANSACTION_REPEATABLE_READ is the best choice.

Note: Be aware of your database server's support for these isolation levels. Database servers may not support all of these isolation levels. Oracle server supports only two isolation levels, TRANSACTION_READ_COMMITED and TRANSACTION_SERIALIZABLE isolation level, default isolation level is TRANSACTION_READ_COMMITED.

5. Close Connection when finished

Closing connection explicitly allows garbage collector to recollect memory as early as possible. Remember that when you use the connection pool, closing connection means that it returns back to the connection pool rather than closing direct connection to the database.

 

Optimization with Statement

Statement interface represents SQL query and execution and they provide number of methods and constants to work with queries. They also provide some methods to fine tune performance. Programmer may overlook these fine tuning methods that result in poor performance. The following are the tips to improve performance by using statement interfaces

        1. Choose the right Statement interface

        2. Do batch update

        3. Do batch retrieval using Statement

        2. Close Statement when finished

1. Choose right Statement interface

There are three types of Statement interfaces in JDBC to represent the SQL query and execute that query, they are Statement, PreparedStatement and CallableStatement.

Statement is used for static SQL statement with no input and output parameters, PreparedStatement is used for dynamic SQL statement with input parameters and CallableStatement is used for dynamic SQL satement with both input and output parameters, but PreparedStatement and CallableStatement can be used for static SQL statements as well. CallableStatement is mainly meant for stored procedures.

PreparedStatement gives better performance when compared to Statement because it is pre-parsed and pre-compiled by the database once for the first time and then onwards it reuses the parsed and compiled statement. Because of this feature, it significantly improves performance when a statement executes repeatedly, It reduces the overload incurred by parsing and compiling.

CallableStatement gives better performance when compared to PreparedStatement and Statement when there is a requirement for single request to process multiple complex statements. It parses and stores the stored procedures in the database and does all the work at database itself that in turn improves performance. But we loose java portability and we have to depend up on database specific stored procedures.

2. Do batch update

You can send multiple queries to the database at a time using batch update feature of statement objects this reduces the number of JDBC calls and improves performance. Here is an example of how you can do batch update,

statement.addBatch( "sql query1");

statement.addBatch(" sql query2");

statement.addBatch(" sql query3");

statement.executeBatch();

All three types of statements have these methods to do batch update.

3. Do batch retrieval using Statement

You can get the default number of rows that is provided by the driver. You can improve performance by increasing number of rows to be fetched at a time from database using setFetchSize() method of the statement object.

Initially find the default size by using

Statement.getFetchSize();   and then set the size as per your requirement

Statement.setFetchSize(30);

Here it retrieves 30 rows at a time for all result sets of this statement.

4. Close Statement when finished

Close statement object as soon as you finish working with that, it explicitly gives a chance to garbage collector to recollect memory as early as possible which in turn effects performance.

Statement.close();

 

Optimization with ResultSet

ResultSet interface represents data that contains the results of executing an SQL Query and it provides a number of methods and constants to work with that data. It also provides methods to fine tune retrieval of data to improve performance. The following are the fine tuning tips to improve performance by using ResultSet interface.

        1. Do batch retrieval using ResultSet

        2. Set up proper direction for processing the rows

        3. Use proper get methods

        4. Close ResultSet when finished

1. Do batch retrieval using ResultSet

ResultSet interface also provides batch retrieval facility like Statement as mentioned above. It overrides the Statement behaviour.

Initially find the default size by using

ResultSet.getFetchSize(); and then set the size as per requirement

ResultSet.setFetchSize(50);

This feature significantly improves performance when you are dealing with retrieval of large number of rows like search functionality.

2. Setup proper direction of processing rows

ResultSet has the capability of setting the direction in which you want to process the results, it has three constants for this purpose, they are

FETCH_FORWARD, FETCH_REVERSE, FETCH_UNKNOWN

Initially find the direction by using

ResultSet.getFetchDirection(); and then set the direction accordingly

ResultSet.setFetchDirection(FETCH_REVERSE);

3. Use proper getxxx() methods

ResultSet interface provides lot of getxxx() methods to get and convert database data types to java data types and is flexibile in converting non feasible data types. For example,

getString(String columnName) returns java String object.

columnName is recommended to be a VARCHAR OR CHAR type of database but it can also be a NUMERIC, DATE etc.

If you give non recommended parameters, it needs to cast it to proper java data type that is  expensive. For example consider that  you select  a product's id from huge database which returns millions of records from search functionality, it needs to convert all these records that is very expensive.

So always use proper getxxx() methods according to JDBC recommendations.

4. Close ResultSet when finished

Close ResultSet object as soon as you finish working with ResultSet object even though Statement object closes the ResultSet object implicitly when it closes, closing ResultSet explicitly gives chance to garbage collector to recollect memory as early as possible because ResultSet object may occupy lot of memory depending on query.

ResultSet.close();

 

Optimization with SQL Query

This is one of the area where programmers generally make a mistake

If you give a query like

Statement stmt = connection.createStatement();

ResultSet rs = stmt.executeQuery("select * from employee where name=RR");

The returned result set contains all the columns data. you may not need all the column data and want only salary for RR.

The better query is "select salary from employee where name=RR"

It returns the required data  and reduces unnecessary data retrieval.

 

Cache the read-only and read-mostly data

Every database schema generally has read-only and read-mostly tables. These tables are called as lookup tables. Read-only tables contain static data that never changes in its life time. Read-mostly tables contain semi dynamic data that changes often. There will not be any sort of writing operations in these tables.

If an application reads data from these tables for every client request, then it is redundant, unnecessary and expensive. The solution for this problem is to cache the read-only table data by reading the data from that table once and caching the read-mostly table data by reading and refreshing with time limit. This solution improves performance significantly. See the following link for source code of such caching mechanism.

http://www.javaworld.com/javaworld/jw-07-2001/jw-0720-cache.html

You can tweak this code as per application requirement. For read-only data, you need not refresh data in its life time. For read-mostly data, you need to refresh the data with time limit. It is better to set this refreshing time limit in properties file so that it can be changed at any time.

 

Fetch small amount of data iteratively instead of fetching whole data at once

Applications generally require to retrieve huge data from the database using JDBC in operations  like searching data. If the client request for a search, the application might return the whole result set at once. This process takes lot of time and has an impact on performance. The solution for the problem is

1. Cache the search data at the server-side and return the data iteratively to the client. For example, the search returns 1000 records, return data to the client in 10 iterations where each iteration has 100 records.

2. Use Stored procedures to return data iteratively. This does not use server-side caching rather server-side application uses Stored procedures to return small amount of data iteratively.

Out of these solutions the second solution gives better performance because it need not keep the data in the cache (in-memory). The first procedure is useful when the total amount of data to be returned is not huge.

 

Key Points

  1. Use Type two driver for two tiered applications to communicate from java client to database that gives better performance than Type1 driver.
  2. Use Type four driver for applet to database communication that is two tiered applications and three tiered applications when compared to other drivers.
  3. Use Type one driver if you don't have a driver for your database. This is a rare situation because all major databases support drivers or you will get a driver from third party vendors.
  4. Use Type three driver to communicate between client and proxy server ( weblogic, websphere etc) for three tiered applications that gives better performance when compared to Type 1 &2 drivers.
  5. Pass database specific properties like defaultPrefetch if your database supports any of them.
  6. Get database connection from connection pool rather than getting it directly
  7. Use batch transactions.
  8. Choose right isolation level as per your requirement. TRANSACTION_READ_UNCOMMITED gives best performance for concurrent transaction based applications. TRANSACTION_NONE gives best performance for non-concurrent transaction based applications.
  9. Your database server may not support all isolation levels, be aware of your database server features.
  10. Use PreparedStatement when you execute the same statement more than once.
  11. Use CallableStatement when you want result from multiple and complex statements for a single request.
  12. Use batch update facility available in Statements.
  13. Use batch retrieval facility available in Statements or ResultSet.
  14. Set up proper direction for processing rows.
  15. Use proper getXXX() methods.
  16. Close ResultSet, Statement and Connection whenever you finish your work with them.
  17. Write precise SQL queries.
  18. Cache read-only and read-mostly tables data.
  19. Fetch small amount of data iteratively rather than whole data at once when retrieving large amount of data like searching database etc.

Posted by tornado
|

http://jakarta.apache.org/commons/dbcp/apidocs/org/apache/commons/dbcp/package-summary.html#package_description

 

여기 내용보고 열쉬미 멜링 리스트 부터.. cvs... google 을 뒤진 결과.... 아주 간단하게

풀을 사용하는 법을 알아냄...

 

커먼스 관련 lib 는 최신으로 도배함 ㅡㅡ

 

1. jocl 만들기...

  파일 이름은 intranet.jocl 로 했음.. 저장은 classes 에 함...

  각 설명은 해당 내용 옆의 주석을 참고하면 됨

 

<object class="org.apache.commons.dbcp.PoolableConnectionFactory" xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl">

  <object class="org.apache.commons.dbcp.DriverManagerConnectionFactory">
    <string value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=euc-kr" /> <!-- jdbcurl -->
    <string value="root" />  <!-- user -->
    <string value="123456" />  <!-- password -->
  </object>
 
  <object class="org.apache.commons.pool.impl.GenericObjectPool">
    <object class="org.apache.commons.pool.PoolableObjectFactory" null="true" />
    <int value="80" />  <!-- max active -->
    <byte value="1" />  <!-- when exhausted action, 0 = fail, 1 = block, 2 = grow -->
    <long value="2000" />  <!-- max wait -->
    <int value="10" />  <!-- max idle -->
    <boolean value="true" />  <!-- test on borrow -->
    <boolean value="true" />  <!-- test on return -->
    <long value="10000" />     <!-- time between eviction runs -->
    <int value="5" />   <!-- number of connections to test per eviction run -->
    <long value="5000" />    <!-- min evictable idle time -->
    <boolean value="true" />   <!-- test while idle -->
  </object>
 
  <object class="org.apache.commons.pool.impl.StackKeyedObjectPoolFactory">
    <int value="10" />
  </object>
 
  <string value="select now()" />  <!-- validation query -->
  <boolean value="false" />  <!-- default read only -->
  <boolean value="true" /><!-- default auto commit -->
</object>

 

 

2. 해당 jocl 을 읽어 들여 서블릿에서 사용하기 위해 ServletListener 를 만듬..

 

/*
 * Created on 2004. 9. 7.
 * Package Name : com.gndsoft.action.admin
 * Version :
 * Author : 유희성(over30tornado@msn.com)
 *
 * History : 2004. 9. 7. 유희성(over30tornado@msn.com) 최초 작성
 *

 *
 */

 

package com.gndsoft.intranet.db;

 

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

 

/**
 * @author Tornado
 *
 */


public class DBCPPoolListener implements ServletContextListener {


 public void contextInitialized(ServletContextEvent sce) {
 
        try {
           
         Class.forName("com.mysql.jdbc.Driver");

 

         Class.forName("org.apache.commons.dbcp.PoolingDriver");
           
         System.setProperty( "org.xml.sax.driver",  "org.apache.xerces.parsers.SAXParser" );

 

        } catch(Exception ex) {
        
         ex.printStackTrace();
        
        }
 }


 public void contextDestroyed(ServletContextEvent sec) {

     // 커먼스 풀에서 뭔가 닫아줘야 할 경우 작성하면 된다.

 }

 

}

 

-------

Class.forName() 에서 뭘 적어줘야 할지 메일링리스트에서 찾다가 질문에 올라온거로 해서 성공함 ㅡㅡ

 

System.setProperty() 때문에 메일링 리스트 엄청 뒤짐 ㅜㅜ ... 저거 몰라서 열라 헤맴..

 

3. web.xml 에 해당 Listener 등록

 

<?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>

    <!-- Context Param -->

 <context-param>
      <param-name>poolName</param-name>
      <param-value>intranet</param-value>
    </context-param>
 
 <listener>
   <listener-class>com.gndsoft.intranet.db.DBCPPoolListener</listener-class>
 </listener>

</web-app>

 

 

-------

Pool 이름이 하드코딩될까 두려운 나머지.. 테스트 하는데 이름을 Init-param 으로 뺌 --

 

 

4. Test 를 하기 위한 JSP 작성

 

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%
 
 Connection conn = null;
 Statement stmt = null;
 ResultSet rs = null;
 
 try{
 
  String name = application.getInitParameter("poolName");
  
  if(name == null || "".equals(name) )  name = "intranet";
  
  conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/" + name);
  
  stmt = conn.createStatement();
  
  rs = stmt.executeQuery("select now()");
  
  while(rs.next()){
  
   out.print( rs.getString(1) );
  }
  
 }catch(Exception e){
 
     e.printStackTrace();
    
 }finally{
 
  try{ if(rs != null) rs.close(); }catch(Exception e){ e.printStackTrace(); }
  
  try{ if(stmt != null) stmt.close(); }catch(Exception e){ e.printStackTrace(); }
  
  try{ if(conn != null) conn.close(); }catch(Exception e){ e.printStackTrace(); }    
  
 }
 

%>

 

끝~!

 

DriverManager.getconnection() 할 때 jdbc URL 이 아닌 커먼스 풀을 적어줘야 풀링된 자원을 가져온다고 함...

몇일 써보고 좋으면 바로 적용~~~~

 

 

Posted by tornado
|

dbcp

JAVA/JSP_Servlet 2004. 9. 6. 16:37
Posted by tornado
|
Applet Technology



  [2004년 4월 19일] 자바 기술을 이용하여 사인드 애플릿 만들기!!!!

              -. 아직도 사인드 애플릿을 만들때 마이크로소프트에서 제공하는 방법을 사용하시나요?
                 이제 더 이상 그렇게 불편하게 하지 않으셔도 됩니다.
                 더 이상 지원되지 않는 Microsoft SDK for Java 4.0을 설치하실 필요도 없습니다.
                 자, 이제 자바 기술을 사용하여 사인드 애플릿을 만들어 보세요.
                 정말이지 제가 게으른 탓에 이제서야 드디어 정리를 했습니다.
                 제가 보기엔 이 방법이 훨씬 더 나은것 같습니다.
                 질문이나 문의사항은 게시판을 이용해 주세요..^^;
            
  Internet Explorer에서 실행되는 Signed Applet을 dubuild를 사용하여 만들기~!!!!

              -. cabarc를 이용하여 Signed Applet을 만들었더니, 브라우저가 실행될때마다 인증을 요구하나요?
                 하하~!!!! 이제 버전이 업그레이드 되기 전에는 인증을 요구하지 않게 할 수 있습니다.
                 cabarc대신 dubuild를 사용해 보세요...
                 어떻게 하냐고요? 그냥 이 문서를 따라하면 됩니다..^^*
                 미루고 미루었는데 드뎌 정리를 했습니다...^^;
                 마니 마니 도움이 되었으면 좋겠습니다...
                 질문이나 이상한 점은 게시판을 이용해 주세요..^^;
            
  Internet Explorer에서 실행되는 Signed Applet을 만드는 방법을 정리한 문서입니다.

              -. Microsoft SDK for Java를 이용하여 Applet에 Sign을 하여 Signed Applet을 만들 수 있습니다.
                 아쉽게도 Signed Applet에 대한 개념을 원하신다면 이 문서에는 없습니다..-.-
                 이 문서는 다만 Signed Applet을 만드는 방법만을 설명합니다..
                 그냥 순서에 따라 만드시면, 쉽게 Signed Applet을 만드실 수 있습니다...
                 그리고, 이 문서는 cabarc라는 명령어(Microsoft SDK for Java에 포함되어 있음.)사용합니다.
                 요즘에는 dubuild라는 명령어(Microsoft SDK for Java에 포함되어 있음.)를 사용합니다...
                 dubuild를 사용하는 방법도 거의 비슷한데...제가 게을러서 정리를 아직 못했습니다..*^^*
                 조만간 정리를 해서 올리도록 하겠습니다...기대하세요~~~~
            

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

[허가없는 링크^^] 패턴  (0) 2004.10.25
[펌] JAVA application 성능향상..  (0) 2004.10.07
[펌] javadoc 유틸리티  (0) 2004.09.01
[nio] 기초 정리 잘된곳  (0) 2004.08.09
[펌] 나만의 자바 컴포넌트를 만들자  (0) 2004.04.01
Posted by tornado
|

Appendix II

 

javadoc 유틸리티

javadoc 유틸리티는 클래스들, 메소드들과 /** . . . */주석을 위한 소스파일을 분석한다.또한, API 문서와 같은 형태의 HTML 파일을 생성해낸다. 사실, API 문서는 자바 소스 파일에 대한 javadoc 의 결과이다.

만일 여러분의 소스 코드에 특별한 구별자인 /**로 시작하는 주석을 추가하면 여러분은 간단히 전문적으로 보이는 문서를 얻을 수 있다. 이 방법은 한 군데에 여러분의 코드와 문서를 저장하게 해주기 때문에 아주 좋은 방법이다. 전통적인 문서는 코드와 주석들이 분리되어 있는문제로 인해 고생하고 있다. 주석이 소스 파일로서 같은 파일 안에 존재하기 때문에 손쉽게내용을 갱신한 후 다시 javadoc 을 수행하기만 하면 된다.

우리는 corejava 패키지내의 파일들에 대해 /** 주석과 javadoc 을 사용했다. 여러분의 웹브라우저를 \CoreJavaBook\corejava\api\tree.html 에 위치시키면 친숙한 형태의corejava 문서를 볼 수 있을 것이다.

 

주석을 삽입하는 방법

javadoc 유틸리티는 다음의 기능에 대한 정보를 추출한다.

l  package

l  public 클래스

l  public interface

l  public 또는 protected 메소드

l  public 또는 protected 변수와 상수

여러분은 이러한 기능들 각각에 대한 주석을 제공할 수 있다.

각각의 주석은 설명하고자 하는 기능의 바로 위에 위치시킨다. 주석은 /**로 시작하여 */

끝을 낸다.

/* * . . . */ 문서화 된 주석은 태그를 따르는 자유 형태의 텍스트를 따른다. 태그

@author 또는 @param 와 같이 @로 시작한다.

자유 형태의 텍스트의 첫 문장은 요약문이다. Javadoc 유틸리티는 자동으로 이러한 문장을 가지는 요약 페이지를 생성한다.

자유 형태 텍스트에서 여러분은 이탤릭체를 위한 <i> . . . </i> , 타자체 폰트를 위한 <tt> . . . </tt> , 볼드체를 위한 <b> . . . </b> , 이미지를 포함하는 <img. . .>처럼 HTML 수식어를 사용할 수 있다. 그러나 여러분은 <h1>이나 <hr> 헤딩을 사용해서는 안 된다. 왜냐하면 이것들은 문서의 포맷팅과 충돌을 일으키기 때문이다.

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

노트 : 만약 주석이 이미지(예를 들어, 사용자 인터페이스 구성요소의 다이어그램이나 이미

)와 같은 다른 파일과의 링크를 포함한다면, 이러한 파일은 doc-파일로 이름 지위진 서브

디렉토리에 위치한다. javadoc 유틸리티는 이러한 모든 파일을 소스 디렉토리에서 문서 디

렉토리로 복사한다.

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

 

일반적인 주석

다음의 태그들이 모든 문서화 주석에 지원된다.

@ since 텍스트

이 태그는 “since” 엔트리를 만든다. text 는 기능을 설명하는 버전을 기술하는 것이다.

@ deprecated 텍스트

이 태그는 더 이상 사용되지 않는 클래스, 메소드, 변수에 대하여 설명을 한다. text 는 제자리로 되돌린다(replacement). 예를 들어, @deprecated Use <tt> setVisible(true) </tt>@see @link tags 를 사용하여 javadoc 문서의 연관된 일부분 또는 외부의 문서로 하이퍼링크되어 진다.

@see link

이 태그는 “See also” 섹션에서 하이퍼링크를 추가한다. 클래스와 메소드 두 가지를 모두사용할 수 있다. 이기서 link 는 아래의 하나이다.

l  package.class#feature label

l  <a href=”. . .”>label</a>

l  “text”

첫 번째 경우가 가장 유용한 경우이다. 클래스와 메소드, 변수의 이름을 주면 javadoc 은 문서에 하이퍼링크를 추가한다. 예를 들어, @see corejava.Console#readInt

(java.lang.String)corejava.Console 클래스의 readInt (String) 메소드에 링크를 추가한다. 패키지의 이름 혹은 패키지와 클래스의 이름을 모두 생략할 수 있다. 그러면,기능은 현재의 패키지나 클래스의 중심부에 있다.

메소드나 변수의 이름과 구분을 하기 위하여 #을 사용해야 함에 주의하여야 한다. 자바 컴파일러는 그 자체로, 패키지와 서브패키지, 클래스, 내부클래스, 메소드, 변수 사이의 구분자로서, 구간 문장의 다양한 의미를 추정하는 고도의 기술을 가지고 있다. 하지만 javadoc 틸리티는 그렇게 똑똑하지 못하여 항상 도와 주어야 한다.

만약 < 문자 뒤에 @see 태그가 온다면 하이퍼링크를 명시하여야 한다. 여러분은 원하는 어떤URL 과도 링크를 할 수 있다. 예를 들어, @see <a href =

www.horstmann.com/corejava.html>The Core Java home page</a> 이러한 각 경우에, 링크를 고정시켜 보이게 하는 선택적인 label 을 지정할 수 있다. 레벨을잊었다면 사용자는 타겟 코드 이름이나 URL 을 볼 것이다.

문자 다음에 @see 태그가 온다면 “see also” 절에 텍스트가 표시된다. 예를 들면, @see“Core Java 1.2 volume 2” 이다.하나의 기능에 대하여 다중 @see 태그를 추가 할 수도 있다. 하지만 이 모두는 반드시 함께있어야 한다.

원한다면 주석의 어디에라도 다른 클래스나 메소드에 하이퍼링크를 위치 시킬 수 있다. 주석의 어디에라도 {@link package.class#feature label} 형태의 특수형 태그를 추가 할 수 있다. 기능의 묘사는 @see tag 와 같은 룰을 따른다.

 

클래스와 인터페이스 주석

클래스 주석은 class 정의 바로 앞이면 어떠한 import 문 뒤에라도 올 수 있다.

태그에는 다음의 것들이 있다.

@author 이름

이 태그는 “author” 엔트리를 만든다. 여기에는 여러 명의 저자를 위한 복수개의 author태그를 사용할 수 있다. 그러나 그들은 모두 함께 선언돼야 한다.

@version

Posted by tornado
|

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

Commons Pool + DBCP 사용법  (0) 2004.09.07
dbcp  (0) 2004.09.06
쓰알.... 플래쉬 게시판땜쉬...  (0) 2004.08.24
[struts] &lt;bean:size 태그...  (0) 2004.08.17
[eclipse 3.0] Ctrl + E 누르니까... ㅋ  (0) 2004.08.16
Posted by tornado
|

게시판을 플래쉬로 가잰다...

 

그래서.... 알아본 결과.... &val_1=xxx&val_2=yyy 와 같은 방식과..

 

XML 로 데이터를 날려서.. 플래쉬에서 xml 을 파싱하는 방법이 있더만...

 

결국 xml 로 하기로 했음.... xml 로 만드는 툴은 jdom 을 선택

 

그래서리... 급조하여 아래의 코드가 나옴 ㅡㅡ

 

덕분에 Action 클래스가 300 줄에 육박 ㅡㅡ 미챠~~~

 

플래쉬에서 파일 업로드는 어케 허나... 환장하겠네 ㅡㅡ

 

//------------------------------------------------------------
  //  게시판 리스트 XML 생성
  //------------------------------------------------------------
  
  Element rootEL = new Element("board-list");
  
  Document doc = new Document(rootEL);
  
  Element articles = new Element("articles");
  
  rootEL.addContent(articles);

  Element articleElement = null;
  
  int virtualNum = p.getVirtualNumber();
  
  while(iter.hasNext()){


   dyna = (DynaBean)iter.next();

 

   articleElement = new Element("article");
   
   Element[] ele = new Element[fieldNames.length];
   
   for(int i = 0; i <fieldNames.length; i++){
    
    ele[i]= new Element(fieldNames[i]);
    
    // 가상 번호 적어주기.
    if("virtualNum".equals(fieldNames[i])){
     
     ele[i].setText("" + virtualNum);
     
    }else if("regidate".equals(fieldNames[i])){
     
     ele[i].addContent(BoardUtil.modifyDate(dyna.get(fieldNames[i]).toString(), true));
     
    }else{
     
     ele[i].addContent(dyna.get(fieldNames[i]).toString());
     
    }

    articleElement.addContent(ele[i]);    
       
   }

 

 

Posted by tornado
|