달력

122024  이전 다음

  • 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
  • 31

웹상에서 입사지원서를 받아서 워드(.doc) 파일로 만드는데요.

<% 
 response.setHeader("Content-Disposition", "attachment; filename="+seat_no+".doc"); 
 response.setHeader("Content-Description", "JSP Generated Data"); 
 response.setContentType("application/vnd.ms-excel"); 
%> 

이런식으로 해서 워드문서는 만드는데 웹페이지에 있는 이미지들은 하나도 포함이 안되네요.

다음 2가지 방법으로 해결 가능 
1. 사용되는 모든 Image에 Full Path URL을 적으시면 됩니다. 즉, <a href="http://xxx.xxx.xxx.xxx./aaa.gif" target=_blank class=postlink>http://xxx.xxx.xxx.xxx./aaa.gif</a> 이런식으로.. 
2. base tag를 사용하시면 됩니다. body tag 바로 위에 <base href="URL">을 적으시면 이후의 모든 URL이 base의 URL을 기준으로 처리됩니다.

'java' 카테고리의 다른 글

java.sql.SQLException: IO 예외 상황: Broken pipe - thread  (0) 2006.01.31
Jakarta POI - 쓰기  (0) 2005.11.30
Jakarta POI - 읽기  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
Posted by 알 수 없는 사용자
|

Jakarta POI - 읽기

java 2005. 11. 30. 00:12

http://poi.apache.org/index.html
http://blog.naver.com/levin01.do?Redirect=Log&logNo=100011049989


I. POI 란?

일반적으로 POI가 엑셀파일을 쓰는 컴퍼넌트로 알려져 있으나 POI는 프로젝트 이름입니다.
즉 POI는 Microsoft Format File을 액세스 할 수 있는 API를 제공합니다. (한마디로 자바에서 MS파일을 읽고 쓸수있도록 지원합니다.)

POI안에는 여러 컴퍼넌트들이 있습니다.

POIFS
Microsoft의 OLE2 포맷 형식의 문서를 자바로 읽고 쓸수 있는 컴퍼넌트입니다
기본적으로 POI의 모든 컴퍼넌트들이 POIFS를 사용합니다.
HSSF
Microsoft의 엑셀파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다.
HWPF
Microsoft의 워드파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다.
이 컴퍼넌트는 디자인 초기단계입니다.
HPSF
Microsoft의 OLE2 포맷 형식의 문서 속성을 어플리케이션에서 사용 할수 있도록 지원하는 컴퍼넌트입니다.
현재 읽기 기능만 제공합니다

워드파일을 핸들링 하는 HWPF는 초기단계라 사용을 못하지만 기대는 되는군요 ^^

ps. 영어사전을 찾아보니 poi는 하와이의 토란 요리를 뜻하더군요.
우리나라말로 하니 자카르타 토란 프로젝트 쯤 될라나? ㅎㅎ

II. 다운로드 및 설치
다운로드 받으러 갑시다~!
http://jakarta.apache.org/site/downloads/downloads_poi.cgi

현재 2.5.1버젼입니다.
다운받은 파일을 압축을 풀면 *.jar 파일들이 있을겁니다 이 파일들을 자신의 어플리케이션 /lib/에 복사합시다

POI API http://jakarta.apache.org/poi/apidocs/index.html

Quick Guide http://jakarta.apache.org/poi/hssf/quick-guide.html

III. Formula(수식) 지원에 관해..

엑셀을 읽고 쓸때 수식을 지원합니다.
org.apache.poi.hssf.usermodel.HSSFCell의 setCellFormula("formulaString") 메쏘드는 스프레드시트에 수식을 추가하는데 사용되며 getCellFormula() 메쏘드는 수식을 대표하는 문자열을 해석하는데 사용됩니다. 하지만 엑셀에서 사용하는 수식을 모두 사용 할 수는 없습니다.

지원되는 부분
-. 셀 참조, 시트참조, 지역참조
-. 상대적 혹은 절대적 참조
-. 수연산 및 논리연산
-. 시트 혹은 매크로 함수
-. 수식 결과값 반환

부분적 지원
문자열을 포함하는 수식을 해석할 수는 있지만 문자열값을 반환하는 수식은 아직 지원하지 않습니다.

지원되지 않는 부분
-. 배열 수식
-. 1진법 수식
-. 3D 참조
-. 에러 값 (cells containing #REF's or #VALUE's)

IV. 기본객체

가장 기본이되는 객체가 다음 4가지 입니다. 이름에서 무엇을 뜻하는지 대강 짐작 할 수 있겠죵?

HSSFWorkbook - 엑셀 워크북을 말합니다.
HSSFSheet - 엑셀 쉬트를 나타냅니다.
HSSFRow - 엑셀에서 특정 행입니다.
HSSFCell - 엑셀에서 특정 행에대한 특정 셀입니다

위 4가지 객체는 앞으로 계속 나올겁니다. 눈여겨 미리 봐 둡시다. @.@

V. 엑셀 읽기 예제

POSFS을 이용하여 엑셀 워크북을 생성합니다.

POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("excelfile.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(fs);

생성된 워크북을 이용하여 시트 수만큼 돌면서 엑셀 시트 하나씩을 생성합니다.

int sheetNum = workbook.getNumberOfSheets();

for (int k = 0; k < sheetNum; k++) {
   System.out.println("Sheet Number : "+k);

   System.out.println(Sheet Name : " + workbook.getSheetName(k));
   HSSFSheet sheet = workbook.getSheetAt(k);

}

생성된 시트를 이용하여 그 행의 수만큼 돌면서 행을 하나씩 생성합니다.

int rows = sheet.getPhysicalNumberOfRows();

for (int r = 0; r < rows; r++) {
   HSSFRow row   = sheet.getRow(r);

   System.out.println("Row : "+row.getRowNum());

}

역시나 생성된 행을 이용하여 그 셀의 수만큼 돌면서 셀을 하나씩 생성합니다.

int cells = row.getPhysicalNumberOfCells();

for (short c = 0; c < cells; c++) {              <--!! short 형입니다. 255개가 max!
    HSSFCell cell  = row.getCell(c);

    int celltype = cell.getCellType();

    ...

}

셀을 생성하여 셀 타입에 따라 처리를 해주면 끝~

주의사항

만약 엑셀에서 A열에 아무런 값이 없으면 그 행은 읽지 못합니다.
행을 읽지 못하니 셀또한 처리 할 수 없습니다

VI. 엑셀읽기 샘플소스

샘플 데이터

사용자 삽입 이미지

A열은 B열에 대한 셀 타입을 나타내며 C열은 D열에대한 셀 타입을 나타냅니다.
즉 B:1 의 123456의 셀 타입은 A:1 일반 이라는 것이며 마찬가지로
D:1의 2005-02-09의 셀타입은 C:1 사용자정의로 세팅하였다는 겁니다

이 엑셀의 데이터를 다음 소스로 읽어 보겠습니다.

<%@ page
language="java"
contentType="text/html;charset=euc-kr"
import="java.io.*,
 org.apache.poi.poifs.filesystem.POIFSFileSystem,
 org.apache.poi.hssf.record.*,
 org.apache.poi.hssf.model.*,
 org.apache.poi.hssf.usermodel.*,
 org.apache.poi.hssf.util.*" %>


<html>
<head><title>Read example</title></head>
<body>

<%

  String excelfile = "C:\\Tomcat 5.0\\webapps\\ROOT\\example.xls";

  try {
       POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excelfile));


       //워크북을 생성!               

       HSSFWorkbook workbook = new HSSFWorkbook(fs);

       int sheetNum = workbook.getNumberOfSheets();


       for (int k = 0; k < sheetNum; k++) {


            //시트 이름과 시트번호를 추출
%>

            <br><br>
            Sheet Number <%= k %> <br>
            Sheet Name <%= workbook.getSheetName(k) %><br>
<%
            HSSFSheet sheet = workbook.getSheetAt(k);
            int rows = sheet.getPhysicalNumberOfRows();


            for (int r = 0; r < rows; r++) {


                // 시트에 대한 행을 하나씩 추출
                HSSFRow row   = sheet.getRow(r);
                if (row != null) {
                     int cells = row.getPhysicalNumberOfCells();
%>
                     ROW  <%= row.getRowNum() %> <%=cells%></b><br>
<%

                     for (short c = 0; c < cells; c++) {


                         // 행에대한 셀을 하나씩 추출하여 셀 타입에 따라 처리
                         HSSFCell cell  = row.getCell(c);
                         if (cell != null) {
                              String value = null;

                              switch (cell.getCellType()) {

                                   case HSSFCell.CELL_TYPE_FORMULA :
                                       value = "FORMULA value=" + cell.getCellFormula();
                                        break;
                                   case HSSFCell.CELL_TYPE_NUMERIC :
                                       value = "NUMERIC value=" + cell.getNumericCellValue(); //double
                                       break;
                                  case HSSFCell.CELL_TYPE_STRING :
                                       value = "STRING value=" + cell.getStringCellValue(); //String
                                       break;
                                  case HSSFCell.CELL_TYPE_BLANK :
                                      value = null;
                                     break;
                                 case HSSFCell.CELL_TYPE_BOOLEAN :
                                     value = "BOOLEAN value=" + cell.getBooleanCellValue(); //boolean
                                    break;
                                case HSSFCell.CELL_TYPE_ERROR :
                                     value = "ERROR value=" + cell.getErrorCellValue(); // byte
                                     break;
                                default :
                             }
%>        
                          <%= "CELL col=" + cell.getCellNum() + " VALUE=" + value %> <br>
<%
                        }
                    }
                }
            }
       }
   } catch (Exception e) {
%>
       Error occurred:  <%= e.getMessage() %>
<%  
       e.printStackTrace();
    }

%>


</body>
</html>

위 소스의 결과입니다.

Sheet Number 0
Sheet Name 한글
ROW 0 4
CELL col=0 VALUE=STRING value=일반
CELL col=1 VALUE=NUMERIC value=123456.0
CELL col=2 VALUE=STRING value=사용자정의
CELL col=3 VALUE=NUMERIC value=38392.0
ROW 1 4
CELL col=0 VALUE=STRING value=숫자
CELL col=1 VALUE=NUMERIC value=123456.0
CELL col=2 VALUE=STRING value=날짜 (yy-m-d h:mm)
CELL col=3 VALUE=NUMERIC value=38393.0
ROW 2 4
CELL col=0 VALUE=STRING value=통화
CELL col=1 VALUE=NUMERIC value=123456.0
CELL col=2 VALUE=STRING value=날짜 (yy年 mm月 dd日)
CELL col=3 VALUE=NUMERIC value=38394.0
ROW 3 4
CELL col=0 VALUE=STRING value=텍스트
CELL col=1 VALUE=NUMERIC value=123456.0
CELL col=2 VALUE=STRING value=날짜 (yyyy년 mm월 dd일)
CELL col=3 VALUE=NUMERIC value=38395.0


결과를 보니 사용자가 지정한 셀 타입에 관계없이 숫자관련 셀은 POI에서 모두 숫자 타입으로 인식해 버렸습니다.날짜 역시 지정한 셀 타입에 관계없이 모두 숫자 타입으로 인식해 버리는군요!
그럼 어떻게 날짜를 제대로 표현할까요?
날짜 타입을 제대로 나타내기 위해서는 날짜 Cell에는 getDateCellValue()를 사용하면 정상적으로 처리 할 수 있습니다.

SimpleDateformat sdf = new SimpleDateformat("yyyy-MM-dd hh:mm");
String date = sdf.format(cell.getDateCellValue());

등을 이용하면 나타내고자 하는 알짜를 표현 하기 더 쉽겠지요 나머지 수식을 가져 올때도 마찬가지입니다. 이런 사항을 도표로 나타내보았습니다.

org.apache.poi.hssf.usermodel.HSSFCell 에는 모두 6가지의 Cell Type이 있는데, cell.getCellType()을 하면 그 셀의 반환값을 알 수 있으며 그에 상응하는 static 필드타입은 다음과 같습니다.

셀타입 필드타입

함수

함수반환값
0 CELL_TYPE_NUMERIC

getNumericCellValue()
-> 숫자 타입일때
getDateCellValue()
-> 날짜 타입일때

double

Date

1 CELL_TYPE_STRING

getStringCellValue()

String
2 CELL_TYPE_FORMULA

getCellFormula()
-> 수식자체를 가져올때
getNumericCellValue()
-> 수식 반환값이 숫자일때
getStringCellValue()
-> 수식 반환값이 문자일때

String

double

String

3 CELL_TYPE_BLANK

4 CELL_TYPE_BOOLEAN

getBooleanCellValue()

boolean
5 CELL_TYPE_ERROR

getErrorCellvalue()

byte

'java' 카테고리의 다른 글

Jakarta POI - 쓰기  (0) 2005.11.30
이미지포함된 워드 파일 다운로드 시  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
정규식  (0) 2005.11.30
Posted by 알 수 없는 사용자
|

스케쥴러 구현

java 2005. 11. 30. 00:03

http://okjsp.pe.kr/bbs?act=VIEW&seq=62106&bbs=bbs3&keyfield=content&keyword=timer&pg=

간단한 Sample을 보여드립니다.
프로퍼티 파일을 이용하면 동적으로 Class를 Load할 수 있죠.
또한 Quartz Sample을 보시면 Crontime까지 실행 도중에 변경가능합니다. 또한 같은 스케쥴 시간을 갖고 있는 Job은 여러개 동시에 등록 가능합니다.
Quartz의 Sample중 InterruptableJobTest을 보시면 실행중인 Job을 찾아서 Delete 시키는 방법도 있으므로, 이런 기능들을 잘 섞어서 쓰시면 가능할 것 같은데요.
-------------------
import java.text.ParseException;
 
import org.apache.log4j.Logger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
 
import com.util.Config;
 
/**
 * project.properties에 설정된 내용을 이용하여 정해진 시간마다 등록된 Thread를 실행하기 위한 Main Program
 */
 
/**
 * 
 */
public class QuartzSample {
    static Logger logger = Logger.getLogger( Np2RawDataSyncTimerMain.class );
 
    public static void main(String [] args)
    {
       // Sample.properties 를 읽어 원하는 내용을 찾아주는 Class
        Config cf = new Config();
 
        // TaskGroups을 구한다.
        // White space로 구분한다.
        String [] taskGroups = cf.getConfig( "TaskGroups" ).split( "\\s" );
 
        SchedulerFactory schFact = null;
        Scheduler scheduler = null;
 
        JobDetail jobDetail = null;
        CronTrigger trigger = null;
        String className = null;
 
        try
        {
            // Schedule 처리를 위한 SchedulerFactory 생성
            schFact = new StdSchedulerFactory();
            scheduler = schFact.getScheduler();
            scheduler.start();
 
            for ( int i = 0; i < taskGroups.length; i++ )
            {
                String scheduleTime = cf.getConfig( taskGroups[i] + ".ScheduleTime" );
                String [] tackName = cf.getConfig( taskGroups[i] + ".TaskNames" ).split( "\\s" );
 
                for ( int j = 0; j < tackName.length; j++ )
                {
                    Class c = null;
                    className = cf.getConfig( tackName[j] + ".ClassName" );
 
                    logger.debug( tackName[j] + ".ClassName : " + className );
 
                    // 실행될 Class를 Load한다.
                    c = Class.forName( className );
 
                    jobDetail = new JobDetail( tackName[j], taskGroups[i], c );
 
                    trigger = new CronTrigger( tackName[j], taskGroups[i] );
                    try
                    {
                        trigger.setCronExpression( scheduleTime );
                    }
                    catch ( ParseException e2 )
                    {
                        logger.error( "CronTrigger ParseException : " + tackName[j] + ".ClassName : " + className );
                        logger.error( "CronTrigger ParseException : " + scheduleTime );
                        e2.printStackTrace();
                    }
 
                    // Config에서 읽은 공통 사항을 Job에 전달하기 위해 저장한다.
                    jobDetail.getJobDataMap().put( "web.driver", webDriver );
                    jobDetail.getJobDataMap().put( "web_db.url", webURL );
                    jobDetail.getJobDataMap().put( "web_db.username", username );
                    jobDetail.getJobDataMap().put( "web_db.password", password );
 
                    try
                    {
                        scheduler.scheduleJob( jobDetail, trigger );
                    }
                    catch ( SchedulerException e1 )
                    {
                        logger.error( "SchedulerException : " + tackName[j] + ".ClassName : " + className );
                        e1.printStackTrace();
                    }
                }
            } // for
 
        }
        catch ( ClassNotFoundException e )
        {
            logger.error( "ClassNotFoundException : " + className );
            e.printStackTrace();
        }
        catch ( SchedulerException e )
        {
            logger.error( "SchedulerException : Scheduler could not execute!!" );
            e.printStackTrace();
        }
 
    }
 
}
---------------------------
Sample.properties 파일의 설정내용
 
TaskGroups = RawDataSyncGroup
 
#
# RowDataSync Group 설정
# 매일 5분 마다 실행
RawDataSyncGroup.ScheduleTime = 0 0/5 * * * ?
RawDataSyncGroup.TaskNames = RawDataSync_1 RawDataSync_2
 
# 실행될 Task의 Full Package 이름을 설정
RawDataSync_1.ClassName = com.kt.np2.biz.sync.RawDataSync_1
RawDataSync_2.ClassName = com.kt.np2.biz.sync.RawDataSync_2

'java' 카테고리의 다른 글

이미지포함된 워드 파일 다운로드 시  (0) 2005.11.30
Jakarta POI - 읽기  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
정규식  (0) 2005.11.30
DB를 이용한 채번  (0) 2005.11.28
Posted by 알 수 없는 사용자
|


테스트 성공.

* Blocking 문제
java 프로세스 실행 시, I/O 가 끝날 때까지 thread 가 run 상태이다. blocking 이 문제가 된다면 thread 를 따로 생성해서 사용하자.
만약 web 에서 구현 시 servlet 을 사용한다면, 문제가 되겠지. application 을 스케쥴걸어서 동작시키는 것이 좋겠다.
http://okjsp.pe.kr/bbs?act=VIEW&seq=46721&bbs=bbs3&keyfield=content&keyword=pop3&pg=
K사에서 구현 시, 스케쥴러 돌려달라고 요청했음.

http://okjsp.pe.kr/bbs?act=VIEW&bbs=bbs3&keyfield=content&keyword=pop3&seq=23441&pg=2


JavaMail을 찾다가 본 소스 입니다. 실제 실행되는지는 잘 모르겠고요.
한번 해보시기 바랍니다.

일단 메일함에 접근을 하기 위해서는 session과 store, folder라는 세가지가 필요합니다.
그러기 위해선 다음과 같이 import해야 합니다.

import javax.mail.*;
import javax.mail.internet.*;
import javax.actication.*;

private Session sess;
private Store store;
private Folder folder;

그리고 나선 smtp 서버와 pop3 서버에 연결을 해야 겠지요 다음과 같습니다.

Properties prop = System.getProperties();
prop.put("mail.smtp.host",smtp 서버);
sess = Session.getInstance(prop, null); // 세션 smtp 시작

store = sess.getStore("pop3");
store.connect(pop3서버, user, pwd); // pop3 에 스토어로 연결됨

folder = store.getFolder("INBOX"); // store를 통해 편지함에 접근합니다.
folder.open(Folder.READ_ONLY); // Inbox 받은편지함을 엽니다.

이렇게 하면 이제 편지들을 가져 올준비가 됐습니다.
folder.open 메소드에 쓰인 상수는 Javamail API에서 찾아보시기 바랍니다.

가져오는 간단한 예제를 보지여.
Message[] messages = folder.getMessages(); // Message 는 편지를 의미합니다.

//내용을 뽑아내는 부분은 반복문으로 뽑아내시는게 좋을겁니다. for문을 쓰면
for (int i=0;i<messages.length;i++) 이하는 대충 넘어가고

보낸 날짜 받기.. 는 String date = messages[i].getSentDate() // 날짜 포맷에 맞춰 바꾸세요.
사이즈 뽑아내기는 String size = messages[i].getSize() // 사이즈도 포맷에 맞춰 바꾸세요.
보낸 사람 주소 Address addr = messages[i].getFrom()[0];
제목  String subject[] = messges[i].getHeader("subject");
      subject[0] 이 제목입니다.

모든 데이터는 한글 변환 처리 해주셔야 할겁니다.
그리고 연결을 끝낼때는 folder와 store를 닫아 주셔야 합니다.

그리고 위에 코드들을 쓰는 method는 모두 MessageException 처리를 해주셔야 합니다.
꼭 성공하세요.. 저도 소스는 구했지만 테스트를 해볼곳이 없어서 아직 못해봤습니다.


* 메일 내용 받기

Part p = body.getBodyPart(0);
 
 if(p.isMimeType("text/*")){
  Object content = p.getContent();             <------- 요기
        if (content instanceof String) {
          mail.contents = (String) content;
        } else if (content instanceof InputStream) {
          InputStream in = (InputStream) content;
          ByteArrayOutputStream bout = new ByteArrayOutputStream();
          byte[] buffer = new byte[8192];
          int amount = 0;
          while ((amount = in.read(buffer)) >= 0) {
            bout.write(buffer, 0, amount);
          }
          mail.contents = new String(bout.toString());
        }
 }



* 특정 경로의 첨부파일 가져오기


try{ 
    Properties props = new Properties(); 
    Session session = Session.getDefaultInstance(props, null); 
    Store store = session.getStore("pop3"); 
    store.connect(host, user, password); 

    Folder folder = store.getFolder("INBOX"); 
    folder.open(Folder.READ_ONLY); 

    Message message[] = folder.getMessages();
    for (int i=0, n=message.length; i<n; i++) { 
        if(message[i].isMimeType("text/plain")){
            System.out.println("일반텍스트메일입니다.");
        }else if(message[i].isMimeType("multipart/*")) {   // 첨부파일일때
            System.out.println("첨부메일입니다.");
            filename =  part.getFileName(); 
            if(filename != null){ 
                InputStream in = part.getInputStream(); 
                FileOutputStream fout = new FileOutputStream(new File(filename)); 
                while(c!=-1){ 
                    fout.write(c); 
                    c=in.read(); 
                } 
                fout.close(); 
                in.close(); 
            }
        }
    }
    folder.close(true); 
    store.close(); 
}catch(Exception e){ 
    System.out.print(e); 
}


'java' 카테고리의 다른 글

Jakarta POI - 읽기  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
정규식  (0) 2005.11.30
DB를 이용한 채번  (0) 2005.11.28
파일 업로드와 MultipartRequest  (0) 2005.11.28
Posted by 알 수 없는 사용자
|

정규식

java 2005. 11. 30. 00:02

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

K사에서 구현 시, 정규식의 패턴을 DB에 넣어 패턴을 설정하여 사용하도록 했다. 관리자가 패턴 입력 시, 만약 패턴에 유효하지 않은 문자를 넣으면 Exception 발생.

'java' 카테고리의 다른 글

Jakarta POI - 읽기  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
DB를 이용한 채번  (0) 2005.11.28
파일 업로드와 MultipartRequest  (0) 2005.11.28
Posted by 알 수 없는 사용자
|

DB를 이용한 채번

java 2005. 11. 28. 22:47

채번 테이블을 가지고 날짜별로 번호를 부여한다.
select 하여 가장 큰 번호를 얻어오며, ... for update  하여 테이블에 락을 걸고 채번한 번호를 update 한다.

채번하는 메소드는 synchronized 를 걸어 싱글톤으로 구현한다.

* 문제점
synchronized 한 메소드에 접근한 프로세스가 이상종료를 하면 key를 가지고 죽어버리기 때문에
다른 프로세스들이 접근할 수 없다. 이러한 경우는 할 수 없이 was를 restart 하게 된다.
혹은 for update 로 테이블에 락을 걸고 이상종료를 하는 경우에는 DB 테이블에도 락이 걸리므로, 심각한 상황에 처하게 된다.

'java' 카테고리의 다른 글

Jakarta POI - 읽기  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
정규식  (0) 2005.11.30
파일 업로드와 MultipartRequest  (0) 2005.11.28
Posted by 알 수 없는 사용자
|

K사 프로젝트 시

LSNRCTL> start
Starting /oracle/app/oracle/bin/tnslsnr: please wait...

TNSLSNR for Solaris: Version 9.2.0.1.0 - Production
System parameter file is /oracle/app/oracle/network/admin/listener.ora
Log messages written to /oracle/app/oracle/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.7.209)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Solaris: Version 9.2.0.1.0 - Production
Start Date                28-NOV-2005 11:28:10
Uptime                    0 days 0 hr. 3 min. 44 sec
Trace Level               off
Security                  OFF
SNMP                      OFF
Listener Parameter File   /oracle/app/oracle/network/admin/listener.ora
Listener Log File         /oracle/app/oracle/network/log/listener.log
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.7.209)(PORT=1521)))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
  Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "minwon" has 1 instance(s).
  Instance "minwon", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
LSNRCTL>


* 상황
1. 갑자기 DB접속이 안되는 현상 발생. 리스너를 start 했는데 되지 않음.
2. 디비가 다운되어 있다고 생각하고 시작하기 위해 sqlplus에서 DBA계정으로 start 를 함. 마운트, 오픈이 정상적으로 이루어짐.
3. 리스너를 start 함. 위의 로그 발생. inteliJ 에서 쿼리를 보냄. 접속은 성공적으로 되고 sql 도 결과를 리턴한다. 하지만 사이트에서 프로그램으로 접속시 Connection refused(DESCRIPTION=(TMP=)(VSNNUM=150999297)(ERR=12505)(ERROR_STACK=(ERROR=(CODE=12505)(EMFI=4)))) 에러 발생.

관련 글 : http://database.sarang.net/?criteria=oracle&keyword=status+UNKNOWN%2C+has+1+handler%28s%29+for+this+service...

* database.sarang.net
status가 UNKNOWN이라고 뜨는 것은 listener.ora 파일에 SID_LIST_LISTENER부분의 상태를 나타내는 것입니다.

제가 알기론, 에러가 아니고, tnslsnr이 찾지를 못해서 unknown이라고 뜬다고 합니다...  REDAY는 접속가능한 상태를 나타냅니다.
RAC환경이 아니시라면, SID_LIST_LISTENER 부분은 없어도 괜찮습니다.

* James's
스레드에서 억세스할 수 있는 파일의 갯수가 정해져 있다. ulimit -a 해서 filesdescriptor 의 갯수.
현재 서버의 갯수가 256으로 잡혀 있음. 그렇기때문에 사용할 수 있는 스레드의 갯수가 한정되어 있는데...
oracle의 해당 인스턴스를 잡고 있어야 할 스레드가 뜨지 못해서, 인스턴스를 찾지 못할 수도 있다.

'DB' 카테고리의 다른 글

nls_database 세팅보기(캐릭터 셋 보기)  (0) 2006.01.06
캐릭터셋 변경  (0) 2006.01.06
MySQL 캐릭터셋 설정  (0) 2005.12.10
DATABASE 한글문서  (0) 2005.12.07
[QUERY] Primary key 생성 시 - 데이터가 있는 상태에서도 가능  (0) 2005.12.07
Posted by 알 수 없는 사용자
|

1. 대용량 파일 업로드
대용량 파일 업로드 시. 소켓을 직접 구현하여 파일을 읽어 업로드 하다가 일정 시간이 지나면 - 점유율을 낮추기 위해 - IO를 끊는다. 잠시 텀을 가지고 다시 IO를 연결하여 파일을 분할하여 write 하는 경우도 있다.

2. 파일 업로드 관련 프로젝트
- MultipartRequest - 클래스를 생성하는 순간 파일사이즈와 관계없이 모두 읽어 wrtie한다. 업로드 되는 파일명을 지정할 수도 없고. 해당 파일명이 중복되면 옵션에 따라 파일명 뒤에 숫자가 붙는다. 한글파일이 깨지지 않도록 인코딩 방법을 지정해 줄 수 있다.
만약 form의 내용이 비어있는 경우에는 null 값으로 들어간다.

- Commons

3. MultipartRequest 의 문제점 발생
- submit 되는 file 폼은 같은 이름의 폼 객체를 사용한다.  
- 업로드 시 파일 명을 자동으로 중복체크하여 파일명을 변경하여 업로드 되는 경우.
- MultipartRequest 의 getFile(name) 을 사용하는 경우.
- form 객체의 가장 마지막 파일만 리턴된다.
- MutipartRequest 수정
- 생성자에서 file 을 hashtable 에 넣어 사용하는데. 그때 중복되는 key가 있으면 덮어서 넣음.

* 수정사항 - K사 프로젝트
- 메소드 추가. getFiles(name) 를 하면 file[] 배열이 리턴된다.
- 메소드 추가. UploadFile[]을 직접 리턴받을 수 있다. UploadFile 클래스는 MultipartRequest 내부에서 사용하는 파일정보를 가진 클래스이다. 디렉토리 정보, 파일명 정보 등이 들어있다.
해당 클래스에서 직접 UploadFile 클래스를 리턴받아 해당 데이터를 직접 가져온다.

'java' 카테고리의 다른 글

Jakarta POI - 읽기  (0) 2005.11.30
스케쥴러 구현  (0) 2005.11.30
JavaMail 을 이용하여 pop3로 메일 가져오기  (1) 2005.11.30
정규식  (0) 2005.11.30
DB를 이용한 채번  (0) 2005.11.28
Posted by 알 수 없는 사용자
|


'Today's Song' 카테고리의 다른 글

Another Sad Song - Jasmin Tabatabai  (0) 2009.01.20
Blower's daughter - Damien Rice  (0) 2009.01.20
Falling Slowly - Glen Hansard  (0) 2009.01.19
If You Want Me - Marketa Irglova  (0) 2009.01.19
Stay - Palmy  (0) 2008.09.28
Posted by marryjane
|