Most installation that I've seen of Tomcat is made with tomcat running as root. This could potentially be a disasters security hole. Most Linux systems only allow the root to listen to port 80...which is why many users of tomcat under Linux run tomcat as root. With jscv, the process will start off as root but later on will change owner to a user of your choice.
Installation
Create the user to run tomcat under with
This will create a directory under
Download and install tomcat under /usr/tomcat. This is how my tomcat directory looks like
Tomcat 5.x ship with a tomcat service file which you can use and modify. However, it's written to be used with Java 1.4. To use it with Java 1.5 you need to tweak it some more or use the following file. Please note the items in red. Tomcat user and the JDK path which you must update to fit your system. Also make sure the DAEMON_HOME executable is in the right place.
poi를 이용하여 클라이언트의 엑셀문서를 서버에 업로드후 읽어내는 작업을 하려합니다.
작업의 목적은 화면상에 입력필드가 너무 많아서(대략 240여개 정도 됩니다),
일일이 입력하기에 불편함이 초래되어,엑셀로 다운받은 다음에 해당 입력값들을 엑셀에서 입력후,
입력한 값을 다시 화면상에 뿌려주려는 것입니다.
업로드 완료후 엑셀파일을 읽을때,
Error occurred : Invalid header signature; read 5789751444030890300, expected -2226271756974174256
java.io.IOException: Invalid header signature; read 5789751444030890300, expected -2226271756974174256
at org.apache.poi.poifs.storage.HeaderBlockReader.<init>(HeaderBlockReader.java:88)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:83).......
위와 같은 에러가 발생합니다.해당 라인을 쫓아가보면,
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filePath + fileName));
이부분입니다.
읽으려 하는 엑셀은 jsp내에서,
response.setContentType("application/vnd.ms-excel;charset=euc-kr");
response.setHeader("Content-Disposition", "attachment; filename="+jspName+".xls");
response.setHeader("Content-Description", "JSP Generated Data");
을 이용해서 생성한것입니다.해당 엑셀파일을 일반 텍스트 에디터에서 열어보면,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=ks_c_5601-1987">
<meta name=ProgId content=Excel.Sheet>
(이하 생략)
meta 태그내의 'content="text/html;' 부분이 의심이 갑니다만.
엑셀을 생성하는 jsp내의 meta 태그부분을 삭제해도,생성된 엑셀을 보면 해당부분이 들어가있는데요.
다시 처음으로 와서,content='text/html' 부분때문에 Invalid header signature...의 오류가 발생하는것인지요?
jsp에서 생성된 엑셀이 아닌 일반 엑셀문서로 테스트 해봤을때는 이상없이 제대로 실행됩니다.
제가 의심한 부분이 맞는것이라면, 해결책은 어떤것이 있을런지 조언 부탁드립니다.
Invalid Header라는 에러메시지의 의미가
파일 헤더가 엑셀타입이 아니라서 그런거 같습니다.
POI가 해석하는 엑셀파일은 MS OLE Compound로 생성된 파일포맷일 경우에만
해당됩니다..html의 header를 excel이라 조작해서 생성된 엑셀파일은
실제론 텍스트파일일뿐 OLE 타입이 아니라서요.
서버에서 생성시 jsp로 생성하지 말고 poi를 이용해서 서버측에 실제
엑셀파일을 생성한 후 클라이언트로 스트리밍을 통해 다운로드 해주는 방식을
택해야할 것같네요.
그렇군요.
실제로 jsp내에서 생성되는 엑셀을 다른이름으로 저장해서 'Micrisoft Excel 통합문서' 형식으로 저장하니,
정상적으로 실행이 되는군요.
충고해주신데로, poi를 이용해서 엑셀을 생성하는 쪽으로 다시 해봐야겠습니다.
답변 고맙습니다.좋은 주말 되세요.
addTo(java.lang.String email) or addTo(java.lang.String email, java.lang.String name)으로 받는 사람의 메일주소를, setFrom(java.lang.String email) or setFrom(java.lang.String email, java.lang.String name)으로 보내는 사람의 메일을 설정합니다
물론 addTo 함수의 추가로 여러 사람에게 메일을 보낼 수 있습니다.
가장 기본적인 setSubject(java.lang.String subject)와 setMsg(java.lang.String msg)로 메일 제목과 내용을 입력한 후 send() 함수로 전송합니다
② 파일 첨부하기
첨부파일과 같이 보낼려면 EmailAttachment 를 생성하여 파일 정보를 입력해 줍니다
파일경로와 파일형태, 파일 설명등을 추가하며 마지막으로 setName(java.lang.String name)을 통해 첨부되는 파일명을 설정합니다
그 후 MultiPartEmail 을 통해 SimpleEmail 처럼 기본 메일정보를 설정합니다
마지막으로 MultiPartEmail의 attach() 함수를 통해 첨부 파일을 추가하여 전송합니다
만약 첨부파일이 두개 이상이라면 EmailAttachment 를 여러개 생성하여 파일 정보를 설정 한 후 attach()를 통해 추가해 주기만 하면 됩니다
③ URL을 통해 첨부하기
파일 경로 정보를 setURL(java.net.URL) 으로 설정할 뿐 위의 첨부파일과 동일합니다
④ HTML 이메일 보내기
HtmlEmail 클래스는 setHtmlMsg()로 작성된 html을 보낼 수 있습니다
이미지 처리가 조금 까탈스럽네요
V. 인증처리
만약 SMTP 서버가 인증을 요구한다면 org.apache.commons.mail.Email 의 setAuthentication(java.lang.String username, java.lang.String password)를 통해 해결할 수 있습니다
이 함수는 JavaMail API의 DefaultAuthenticator 클래스를 생성하여 사용합니다
② 압축을 풀면 lucene-1.4.3.jar와 lucene-demos-1.4.3.jar 파일을 클래스 패스에 겁니다
"set" 명령으로 확인합니다
설치 끝 ~
IV. 데모I 실행하기
Lucene 데모에는 두가지 데모가 있습니다
하나는 일반적인 인덱싱, 및 검색이고 다른 하나는 웹에서 사용하기 위한 인덱싱 및 웹검색입니다
1) 데모I 실행
먼저 네이버나 야후같은 웹 검색엔진을 생각해 봅시다 수도없이 많은 문서들이 어떻게 해서 그렇게 빠릴 검색될까요? 바로 검색 전처리 작업을 하기 때문입니다 예를들어 간단하게 보자면 "love"라는 단어는 A문서, B문서, C문서에 포함되어 있다라는 정보를 미리 만들어 두는 것입니다 즉 인덱스를 만들어 두는 것이지요 그리고 웹로봇들이 문서를 수집해오면 추가된 문서들에 대해 하루에 몇번씩 배치작업으로 인덱스를 추가해 주겠지요 결과적으로 "love" 검색시 인덱스 정보를 뒤져서 A문서, B문서, C문서의 결과를 보여주는 겁니다
lucene도 마찬가지 입니다 인덱스를 먼저 만들어 주어야 합니다 먼저 일단 데모프로그램을 이용하여 인덱스를 만들어 보고 이를 이용하여 검색해 봅시다 내부 코딩은 일단 실행 이후에 살펴봅시다 ^_^ (눈에 먼저 보여야 멀 해도 잘되죵)
C:\lucene-1.4.3\src\ 는 데모을 위한 자바소스 파일입니다
① 인덱스 생성하기 다음 명령으로 인덱스를 생성해 봅시다 인덱스 생성 어플리케이션은 IndexFiles.java 이며 파라미터는 인덱스를 만들 소스파일들(검색대상파일들) 입니다 여기서는 lucene의 document를 index 처리해 보겠습니다
야호~ 인덱스가 생성되었습니다
C:\lucene-1.4.3\index 풀더를보면 다음 파일들이 생성된 것을 알수있습니다
② 검색하기 검색 어플리케이션은 SearchFiles.java 이며 실행 후 Query: 에 검색할 단어를 입력해 봅시다
와~ 성공! 엄청 빠릅니다!!
검색결과가 10개씩 리스팅되며 다음 리스트는 y버튼을 클릭하여 조회 할수 있습니다
2) 데모I 인덱싱 코드 분석
이 데모 프로그램은 가장 기본이 되는 프로그램으로 핵심 코딩만 되어 있으니 lucene을 사용하기 위해서는 꼭 알아 두어야 합니다
① Analyzer 선택
Analyer 는 문서를 인덱싱 하거나 검색할때 핵심이 되는 요소로서, 텍스트를 파싱할 때 사용합니다 Analyzer의 종류에는 다음 몇가지 들이 있습니다
② IndexWriter 생성 자 이제 Analyer를 선택했으면 IndexWriter를 생성하여 Index를 만들어봅시다
첫번째 파라미터는 index가 생성될 위치를 말하며 두번째 파라미터는 선택한 Analyzer를, 세번째 파라미터는 index를 초기화 하여 다시 생성할것인지 말것인지를 말합니다 즉 추가/삭제만 할 것인지(false) 새로 만들것인지(true)를 나타냅니다 문서가 많을경우 매번 새로 만들수 없으며, 또한 만약 몇개의 문서만 변경되었는데 모두 다시 인덱스를 만들수는 없기 때문입니다 (시간 상당히 걸림 --)
③ Index에 document 추가 다음으로 소스 디렉토리(검색대상 문서들)의 파일들을 읽어가며 Analyzer에 의해 파싱된 문서 정보를 인덱스에 추가합니다
④ index optimize 마지막으로 인덱싱한 정보를 하나의 파일로 merge 합니다 즉 검색에 적합하도록 파일을 하나로 합치는 겁니다
⑤ index close
사용후 받드시 close 합시다!
끝~ 간단하죠?
이제 전체 소스를 살펴봅시다
소스는 C:\lucene-1.4.3\src\demo\org\apache\lucene\demo 에 있습니다
org.apache.lucene.demo.IndexFiles.java
3) 데모I 검색 코드분석 검색은 인덱스를 만드는 코드보다 훨씬 쉽습니다
① IndexSearcher 생성 실질적으로 검색을 담당할 IndexSearcher를 생성해 봅시다 파라미터로는 index가 생성되어있는 위치를 입력합니다
② Query 생성 Query는 질의 문자열을 파싱해 줍니다 (즉 AND,OR,NOT,!,-등의 논리연산이나 와일드카드 *,?등을 파싱합니다)
첫번째 파라미터는 질의를, 두번째 파라미터는 검색 필드를, 세번째 파라미터는 인덱스를 만든 Analyzer와 동일한 Analyzer를 입력해 줘야 합니다
③ 검색 및 검색한 결과 저장
파싱된 쿼리를 가지고 검색하여 그 결과값을 반환 받습니다
반환된 Hits 클래스는 순위가 매겨진 문서들로 검색결과를 저장하고 유지합니다
④ IndexSearcher close 검색이 끝났으면 닫아줍시다
전체 소스를 살펴봅시다
org.apache.lucene.demo.SearchFiles.java
V. 질의 문법
질의 문법에 대해 알아봅시다
① A AND B
A와 B가 모두 포함된 문서를 검색한다
② A OR B
A혹은 B가 포함된 문서를 검색한다
③ A NOT B
A는 포함되고 B는 포함되지 않는 문서를 검색한다
A ! B, A - B와 동일하다
④ +A OR B
A OR B에서 A는 받드시 포함된 문서를 검색한다
⑤ A*
A로 시작하는 단어가 있는 문서를 검색한다
⑥ A?
A로 시작하는 두글자의 단어가 있는 문서를 검색한다
⑦ A~
A와 스펠링이 비슷한 글자를 지닌 단어가 있는 문서를 검색한다
⑧ (A OR B) AND C
논리연산의 그루핑 또한 지원한다
AND, OR, NOT등은 반드시 대문자로 입력해야 인식됩니다
다음 시간에는 두번째 데모 프로그램을 실행시켜 보고 lucene을 웹 어플리케이션에 달아 봅시다~
다운받은 파일의 압축을 풀고 환경변수 및 패스를 잡아줍니다 set ANT_HOME=c:\ant set JAVA_HOME=c:\jdk1.4.2 set PATH=%PATH%;%ANT_HOME%\bin
III. 간단한 Ant 예제
Ant를 이용하여 web application을 구성할 때 다음의 구조를 유지하기를 권장합니다
① build : src, web, docs에서 결과적으로 만들어진 산출물 디렉토리 ② dist : build를 배포하기 위한 배포 디렉토리 ③ docs : 배포판에 배포할 정적인 문서를 관리할 디렉토리 ④ src : /WEB-INF/classes 에 위치할 java 소스 디렉토리 ⑤ web : HTML, JSP, 이미지등의 컨텐트 디렉토리 (WEB-INF의 서브디렉토리 포함) ⑥ build.properties : build.xml에서 사용할 properties ⑦ build.xml : ant 명령으로 실행될 설정파일
src에 하나이상의 java 소스를 테스트로 넣어 놓으세요
자 이렇게 디렉토리를 설정하고 build.xml 을 다음 step에 따라 따라 해 BOA요 ^^&
STEP 1. build.xml 의 기본구조
xml을 기본적인 내용을 안다면 이해하기 쉽습니다
하나의 build 파일은 하나의 project로 구성되며 이는 다시 여러 target으로 구성됩니다
target 이란 빌드 과정중 수행해야 할 task들을 모아놓은 job 단위 라고 보면 됩니다
compile target이라 한다면 compile에 관련된 작업들을 모아놓은 그룹이라 생각하면 쉽게 이해 될겁니다
STEP 2. 시~작 Ant 맛보기~ ① build.xml에 다음을 입력한 후 저장 합니다
-. project
project는 하나 이상의 target을 정의 합니다 또한 하나의 target은 task의 집합입니다
ant를 실행할 시에 어느 타겟을 실행할 것인지 지정할 수가 있으며 (예: \ant clear)
지정하지 않았을 경우 디폴트로 설정된 값이 사용됩니다 이부분이 default="clear"입니다
-. property
전역변수 설정 혹은 그렇게 사용할 build.properties를 정의 합니다
build.properties에 catalina.home을 정의하였으며 여러 환경이 변하더라도 이 값만
변경해주면 build.xml을 수정없이 바로 실행 가능합니다
-. echo
message 내용을 출력 합니다
-. target
target 이란 task의 집합으로 실질적으로 실행될 코드들의 묶음입니다
여기서는 아무 task도 없습니다
② build.properties에 다음을 입력 후 저장합니다
catalina.home 은 변수로 사용할 것이며 그 값은 C:\Tomcat 5.0입니다
③ 실행
해당 디렉토리로 이동하여 도스창에서 ant 라고 칩니다
STEP 3. 사전작업 하기~
이번 단계에서는 컴파일 하기전 전역변수 선언이나 컴파일 시 클래스 패스 설정을 해봅시다
① build.xml
-. project
이번에는 default 값을 prepare로 하였습니다 고로 target은 prepare가 실행될 것입니다
-. property
역시나 build.properties를 정의하였고 여러 전역변수를 설정하였습니다
build.home 이란 변수에는 ${basedir}/build 값이 정의되었으며
build.home은 ${build.home}으로 사용할수 있습니다
궁금하면 <echo message="${build.home}"/> 등으로 출력해 봅시다~
-. path
${catalina.home} 은 build.properties에서 정의하였다는것을 기역하실겁니다
fileset은 파일들의 집합을 나타내는데 어떤 특정파일만 포함 할수 있거나 혹은 어느 특정파일만 제외할 수 있습니다
javadoc target의 javadoc 태스트를 보면 java 소스가 있는 소스디렉토리와
API를 생성할 타겟 디렉토리를 정해주면 알아서 API를 생성해 줍니다
만들어진 API는 배포버젼의 dist디렉토리로 해주면 더 좋겠지요
dist target은 배포파일인 war를 만듭니다
필요한 문서가 있으면 docs 디렉토리를 만들어 로 복사도 하도록 합시다
jar 태스크는 위의 방식과 같이 사용합니다
② 실행
VI. Ant 실행
① C:\예제\ant -help
ant [options] [target [target2 [target3] ...]]
Options : -help 이 메세지의 표시 -projecthelp 프로젝트 도움 정보의 출력 -version 버전 정보의 출력과 종료 -diagnostics diagnose 나 report 문제에 도움이 되는 정보의 출력. -quiet, -q 한층 더 메세지를 적게 -verbose, -v 한층 더 메세지를 많게 -debug 디버그 정보의 출력 -emacs adornments 없이 로그 정보의 생성(produce) -logfile <file> 로그를 지정 파일에 출력 -l <file> '' -logger <classname> 로그 생성을 실행하기 위한 클래스 -listener <classname> 프로젝트 청취자(listener) 역할의 class의 인스턴스를 추가 -buildfile <file> 지정된 빌드 파일의 사용 -file <file> '' -f <file> '' -D<property>=<value> 지정된 프로퍼티의 값의 사용 -propertyfile <name> 모든 프로퍼티를 파일로부터 로드 (-D프로퍼티보다 전에) -inputhandler <class> 입력 요청(requests)를 취급하는 클래스 -find <file> 파일시스템의 루트로 향해 빌드파일을 검색하고 그것을 사용
② C:\예제\ant
현재 디렉토리에 있는 build.xml 파일을 이용해, 디폴트 타겟으로 Ant 를 실행합니다.
③ C:\예제\ant compile
현재 디렉토리에 있는 build.xml이 실행되며 파라미터로 compile을 지정하면 project의 default 값을 무시하고 compile target을 실행합니다 물론 depends 가 있다면 먼저 실행합니다
④ C:\예제\ant -buildfile test.xml
현재 디렉토리에 있는 test.xml 파일을 이용해, 디폴트 타겟으로 Ant 를 실행합니다.
⑤ C:\예제\ant -buildfile test.xml dist
현재 디렉토리에 있는 test.xml 파일을 이용해, dist 라는 이름의 타겟으로 Ant 를 실행합니다.
이제는 데이터베이스 풀을 이용한 커넥션 풀을 사용하지 않는다는것은 상상조차 할 수 없게 되었다. 각 WAS의 벤더들은 오래전부터 자사제품에 대해 최적화된 커넥션 풀을 기본적으로 제공을 하기까지 이르렀다. 또한 한스버그의 커넥션 풀링이나 풀맨의 풀등 여러 오픈된 커넥션 풀 소스들이 돌아다기기도 하였다.
여기서는 Jakarta Commons에서 진행하고있는 Commons-dbcp project에 대해 알아보고 간단한 예제를 소개하기로 하겠다
II. 다운로드 및 설치
dbcp는 commons의 pool과 collection을 사용하기때문에 다음3가지를 모두 설치해야 정상적으로 dbcp를 사용할 수 있다.
Commons-Lang은 java.lang에 있는 클래스처럼 기능적으로 필요한 유틸리티들을 모아놓은 클래스들의 집합입니다. 아마도 여러분들 역시 직접 유틸리티 클래스들을 만들어 사용하고 있을겁니다. 즉 코딩을 하다보면 이렇거 있었으면 좋겠다 싶은것들이 Commons Lang에 다 있다고 생각하시면 됩니다 ^^
일반적으로 POI가 엑셀파일을 쓰는 컴퍼넌트로 알려져 있으나 POI는 프로젝트 이름입니다. 즉 POI는 Microsoft Format File을 액세스 할 수 있는 API를 제공합니다. (한마디로 자바에서 MS파일을 읽고 쓸수있도록 지원합니다.)
POI안에는 여러 컴퍼넌트들이 있습니다.
① POIFS Microsoft의 OLE2 포맷 형식의 문서를 자바로 읽고 쓸수 있는 컴퍼넌트입니다 기본적으로 POI의 모든 컴퍼넌트들이 POIFS를 사용합니다. ② HSSF Microsoft의 엑셀파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다. ③ HWPF Microsoft의 워드파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다. 이 컴퍼넌트는 디자인 초기단계입니다. ④ HPSF Microsoft의 OLE2 포맷 형식의 문서 속성을 어플리케이션에서 사용 할수 있도록 지원하는 컴퍼넌트입니다. 현재 읽기 기능만 제공합니다
엑셀을 읽고 쓸때 수식을 지원합니다. 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);
SmartUpload, MultipartRequest, Commons fileupload등을 모두 사용해 보았지만 개인적으로 가장 애착이 가는 파일 업로드입니다.
아쉬운점은 Commons-fileupload는 지난 2003년 6월 1.0버젼으로 정식 릴리즈 되었지만 그 이후로 이렇다 할 패치나 보안이 전혀 안되었다는 것입니다. 이말은 파일 업로드 자체가 그리 복잡한 패키지가 아니며 첫 정식 버젼이 그만큼 완벽하다는 것을 반증하는 말이기도 하겠지요 ^^
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
if (FileUpload.isMultipartContent(request)) {
DiskFileUpload fileUload = new DiskFileUpload(); fileUpload.setRepositoryPath(upload); fileUpload.setSizeMax(100*1024*1024); fileUpload.setSizeThreshold(1024*50);
List items = fileUpload.parseRequest(request);
Iterator iterator = items.iterator(); while (iterator.hasNext()) {
FileItem item = (FileItem) iterator.next();
if (!item.isFormField()) { if (fileItem.getSize() > 0) { //파일 이름을 가져온다 String filename = fileItem.getName().substring(fileItem.getName().lastIndexOf("\\")+1);
기본적으로는 Web Application을 테스팅 하는데 디자인 되었지만 다른 기능들도 테스트 할 수 있도록 확장되었답니다
그럼 Apache JMeter로 무엇을 할 수 있을까요?
JMeter는 정적인 것 뿐만 아니라 동적인 자원 (files, Servlet, Perl, Java Object, DataBase 와 Queries, FTP Servers 등) 둘다 성능을 테스트 하는데 사용됩니다. 즉 서버나 네트웍 혹은 Object에 스트레스를 가하여 다양한 형태의 상태에서 성능을 전반적으로 분석 할 수 있도록 도와준다는 겁니다.
그럼 JMeter의 특징을 간단히 살펴보죵.
-. HTTP나 FTP서버 뿐만 아니라 임의의 데이터베이스 쿼리도 성능을 테스트 할 수 있습니다.
-. 100% 순수 자바로 구현되었기 때문에 기종에 상관없이 실행 할 수 있습니다.
-. Swing 기반의 Componet를 지원합니다.
-. Multithreading 기능을 이용하여 동시에 많은 Thread를 발생 시킬수도 있으며 혹은 독립된 Thread를 연속적으로 발생시켜 테스팅 할 수도 있습니다
먼저 jdk 1.4 이상이어야 합니다. jdk 1.4.1 이하버젼에서는 GUI elements가 잘 작동하지 않는 다는 bug가 레포팅 되었습니다. 운영체제는 unix (solaris, linux) 및 Widnows 계열 모두 잘 작동합니다.
그럼 다운 받은 파일의 압축을 풀어봅시다. 제가 받은 파일은 2.0.2버젼이군요
잠깐 디렉토리 구조를 보지요.
/bin 에는 실행관련 파일들이 들어있습니다.
/docs 와 /printable_docs에는 사용자 매뉴얼과 데모가 들어있습니다.
/extras 는 JMeter를 ant로 바로 실행할수 있도록 하는 설명이 들어있고요
/lib에는 JMeter를 실행하면서 로딩해야할 다른 서드 파티 jar파일을 넣으면 됩니다 만약 JDBC 테스팅을 한다면 해당하는 벤더의 JDBC를 넣으면 되겠네요
ㅈ ㅏ ~ 그럼 실행해 봅시다 /bin/jmeter.bat 을 따블클릭 합니다.
IV. 테스트 계획 수립
테스트 시작 전 먼저 계획을 수립해봅시다 어떻게 해야 할까요?
그냥 쉽게 일반적으로 생각해 봅시다
1) 테스트 인원 및 몇번을 반복할 지 결정한다 2) 첫화면을 간다 3) 로그인 페이지로 간다 4) 500ms 정도 쉰다 (로그인 아이디, 패스워드 입력시간) 5) 로그인을 한다 6) 메뉴를 하나씩 클릭한다 7) 특별한 메뉴는 반복적으로 클릭한다. 8) 또한 어떤 메뉴는 딱 한번만 클릭해야 한다. 9) 또한 다른 메뉴는 랜덤하게 클릭한다. 등의 정도가 되겠지요..
그럼 이러한 작업들이 모두 JMeter로 가능한가? YES!!
V. 초간단 테스트 예제
자 그럼 먼저 간단한 예제를 한번 만들어 봅시다.
먼저 JMeter를 실행하면 다음과 같은 화면이 나올겁니다.
많이 보고 얼렁 익숙해 집시다.
왼쪽편에 'Test Plan'이라는 노드가 보이는데 이 노드는 테스트 계획을 나타낼 일련의 실행 코드 집합 이라고 보면 됩니다 (말이 좀 어렵낭?-_-?)
중간에 User Defined Variables 라고 나오는데 이건 뭔지 저도 잘 모루겠습니다 -_-;
암튼 분명한건 여기서 정의한 변수 및 값은 테스트 플랜 이하 노드에서 모두 상속받아 사용한다는 겁니다.
다음에 체크박스 두개가 있는데 첫번째 'Run each Thread..' 요놈은 Thread를 순차적으로 실행 하겠냐 아니면 동시에 실행하겠냐의 여부를 묻는데 체크하지 않으면 동시에 실행 하는걸로 되어 있습니다. 여기서 Thread란 조금 후에 설명 하겠습니다. 두번째 체크박스는 각 요청에대한 서버의 응답 데이터를 파일에 기록할 것인지 여부를 말하는 것인데 이걸 체크하면 성능이 확~ 떨어지니 왠만함 하지 말라고 되어있습니다.
자 이제 본격적으로 시작해 봅시다. 'Test Plan'을 오른쪽 마우스로 클릭해 봅시다
Thread Group 이란 테스트 계획을 수행할 수행 단위 그룹이라 보면 될것 같습니다. 이 Thread Group을 여러개 추가 할 수도 있으며 그럴 경우 위에서 언급한 체크박스로 동시에 실행 할 것인지 순차적으로 실행 할 것인지 결정 해야 합니다.
그럼 이름을 뭘로 할까요? 'Jakarta Project'라 하지요 -_-;
ㅈ ㅏ 이름을 'Jakarta Project'라 하였습니다 멋집니다 ;;
가운데 체크박스 3개가 있네요
이건 만약 테스트 수행도중 에러(테스트 대상의 에러)가 발생 한 경우 계속할 것인지 Thread만 멈출 것인지 아니면 테스트 자체를 멈출것인지를 선택합니다 여기선 그냥 'Continue'로 하지요
그다음 항목이 가장 중요하므로 잘 숙지해야 합니다.
Number Of Threads 란 이 Thread Group이 생성할 Thread갯수를 말하는데, 쉽게 말하면 이 그룹에서는 몇 사람으로 테스트 할 것이냐 라고 생각하면 됩니다.
Ramp-Up Period (in seconds)는 한 Thread가 시작 된 후 다음 Thread가 시작 될 때까지의 대기 시간을 의미합니다 예를 들어 보자면 10개의 Thread가 사용되고 Ramp-up Period가 50이라면 총 10개의 Thread가 모두 실행되려면 50초가 걸린다는 겁니다. 즉 평균적으로 보자면 한 Thread가 실행 후 다름 Thread까지 5(50/10)초정도 후에 실행 되다는 거지요 (휴 어렵다 =3)
Loop Count는 실행 횟수를 말합니다. forever에 체크하면 무한 루프를 돕니다. 이때는 사용자가 수동으로 STOP 시켜줘야 합니다.
이제 'Jakarta Project'에 마우스를 오른쪽으로 클릭 후 'Add -> Config Element -> HTTP Request Defaults'를 선택합니다.
이 'HTTP Request Defaults'는 HTTP request를 설정함에 있어서 이 노드 이하의 HTTP request는 모두 HTTP Request Defaults에서 설정한 값을 디폴트로 상속 받아 사용하겠다는 겁니다.
반드시 추가해야 할 필수 요소는 아닙니다만 이후의 추가해야 할 HTTP Request노드가 많다면 일일이 다 다음과 같이 세팅해야 함으로 이를 추가해 놓는 편이 좋습니다.
Protocol에는 당연히 웹이니 HTTP를 써야겠고 Server name or ip에는 연결할 서버의 이름이나 ip를 적습니다. 주의할것은 주소까지 모두 여기에 적으면 안됩니다. 나머지 부분은 path 부분에 적어야 합니다.
Commons DbUtils : 데이터베이스 사용에 있어서 단순노가다로 이루어지던 많은 작업을 편리하게 해준다. 그동안 "이거 귀찮은데 유틸로 뽑아놓을까?" 아니면 "우씨~ 이런 노가다" 하던 부분이 한방에 해결됐다. 단순한 유틸 패키지이기에 사용법도 간단하고 편리하다.
//1. JDBC 드라이버 로딩을 간략화(로딩 성공시 true 반환)
if (!DbUtils.loadDriver("com.mysql.jdbc.Driver")) {
몇 년전에 DbUtils와 비슷한 클래스를 만든 적이 있었는데, 그때도 좀 찾아볼 걸 그랬나봅니다. 그러고 보면 저도 apache commons에 이미 있는 것을 많이도 만들어본 삽질의 시간들을 겪었었습니다. 신입 때 commons beanutils하고 commons io에 포함된 것 비슷한 유틸리티 만들어 놓고 혼자서 뿌듯해 했었죠 -_-;