דוגמה ל-JNDI של מקור נתונים Tomcat ב-Java

ברוך הבא למדריך לדוגמה של Tomcat DataSource JNDI. בקורס הקודם חקרנו את JDBC DataSource ולמדנו איך להשתמש בו ביישום ג'אווה סטנדלון.

Tomcat DataSource JNDI

היתרון האמיתי של DataSource בא לידי ביטוי כאשר אנו משתמשים בו יחד עם JNDI Context, לדוגמה, בבריכת חיבורים ביישום אינטרנטי המוטמע בתוך תכנית סרבלט. רוב הסרבלט קונטיינרים הפופולריים מספקים תמיכה מובנית עבור DataSource דרך הגדרת משאבים והקשר JNDI. זה עוזר לנו ליצור ולהשתמש בבריכת חיבורים של DataSource עם כמה שורות של תצורה בלבד. מדובר בדוגמה להגדרת Tomcat DataSource JNDI. Apache Tomcat מספק שלושה דרכים להגדיר DataSource בהקשר JNDI.

  1. התקשורת context.xml – זהו הדרך הקלה ביותר להגדיר DataSource, כל שאנו צריכים הוא קובץ context.xml בתיקייה META-INF. עלינו להגדיר אלמנט משאב בקובץ ההקשר, והמכשיר יתעסק בטעינה ובהגדרתו. הגישה פשוטה אך יש לה חסרונות מסוימים;
    • מכיוון שקובץ ההקשר מסופק יחד עם קובץ ה-WAR, עלינו לבנות ולהשיק מחדש את ה-WAR לכל שינוי קטן בתצורה. אותו בעיה מתקיימת אם היישום שלך פועל בסביבה מבוזרת או אם יישום שלך צריך להיות פורסם בסביבות בדיקה שונות כמו QA, IT, PROD וכו'.
    • המקור לנתונים נוצר על ידי המכשיר עבור שימוש ביישום בלבד, ולכן אין אפשרות להשתמש בו באופן גלובלי. לא ניתן לשתף את המקור לנתונים בין מספר יישומים.
    • אם יש מקור גלובלי (ב-server.xml) הוגדר עם אותו שם, המקור לנתונים של היישום מתעלם.
  2. קובץ server context.xml – אם ישנם מספר יישומים בשרת וברצונך לשתף מקור נתונים ביניהם, ניתן להגדיר זאת בקובץ ה- server context.xml. קובץ זה ממוקם בתיקייה apache-tomcat/conf. טווח פעולתו של קובץ ה- server context.xml הוא בתיקיית היישום, לכן אם תגדיר מאגר חיבורי נתונים עם 100 חיבורים וישנן 20 יישומים, אזי המקור ייווצר עבור כל אחד מהיישומים. כך נקבל 2000 חיבורים שיבלעו בוודאי את כל משאבי שרת המסד נתונים ויפגעו בביצועי היישום.
  3. server.xml ו- context.xml – ניתן להגדיר מקור נתונים ברמה גלובלית על ידי הגדרתם באלמנט GlobalNamingResources בקובץ server.xml. אם נעשה שימוש בשיטה זו, יש להגדיר ResourceLink מקובץ context.xml של השרת או היישום. זו הדרך המועדפת כאשר תרצה לשתף מקור משותף בין מספר יישומים הרצים על השרת. לגבי ResourceLink, האם להגדיר אותו בקובץ ה- context.xml של השרת או ברמת היישום, תלוי בדרישותיך.

בוא נעבור לדוגמת JNDI של מקור נתונים ב- Tomcat ביישום אינטרנטי של ג'אווה. להגדרת נתוני המבחן, נא לעיין במאמר האחרון שלי אודות דוגמא ל- JDBC DataSource.

דוגמת תצורת JNDI DataSource של Tomcat – server.xml

הוסף את הקוד הבא בקובץ server.xml של Tomcat. הקוד צריך להיתקע בתוך אלמנט GlobalNamingResources. ודא שמנהג ה־driver של מסד הנתונים קיים בתיקיית ה־lib של Tomcat, כך שבמקרה זה צריך להיות jar של mysql jdbc בתיקיית ה־lib של Tomcat.

<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.

הוסף את הקוד הבא בקובץ context.xml של השרת.

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

שים לב ששם הקישור למשאב זה שונה מהקישור הגלובלי, עלינו להשתמש בשם זה בתוכנית ה־Java שלנו כדי לקבל את ה־DataSource.

דוגמת Tomcat DataSource 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("

Employee Details

"); out.print(""); out.print(""); out.print(""); while(rs.next()) { out.print(""); out.print(""); out.print(""); out.print(""); } out.print("
Employee IDEmployee Name
" + rs.getInt("empid") + "" + rs.getString("name") + "

"); // בואו נדפיס מידע על מסד הנתונים out.print("

Database Details

"); out.print("Database Product: "+con.getMetaData().getDatabaseProductName()+"
"); out.print("Database Driver: "+con.getMetaData().getDriverName()); out.print(""); }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 based configuration וזה יעבוד ב-Tomcat 7 או גרסאות גבוהות יותר. אם אתה משתמש בגרסה נמוכה יותר של Tomcat אז עליך לבצע מספר שינויים בקוד הסרבל, להסרת ההערה WebServlet ולתצורה בקובץ web.xml. חלק מקוד הסרבל שאנו מעוניינים בו;

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

זהו הדרך לקבלת המשאבים שנגדירנו לשימוש באפליקציה. יכולנו לכתוב זאת גם בדרך זו;

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

I am also printing some database information to check which database we are connected. Now when you will run the application, you will see following output. Let’s see how easy it is to switch the database server because we are using Tomcat DataSource. All you need is to change the Database properties. So if we have to switch to Oracle database, my Resource configuration will look like below.

<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"/>

וכאשר אנו מאתחלים את השרת ומפעילים את האפליקציה, היא תתחבר למסד נתונים של Oracle ותפיק את התוצאה הבאה. זהו הכל לדוגמת הגדרת Tomcat DataSource JNDI, תוכל להגדיר את המשאב בדרך דומה בקבצי context.xml גם.

Source:
https://www.digitalocean.com/community/tutorials/tomcat-datasource-jndi-example-java