달력

02

« 2012/02 »

  •  
  •  
  •  
  • 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
  •  
  •  
  •  
일반적인 웹 애플리케이션을 개발할 때 서블릿을 이용할 경우 자바 Thread를 이용할 경우가 별로 없는 듯 하다. 왜냐하면 서블릿을 기존의 HTML을 렌더링하는 일반적인 용도로 사용할 경우에는 Thread를 이용할 경우가 확실히 작아진다.

하지만, 타 기종간의 애플리케이션을 기반으로 한 서버 사이드의 영역으로서 J2EE 프로젝트에서 서블릿을 사용할 경우 실행 파일과 같은 역할을 수행하는 경우가 많다. 실제로 서블릿은 CGI 형태의 코딩에 어울리는 코딩 기법이기도 하다. 서버 사이드의 실행 파일이라고 할 수 있겠다.

사실 서블릿은 그 용도가 아주 다양한데, 웹 애플리케이션을 공부하는데 있어 J2EE를 시작한다면 JSP를 공부하기 보다는 먼저 서블릿을 공부하는게 올바른 순서라고 할 수 있다.
서두가 길어졌다. 제목대로 간단하게 서블릿 코드 상에 Thread를 구동시켜 보자.

먼저, 간단한 Thread 코드를 살펴보자. [CountRunable.java]
/**
 * CountRunable.java
 *
 * Runnable 인터페이스를 구현한 간단한 Count Thread 프로그램
 */
package net.wiseant.test.thread;

/**
 * @author SangHyup LEE
 * @version 1.0
 *
 */
public class CountRunable implements Runnable {

    private int count = 0;
    
    public CountRunable(int count) {
        this.count = count;
    }
    
    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("COUNT : " + count);
    }

}


[CountRunable.java]는 Runable를 implements 하여 구현한 간단한 Thread 코드이다. 그럼 CountRunable 클래스를 호출하는 서블릿 코드를 살펴보자.

[CountThreadServlet]
/**
 * CountThreadServlet.java
 *
 * CountRunable 쓰레드를 수행하기 위한 servlet 프로그램
 */
package net.wiseant.test.web.servlet;

import java.io.IOException;

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

import net.wiseant.test.thread.CountRunable;

public class CountThreadServlet extends HttpServlet {

    private static int count = 0;
    
    /**
     * The doGet method of the servlet. <br>
     *
     * This method is called when a form has its tag value method equals to get.
     *
     * @param request the request send by the client to the server
     * @param response the response send by the server to the client
     * @throws ServletException if an error occurred
     * @throws IOException if an error occurred
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        while ( count <= 20 ) {
            CountRunable countRunable = new CountRunable(count);
            Thread countThread = new Thread(countRunable);
            countThread.start();
            count++;
        }
        
    }

}


doGet 메소드에 간단하게 Runable를 implements하여 구현한 CountRunable를 실행하고 있는 코드가 보인다. 일반적으로 자바 Thread를 수행하는 코드와 다를 것이 없다.
코드를 실제로 수행해보면 count를 static 변수로 선언하였기 때문에 각 Thread가 수행되는 순서에 따라서 증가하대 그 순서가 serial  하지 않고, Thread가 수행되는 순서에 따라서 실행되는 것을 알 수 있다. 다음은 예제로 돌려본 실행하면이다.

COUNT : 0
COUNT : 1
COUNT : 2
COUNT : 6
COUNT : 4
COUNT : 3
COUNT : 8
COUNT : 13
COUNT : 11
COUNT : 10
COUNT : 5
COUNT : 9
COUNT : 7
COUNT : 14
COUNT : 12
COUNT : 15
COUNT : 16
COUNT : 18
COUNT : 19
COUNT : 20
COUNT : 17
Posted by korcslewis
JSTL에는 많은 기능들이 있으나, 대체로 일일히 기억한 상태로 사용하기에는 부담이 많다. 그래서 하나씩 정리해 두어야 하는데 오늘은 날짜를 출력하기 위한 fmt:formatDate를 사용해 본다.

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>


JSP 코드에는 당연히 위의 선언문이 필요하다. 다음은 fmt:formatDate 태그를 이용하여 날짜를 출력해보자.

<c-rt:set var="now" value="<%=new java.util.Date()%>" />

<fmt:formatDate value="${now}" pattern="yyyy-MM-dd hh:mm:ss" />


위와 같은 형태로 formatDate를 사용하면 다음과 같은 형태로 우리가 알기 쉬운 형태로 보이게 된다.

2008-01-28 11:20:49

여기서 한 가지 주의할 점은 보통 자바에서 날짜를 long 타입으로 정의해 놓은 스팩이 많다. 파일의 lastModified 메소드도 리턴형이 long으로 되어 있다. 따라서 만약에 파일의 최종 수정일을 위와 같은 날짜의 형태로 보여주기 위해서는 해당 lastModified 메소드로 리턴되는 long을 아래와 같이 임시 변수에 set 한 후에, 출력해야 한다.

<c-rt:set var="tempDate" value="<%= new java.util.Date(file.lastModified()) %>">




이와 관련된 스팩과 많은 예제를 인터넷에서 찾아볼 수 있다. 대략 정리해 보면 다음과 같다.

JSTL 기초, Part 1: Expression Language (한글) :  http://www.ibm.com/developerworks/kr/library/j-jstl0211.html
JSTL 기초, Part 2: core 분석 (한글) : http://www.ibm.com/developerworks/kr/library/j-jstl0318/
JSTL 기초, Part 4: SQL과 XML 콘텐트에 액세스 하기 (한글) : http://www.ibm.com/developerworks/kr/library/j-jstl0520/
TAG JSTL
Posted by korcslewis
JSTL을 사용하면서 가장 많이 애용되는 태그는 <c:if>와 <c:choose> 인거 같다. 하지만 JSTL의 특성상 쉽게 외워지지 않게 된다. 나한테 약간은 고질적인 면이당^^;; 자주 사용하는게 아니니 할 때마다 찾아보게 된다. 그래서 내 스스로 정리하기로 마음을 먹었다.

일단 <c:if> 태그에 대해서 알아보자.

<%@ taglib uri="/WEB-INF/tld/c.tld" prefix="c" %>

<%-- Simple if conditions --%>
<c:if test='${param.p == "someValue"}'>
객체 param.p 와 someValue의 값이 같으면 이 부분이 출력된다.
</c:if>
<c:if test='${param.p}'>
param.p의 값이 'true'이면 이 부분이 출력된다.
</c:if>
<c:if test='${empty param.p}'>
param.p의 값이 null이면 이 부분이 출력된다.
</c:if> 
<c:if test='${!empty param.p}'>
param.p의 값이 null이 아니면 이 부분이 출력된다.
</c:if>


자바 코드에서 if/else 문의 사용은 누구나 알 수 있다. 하지만 JSTL에서는 if/else의 구문을 <c:choose> 태그를 사용해야 구현이 가능하다. 다음은 그 예제이다.

<%-- A simple if/else condition --%>
<c:choose>
<c:when test='${param.p == "someValue"}'>
param.p와 'someValue'의 값이 같으면 이 부분이 출력된다.
</c:when>
<c:otherwise>
if/else문에서 else에 해당하는 즉, param.p와 'someValue'의 값이 다르면 이 부분이 출력된다.
</c:otherwise>
</c:choose>


다음은 이 보다 조금더 복잡한 다중조건을 이용한 <c:chosse> 태그의 예제이다.

<c:choose>
<c:when test='${param.p == "0"}'>
param.p의 값이 '0'이면 이 부분이 출력된다.
</c:when>
<c:when test='${param.p == "1"}'>
param.p의 값이 '1'이면 이 부분이 출력된다.
</c:when>
<c:otherwise>
param.p이 값이 '0', '1'이 아니면 이 부분이 출력된다. 즉, else의 마지막 구문이다.
</c:otherwise>
</c:choose>


이 뿐만 아니라, <c:out> 태그도 조건에 의한 템플릿 텍스트를 생성하여 출력할 수 있다. 만약 속성값이 null이면, 디폴트 값이 생성된다. 다음은 이에 해당하는 예제이다.

<%-- Default value in an attribute --%>
<c:out value='${param.p}' default="p의 값이 null이면 default로 지정된 이 값이 출력된다." />

<%-- Default value in the body content --%>
<c:out value='${param.p}'>
p의 값이 null이면 이 부분이 출력된다.
</c:out>
TAG JSTL
Posted by korcslewis
서버 운영 중에 Too many open files Exception 이 발생한 경우라면 대부분 동시 접속자가 갑자기 증가한 것에 따른 소켓도 파일 IO로 처리하는 특성 때문에 발생하는 문제이다.
이에 대한 대처 방법으로 다양하게 포스팅 해 둔 블로거들 및 글이 있어 정리해 본다.

BEA 지원 진단 패턴

풍경소리
Too many open files

scarable 님의 여러 포스팅
Posted by korcslewis
최근 웹 표준을 기반으로 한 웹 사이트 기획이나 설계, 구현이 많이 이루어지고 있는 추세이다. 참 다행인 듯 하다.
웹 표준엔 XHTML + CSS + JavaScript를 이용한 프리젠테이션 영역의 이슈를 주로 다루고 있는데, 추가적으로 반드시 다루어야 하는 부분이 Character set 에 대한 표준이다.
Character set에 대한 표준은 단순히 웹 표준에서 뿐 만이 아니라 웹 애플리케이션, 응용 애플리케이션에 이르기까지 개발 전체적인 측면에서 표준으로 다루어야 한다.
그럼면에서 UTF-8을 기반으로 한 개발 표준을 다룰 줄 알아야 하고, 그에 따른 경험이 중요하다고 하겠습니다.

다행히 Java는 UTF-8을 기본으로 지원하기 때문에 구현이나 연동 상에 별다른 문제는 발생하지 않는다. 다만 타 시스템 간에 연동이나 UTF-8을 기본 문자셋으로 설정해 두지 않은(예를들면, Windows 같은) 시스템에서의 팁을 제공하고자 한다.

여기선 타 시스템 간의 연동에 대해서는 다루지 않고, 윈도우 같은 기본 문자셋을 UTF-8을 사용하지 않는 시스템에서의 웹 애플리케이션 구현히 발생할 수 있는 한 가지를 다루고자 한다.

자바는 문자셋을 시스템의 문자셋을 기본으로 VM이 가동되기 때문에 String을 처리할 때는 해당 문자셋 형태로 지원한다. 그래도 데이터베이스 + WAS + 웹 애플케이션을 UTF-8 형태로 맞추어두고 개발하게 된다. 이 때 발생할 수 있는 문제가 서버에서 XML을 리턴한다든지, response로 보내는 것이 HTML이 아닌 별도의 프로토콜에 의한 문자열을 반환할 때가 있다. 대표적인 것이 XML을 응답으로 주는 것이다.

이럴 때, 보통은 Servlet을 이용하여 HTTP Body에 XML을 실어서 보내게 되는데, String 처리까지는 UTF-8을 기반으로 한 코딩이 별도의 설정이나 기법없이 가능하다. 그리고 최종 아래와 같이 XML 문자열을 반환한다.

String xmlData = "뭐라뭐라";

PrintWriter out = response.getWriter();
        
out.println(xmlData);
        
out.flush();
out.close();


이 때, HTTP Response 객체를 이용한 HTTP Header를 셋팅해 주어야 하는데, 해당 문자열의 크기(즉, HTTP Body), Content Type 등을 다음과 같이 지정해 준다.

response.setContentLength(xmlData.getBytes().length);
response.setContentType("application/xml");
response.setCharacterEncoding("utf-8");


Content Length에 해당하는 결과 값으로 주어지는 String의 length가 실제 HTTP Body의 크기가 된다. 혹시나 실수로 xmlData.length() 함수를 사용하여 Content Length를 지정하는 일이 없길 바란다. 이러한 로직의 응답시에는 반드시 String의 lenght가 아니라 String byte의 length를 사용해야 한다.

그런데, 위의 예처럼 xmlData.getBytes().length 를 그대로 이용하여 UTF-8을 기본 문자셋으로 사용하지 않는 시스템에 서버 애플리케이션을 올려두면 한글이 들어간 XML인 경우에는 분명히 사이즈가 다르게 전달된다. 그래서 XML이 정상적으로 클라이언트에 전달되지 않는다.

이럴 때 아래와 같이 명시적으로 String의 byte 문자셋을 UTF-8으로 지정해 주어야 한다.

response.setContentLength(xmlData.getBytes("UTF-8").length);
response.setContentType("application/xml");
response.setCharacterEncoding("utf-8");


그러면, 소스 레벨에서 String의 문자셋을 UTF-8 형태로 byte를 얻어오기 때문에 정상적인 처리가 가능하다.

단순히 웹 사이트나 통일된 환경에서의 처리에는 이와 같은 팁이 유용하지 않치만 타 시스템 간의 연동이나 개발/운영된 환경에서 벗어난 포팅등에서는 유용하게 사용될 만한 팁이라 할 수 있다.
Posted by korcslewis
HTTP Server로 Client와 연동할 때 간혹 구현에 따라서 HTTP Header와 body 사이에 CRLF가 두 개만 있어야 정상인데, 비정상적으로 CRLF가 두 개 이상일 경우가 발생한다.
이럴 때는 다음과 같은 코드를 넣어 두어 CR, LF에 대한 byte는 skip하고 처리해 주면 된다.

  for ( int k=position; k < this.httpBodyBuffer.length; k++ ) {
   StringBuffer startStringTemp = new StringBuffer();
   startTemp = Integer.toHexString(httpBodyBuffer[k] & 0x000000FF);
   startStringTemp.append((startTemp.length() == 1 ? "0"+startTemp : startTemp));
   
   if ( ("0d".equals(""+startStringTemp)) || ("0a".equals(""+startStringTemp)) ) {
    System.out.println("k = " + k);
   } else {
    position = k;
    System.out.println("HTTP BODY Start position : " + position);
    break;
   }
  }
TAG crlf, HTTP, java
Posted by korcslewis
According to TLD or attribute directive in tag file, attribute test does not accept any expression 
JSTL을 이용한 구현시 위와 같은 에러가 발생할 경우가 있다.

OKJSP의 운영자이신 kenu님께서도 동일한 에러가 발생한 경우가 있었나 보다...


그 해답이 다음의 링크에 존재한다^^;;



TAG JSTL
Posted by korcslewis
2009/04/30 16:53

Mastering J2EE Application Development Java EE2009/04/30 16:53

"J2EE 애플리케이션 개발 마스터하기(Mastering J2EE Application Development)" 제목을 연재 형태로 되어 있는 오라클의 문서이다.


늘상 공부할 것에 쌓여 있으니 이것 역시 나에게도 부담 아닌 부담인 것 처럼 느껴지기도 한다.
그래도, 빠른 시간 내에 읽어봐야 할 거 같다.
TAG java, JEE, Oracle
Posted by korcslewis
<c:forEach>를 이용하여 JSP를 개발할 시에 보통은 다음과 같은 용도로 사용을 많이한다.


<c:forEach var="category" items="${categoryList}">
         <c:out value="${category.categoryName}" /></li>
</c:forEach>


이는 Controller 레이어에서 categoryList 라는 이름으로 카테고리 리스트를 넘겨주면 JSP에서 <e:forEach>를 이용하여 위와 같이 출력할 수 있다.


하지만, 다음과 같이 순차적 증가를 위해 사용하기도 한다.


<c:forEach var="min" begin="1" end="10 step="2">
  <option value="<c:out value='${min}' />"><c:out value="${min}" /></option>
</c:forEach>
Posted by korcslewis

Linux 기반은 내게 그리 익숙하지 않은 시스템이었다. 몇 번에 걸쳐서 사용해 본 적은 있지만 설치부터 Java 환경 셋팅 & apache와 Tomcat까지의 연동은 처음인 듯 하다.
그러함에도 그렇게 많은 시간이 할애되지 않은 것이 다행이면 다행이라는 생각이 든다. 몇 년전과 다른 점은 확실히 구글의 검색도움으로 내가 원하고자하는 자료를 쉽게 찾아볼 수 있었다는 것이다. 고맙고 놀랍기도 하고 무서울 수도 있었당^^

RedHat의 설치에 대해서는 다룰 수 없음으로 기본적으로 설치가 되어있다는 가정 하에 Java 환경을 셋팅해 보자. Java Web Application을 개발할 때는 굳이 Apache + Tomcat을 연동할 필요는 없다. 다만 실무에서는 static page에 대해서는 Apache가 처리해 주고, JSP, Servlet과 같은 danamic page에 대해서는 Tomcat이 처리하도록 해 줌으로서 서버 성능상 향상되어질 수 있다. 적은 리소스로 보다 많은 처리를 해 줄수 있는 것이다.

그럼, 먼저 JDK1.6.0_13를 설치해 보자. JDK5의 update가 12까지 진행이 되었다.
http://java.sun.com 로 가서 "Linux self-extracting file" 파일을 다운로드 받으면 된다.

다음은 설치한 Linux의 root 계정으로 실행한다.

[root@wiseant downloads]# chmod 755 jdk-6u13-linux-i586.bin

chmod 명령어의 755는 jdk-6u13-linux-i586.bin 파일을 실행가능한 형태로 파일 속성을 변경해 주는 것이다. jdk-6u13-linux-i586.bin 파일은 RPM 방식으로 자동을 설치해 주는 리눅스 파일 형태이다.

이제 실제로 jdk-6u13-linux-i586.bin 실행하여 설치하면 되는데, 여기서는 /usr/local 디렉토리에 설치하였다. jdk-6u13-linux-i586.bin 파일을 /usr/local 디렉토리로 복사 또는 mv 시킨다. 그리고 다음의 명령을 실행한다.

[root@wiseant local]# ./jdk-6u13-linux-i586.bin

그러면 라이센스에 대한 쭈욱 설명이 나오고 "Do you agree to the above license terms? [yes or no]"가 마지막으로 동의 여부를 물어본다.이때 "y"라고 입력하면 자동으로 /usr/local/jdk1.6.0_13 디렉토리 아래에 JDK를 설치한다.

다음은 윈도우 환경에서 CLASSPATH와 JAVA_HOME 셋팅을 하는 것과 같이 JAVA path를 셋팅해 주어야 한다.

vi로 /etc/profile 파일을 열어준다.

[root@wiseant etc]# vi /etc/profile

profile 파일의 가장 아래에 다음을 입력해 준다.

JAVA_HOME=/usr/local/jdk1.6.0_13
export JAVA_HOME
PATH=$PATH:$JAVA_HOME/bin

profile 파일을 저장하고 빠져나온다(:wq!). 이제 시스템에 반영하기 위해서 source 명령어로 profile을 실행한다.

[root@wiseant etc]# source /etc/profile

정상적으로 path가 설정이 되었는지 java -version 명령어로 테스트해 본다.

[root@wiseant etc]# java -version
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)

위와 같이 나와야 정상적으로 설치된 것이다.

만약 위와 같이 "/etc/profile" 에서 JAVA_HOME을 셋팅해 주고 path를 셋팅해 주었지만, 정상적으로 실행되지 않을 때가 있다.
그럴 때는 다음과 같이 해 준다.

[root@wiseant etc]# update-alternatives --install "/usr/bin/java" "java" "/usr/local/jdk1.6.0_13/bin/java" 1
[root@wiseant etc]# update-alternatives --config java

선택을 해야 하는 경우 /usr/local/jdk1.6.0_13/bin/java" 항목을 선택해 준다. 기존의 Redhat 설치시 Java가 설치된 경우이면 SUN Java SDK는 2번이다.


다음은 Apache와 Tomcat을 설치해 보자. 둘 다 http://www.apache.org 에서 다운로드 받을 수 있다. 여기서 주의 할 점은 apache는 linux 소스 버전으로 다운로드 받아야 한다는 것이다.

다운로드를 받으면 각각 다음과 같은 파일명을 가진다.

Apache : httpd-2.2.11.tar.gz
Tomcat : apache-tomcat-6.0.18.tar.gz

둘 다 tar 형태임으로 tar 명령어로 압축을 풀 수 있다.

그리고 한 가지더 tomcat_connector를 다운로드 받아야 한다. 역시 http://www.apache.org 에서 다운로드 받을 수 있다. mod_jk 에 해당하는 Apache + Tomcat 연동 라이브러리이다.

Tomcat-Connector : tomcat-connectors-1.2.28-src.tar.gz

먼저 Apache를 설치해 보자. 다운로드 받은 "httpd-2.2.11.tar.gz" 파일을 풀어주면 " httpd-2.2.11" 디렉토리가 생성되어진다.

소스를 컴파일 하기 전에 configure를 통해서 Apache의 설치환경을 셋팅할 수 있다. Apache는 다음의 옵션 뿐만 아니라 다양한 환경으로 셋팅이 가능하도록 할 수 있는데, 여기에 대해서는 다른 많은 문서를 참조하기 바란다.
[root@wiseant httpd-2.2.11]./configure --prefix=/usr/local/apache-2.2.11 --enable-suexec --enable-so --with-suexec-caller=bin --enable-ssl --with-ssl=/usr/local/ssl --enable-cache --enable-ext-filter --with-z=/usr/include --enable-dav --enable-mods-shared=all --enable-module=rewrite
configure 명령어의 --prefix 옵션으로 /usr/local/apache2.2.11 디렉토리에 Apache를 설치하겠다는 뜻이다.
그 외에는 openssl 을 사용하는 등의 옵션이다. 별도의 configure 옵션 자료를 참고해야 한다.

다음은 컴파일 해 준다.
[root@wiseant httpd-2.2.11]make

다음은 설치해 준다.
[root@wiseant httpd-2.2.11]make install

이제 Apache의 설치는 끝났다. 설치한 apache2.2.11/bin 디렉토리로 이동하고 다음과 같이 apache를 실행시켜보자.

[root@wiseant build]# cd /usr/local/apache2.2.11/bin/
[root@wiseant bin]# ls -al
합계 3088
drwxr-xr-x    2 root     root         4096  6월 21 11:02 .
drwxr-xr-x   15 root     root         4096  6월 21 11:02 ..
-rwxr-xr-x    1 root     root        92434  6월 21 11:02 ab
-rwxr-xr-x    1 root     root         3443  6월 21 10:57 apachectl
-rwxr-xr-x    1 root     root         7029  6월 21 11:02 apr-1-config
-rwxr-xr-x    1 root     root         5831  6월 21 11:02 apu-1-config
-rwxr-xr-x    1 root     root        22602  6월 21 10:57 apxs
-rwxr-xr-x    1 root     root        38057  6월 21 11:02 checkgid
-rwxr-xr-x    1 root     root         8876  6월 21 10:57 dbmmanage
-rw-r--r--    1 root     root          983  6월 21 10:57 envvars
-rw-r--r--    1 root     root          983  6월 21 10:57 envvars-std
-rwxr-xr-x    1 root     root        61060  6월 21 11:02 htcacheclean
-rwxr-xr-x    1 root     root        53131  6월 21 11:02 htdbm
-rwxr-xr-x    1 root     root        39414  6월 21 11:02 htdigest
-rwxr-xr-x    1 root     root        50543  6월 21 11:02 htpasswd
-rwxr-xr-x    1 root     root      2599969  6월 21 11:02 httpd
-rwxr-xr-x    1 root     root        39105  6월 21 11:02 httxt2dbm
-rwxr-xr-x    1 root     root        39548  6월 21 11:02 logresolve
-rwxr-xr-x    1 root     root        39973  6월 21 11:02 rotatelogs
[root@wiseant bin]# ./apachectl start

정상적으로 구동이 되었으면 http://linux-ip 라고 입력하면 Apache 첫 화면이 나와야 한다. 별다른 어려움은 없을 것이다.


다음은 Tomcat을 설치해 보자. Tomcat의 설치는 소스를 컴파일 하지 않아도 됨으로 더욱 간단하다.
다운로드받은 "apache-tomcat-6.0.18.tar.gz" 파일을 /usr/local 디렉토리 풀어준다.

[root@wiseant local]# tar -xvf apache-tomcat-6.0.18.tar

그러면, /usr/local/apache-tomcat-6.0.18 디렉토리로 Tomcat이 설치된 것이다.

실행은 간단하다. /usr/local/apache-tomcat-6.0.18/bin 디렉토리로 이동하여 다음의 명령어를 실행한다.

[root@wiseant bin]# ./startup.sh
Using CATALINA_BASE:   /usr/local/apache-tomcat-6.0.18
Using CATALINA_HOME:   /usr/local/apache-tomcat-6.0.18
Using CATALINA_TMPDIR: /usr/local/apache-tomcat-6.0.18/temp
Using JRE_HOME:       /usr/local/jdk1.5.0_12

에러메시지가 뜨지 않으면 정상적으로 동작한 것이다.

http://linux-ip:8080 주소로 브라우저를 실행시켜보자. Tomcat 첫 화면이 나오면 성공적으로 Tomcat을 설치한 것이다.


이제 끝으로, Tomcat-connector를 이용하여 Apache와 Tomcat을 연동해 보자. 대부분 여기서 가장 시간이 많이 소비할 것이다. 나도 마찬가지였다.

먼저, Apache와 Tomcat의 서비스를 종료하자.

Tomcat 종료 : [root@wiseant bin]# /usr/local/apache-tomcat-6.0.18/bin/shutdown.sh
Apache 종료 : [root@wiseant bin]# /usr/local/apache-2.2.11/bin/apachectl stop

다운로드 받은 "tomcat-connectors-1.2.28-src.tar" 압축을 풀어준다.

[root@wiseant bin]# tar -xvf tomcat-connectors-1.2.28-src.tar

그러면 tomcat-connectors-1.2.28-src 디렉토리가 생성되는데, tomcat-connectors-1.2.28-src 디렉토리의 native 디렉토리로 이동한다.

다음은 소스를 컴파일 해야 함으로 configure를 실행한다. 옵션으로 설치된 Apache의 경로를 지정해 준다.

[root@wiseant native]# ./configure --with-apxs=/usr/local/apache-2.2.11/bin/apxs

make와 make install를 실행한다.

[root@wiseant native]# make
[root@wiseant native]# make install

정상적으로 설치되었다면 /usr/local/apache2.2.11/modules 디렉토리에 "mod_jk.so" 파일이 생성되어져 있다. .so 파일은 윈도우의 dll과 같은 역할을 해 준다.

다음은 설치된 Tomcat-Connector를 이용한 Apache + Tomcat의 실제 연동을 위한 설정 파일들의 예이다.
먼저, 설치된 Apache 디렉토리의 conf 디렉토리에 workers.properties 파일를 만들어준다.

workers.properties 파일에 다음의 항목들을 셋팅해 준다.

workers.tomcat_home=/usr/local/apache-tomcat-6.0.18
workers.java_home=/usr/local/jdk1.6.0_13
ps=/
worker.list=default
worker.ajp13.port=8009
worker.ajp13.host=wiseant.net
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=ajp13
worker.inprocess.type=jni
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)tomcat.jar
worker.inprocess.cmd_line=start
worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll
worker.inprocess.stdout=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stdout
worker.inprocess.stderr=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stderr

중요한 것은 worker.inprocess.type=jni 이전까지 임으로 각자의 환경에 맞게 셋팅해 준다.


다음은 /usr/local/apache-2.2.11/conf 디렉토리에 있는 httpd.conf 파일의 가장 아래쪽에 다음을 추가해 준다.

LoadModule jk_module modules/mod_jk.so

JkWorkersFile "conf/workers.properties"
JkLogFile "logs/mod_jk.log"
JkLogLevel info
JkMount /examples/jsp default
JkMount /examples/jsp/* default


httpd.conf 파일을 저장한다(:wq!). 이제 Tomcat-Connector를 이용한 Apache + Tomcat의 연동의 셋팅도 마무리한 것이다.
이것으로 apache는 80 포트를 이용한 web server로 실행되고 Tomcat은 8080로 구동하는 JSP Container로 실행하게 된다.
Tomcat + Apache을 실행하여 테스트 해 보자.

Tomcat 실행 : [root@wiseant bin]# /usr/local/apache-tomcat-6.0.18/bin/startup.sh
Apache 실행 : [root@wiseant bin]# /usr/local/apache-2.2.11/bin/apachectl start

두 프로세스가 정상적으로 구동되었으면 브라우저에서 다음의 주소를 실행시켜보자.
"http://linux-ip/examples/jsp" 라는 URL로 접근했을 때 Tomcat의 jsp-examples 가 실행되어야 한다.

이것으로 RedHat9.0에서 JDK, Apache+Tomcat의 연동은 모두 끝난 것이다.
참고로 mod_jk를 이용한 Apache와 Tomcat의 연동은 여기서 제시한 방법외에도 다양한 자료가 존재한다.
따라서 여러가지 경로로 다양하게 접근해 보는 것도 좋은 방법이라 생각된다.

Posted by korcslewis