Поиск по сайту:

Пример Tomcat DataSource JNDI на Java


Добро пожаловать в учебник Tomcat DataSource JNDI. Мы рассмотрели JDBC DataSource в последнем руководстве и узнали, как использовать его в автономном Java-приложении.

Источник данных Tomcat JNDI

  1. Application context.xml. Это самый простой способ настроить источник данных. Все, что нам нужно, — это файл context.xml в каталоге META-INF. Мы должны определить элемент Resource в файле контекста, а контейнер позаботится о его загрузке и настройке. Подход прост, но имеет некоторые недостатки;
    • Поскольку файл контекста связан с файлом WAR, нам необходимо создавать и развертывать новый файл WAR для каждого небольшого изменения конфигурации. Та же проблема возникает, если ваше приложение работает в распределенной среде или ваше приложение необходимо развернуть в разных средах тестирования, таких как QA, IT, PROD и т. д.
    • Источник данных создается контейнером только для использования приложением, поэтому его нельзя использовать глобально. Мы не можем использовать источник данных в нескольких приложениях.
    • Если существует глобальный источник данных (server.xml), определенный с таким же именем, источник данных приложения игнорируется.
  2. Server context.xml. Если на сервере есть несколько приложений и вы хотите использовать для них общий источник данных, мы можем указать это в файле server context.xml. Этот файл находится в каталоге apache-tomcat/conf. Областью действия файла server context.xml является приложение, поэтому, если вы определяете пул соединений DataSource из 100 соединений и существует 20 приложений, источник данных будет создан для каждого приложения. Это приведет к 2000 подключениям, которые, очевидно, будут потреблять все ресурсы сервера базы данных и снижать производительность приложений.
  3. server.xml и context.xml. Мы можем определить DataSource на глобальном уровне, определив их в элементе server.xml GlobalNamingResources. Если мы используем этот подход, нам нужно определить ResourceLink из файла context.xml для конкретного сервера или приложения. Это предпочтительный способ, когда вы хотите использовать общий пул ресурсов для нескольких приложений, работающих на сервере. Что касается ссылки на ресурс, следует ли определить ее на уровне сервера в контекстном XML-файле или на уровне приложения, зависит от ваших требований.

Давайте перейдем к примеру Tomcat DataSource JNDI в веб-приложении Java. Для настройки тестовых данных обратитесь к моей последней статье о примере JDBC DataSource.

Пример конфигурации Tomcat DataSource 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"/>

Здесь мы создаем контекст JNDI с именем jdbc/MyDB, который является типом DataSource. Мы передаем конфигурации базы данных в URL, имени пользователя, пароле и атрибуте driverClassName. Свойства пула соединений определяются в атрибутах maxActive, maxIdle и minIdle.

Конфигурация ссылки ресурса JNDI Tomcat DataSource — context.xml

Добавьте приведенный ниже код в файл server context.xml.

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

Обратите внимание, что имя ссылки на ресурс отличается от глобальной ссылки, мы должны использовать это имя в нашей java-программе, чтобы получить DataSource.

Пример JNDI источника данных Tomcat

Создайте динамическое веб-приложение с именем 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, и она будет работать в 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"/>