웹사이트 검색

Java의 Tomcat DataSource JNDI 예제


Tomcat DataSource JNDI 예제 자습서에 오신 것을 환영합니다. 지난 튜토리얼에서 JDBC DataSource를 살펴보고 독립 실행형 Java 애플리케이션에서 사용하는 방법을 배웠습니다.

Tomcat 데이터 소스 JNDI

  1. Application context.xml - 이것은 DataSource를 구성하는 가장 쉬운 방법이며 META-INF 디렉토리에 있는 context.xml 파일만 있으면 됩니다. 컨텍스트 파일에 Resource 요소를 정의해야 하며 컨테이너가 로드 및 구성을 처리합니다. 접근 방식은 간단하지만 몇 가지 단점이 있습니다.\n
    • 컨텍스트 파일이 WAR 파일과 함께 번들로 제공되기 때문에 모든 작은 구성 변경에 대해 새 WAR을 빌드하고 배포해야 합니다. 응용 프로그램이 분산 환경에서 작동하거나 응용 프로그램을 QA, IT, PROD 등과 같은 다른 테스트 환경에 배포해야 하는 경우에도 동일한 문제가 발생합니다.
    • 데이터 소스는 애플리케이션 용도로만 컨테이너에서 생성되므로 전역적으로 사용할 수 없습니다. 여러 애플리케이션에서 데이터 소스를 공유할 수 없습니다.
    • 동일한 이름으로 정의된 전역 데이터 소스(server.xml)가 있는 경우 애플리케이션 데이터 소스는 무시됩니다.
  2. Server context.xml - 서버에 여러 애플리케이션이 있고 이들 간에 DataSource를 공유하려는 경우 서버 context.xml 파일에서 정의할 수 있습니다. 이 파일은 apache-tomcat/conf 디렉토리에 있습니다. 서버 context.xml 파일의 범위는 응용 프로그램이므로 100개의 연결로 DataSource 연결 풀을 정의하고 20개의 응용 프로그램이 있는 경우 각 응용 프로그램에 대해 데이터 소스가 생성됩니다. 이로 인해 분명히 모든 데이터베이스 서버 리소스를 소비하고 애플리케이션 성능을 저하시키는 2000개의 연결이 생성됩니다.
  3. server.xml 및 context.xml - server.xml GlobalNamingResources 요소에서 DataSource를 정의하여 전역 수준에서 DataSource를 정의할 수 있습니다. 이 접근 방식을 사용하는 경우 서버 또는 애플리케이션별 context.xml 파일에서 ResourceLink를 정의해야 합니다. 이는 서버에서 실행 중인 여러 응용 프로그램 간에 공통 리소스 풀을 공유하려는 경우 선호되는 방법입니다. 리소스 링크와 관련하여 서버 수준 컨텍스트 xml 파일 또는 응용 프로그램 수준에서 정의할지 여부는 요구 사항에 따라 다릅니다.

Java 웹 애플리케이션의 Tomcat DataSource JNDI 예제로 넘어가겠습니다. 테스트 데이터 설정에 대해서는 JDBC DataSource 예제에 대한 지난 기사를 참조하십시오.

Tomcat 데이터 소스 JNDI 구성 예 - server.xml

tomcat server.xml 파일에 아래 코드를 추가합니다. 코드는 GlobalNamingResources 요소에 추가되어야 합니다. 또한 데이터베이스 드라이버가 tomcat lib 디렉토리에 있는지 확인하십시오. 따라서 이 경우 mysql jdbc jar가 tomcat lib에 있어야 합니다.

<Resource name="jdbc/MyDB" 
      global="jdbc/MyDB" 
      auth="Container" 
      type="javax.sql.DataSource" 
      driverClassName="com.mysql.jdbc.Driver" 
      url="jdbc:mysql://localhost:3306/UserDB" 
      username="pankaj" 
      password="pankaj123" 
      
      maxActive="100" 
      maxIdle="20" 
      minIdle="5" 
      maxWait="10000"/>

여기에서는 DataSource의 일종인 jdbc/MyDB라는 이름으로 JNDI 컨텍스트를 생성하고 있습니다. URL, 사용자 이름, 비밀번호 및 driverClassName 속성에 데이터베이스 구성을 전달하고 있습니다. 연결 풀링 속성은 maxActive, maxIdle 및 minIdle 속성에서 정의됩니다.

Tomcat 데이터 소스 JNDI 리소스 링크 구성 - context.xml

서버 context.xml 파일에 아래 코드를 추가합니다.

<ResourceLink name="jdbc/MyLocalDB"
                global="jdbc/MyDB"
                auth="Container"
                type="javax.sql.DataSource" />

리소스 링크 이름은 전역 링크와 다르며 DataSource를 가져오려면 Java 프로그램에서 이 이름을 사용해야 합니다.

Tomcat 데이터 소스 JNDI 예제

이름이 JDBCDataSourceTomcat인 동적 웹 애플리케이션을 생성한 다음 아래 코드로 서블릿을 생성합니다.

package com.journaldev.jdbc.datasource;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

@WebServlet("/JDBCDataSourceExample")
public class JDBCDataSourceExample extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Context ctx = null;
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try{
			ctx = new InitialContext();
			DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
			
			con = ds.getConnection();
			stmt = con.createStatement();
			
			rs = stmt.executeQuery("select empid, name from Employee");
			
			PrintWriter out = response.getWriter();
            response.setContentType("text/html");
            out.print("<html><body><h2>Employee Details</h2>");
            out.print("<table border=\"1\" cellspacing=10 cellpadding=5>");
            out.print("<th>Employee ID</th>");
            out.print("<th>Employee Name</th>");
            
            while(rs.next())
            {
                out.print("<tr>");
                out.print("<td>" + rs.getInt("empid") + "</td>");
                out.print("<td>" + rs.getString("name") + "</td>");
                out.print("</tr>");
            }
            out.print("</table></body><br/>");
            
            //lets print some DB information
            out.print("<h3>Database Details</h3>");
            out.print("Database Product: "+con.getMetaData().getDatabaseProductName()+"<br/>");
            out.print("Database Driver: "+con.getMetaData().getDriverName());
            out.print("</html>");
            
		}catch(NamingException e){
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				rs.close();
				stmt.close();
				con.close();
				ctx.close();
			} catch (SQLException e) {
				System.out.println("Exception in closing DB resources");
			} catch (NamingException e) {
				System.out.println("Exception in closing Context");
			}
			
		}
	}

}

Servlet 3 Annotation 기반 구성을 사용하고 있으며 Tomcat 7 이상 버전에서 작동합니다. 낮은 버전의 Tomcat을 사용하는 경우 WebServlet 주석을 제거하고 web.xml 파일에서 구성하려면 서블릿 코드를 약간 수정해야 합니다. 관심 있는 서블릿 코드 부분

ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");

이는 애플리케이션에서 사용하도록 정의된 JNDI 리소스를 가져오는 방법입니다. 이런 식으로도 작성할 수 있었습니다.

ctx = new InitialContext();
Context initCtx  = (Context) ctx.lookup("java:/comp/env");
DataSource ds = (DataSource) initCtx.lookup("jdbc/MyLocalDB");
<Resource name="jdbc/MyDB" 
      global="jdbc/MyDB" 
      auth="Container" 
      type="javax.sql.DataSource" 
      driverClassName="oracle.jdbc.driver.OracleDriver" 
      url="jdbc:oracle:thin:@localhost:1521:orcl" 
      username="hr" 
      password="oracle" 
      
      maxActive="100" 
      maxIdle="20" 
      minIdle="5" 
      maxWait="10000"/>