مرحبًا بك في درس مثال Tomcat لـ Spring DataSource JNDI. في وقت سابق، رأينا كيفية تنفيذ عمليات قاعدة البيانات باستخدام Spring JDBC integration. ومع ذلك، في معظم الأحيان، يتم نشر تطبيقات المؤسسات في حاوية خدمة السيرفلت مثل Tomcat، JBoss إلخ.
Spring DataSource
نعلم أن DataSource مع JNDI هو الطريقة المفضلة لتحقيق تجميع الاتصالات والاستفادة من تنفيذات الحاوية. اليوم، سنلقي نظرة على كيفية تكوين تطبيق ويب Spring لاستخدام اتصالات JNDI المقدمة من Tomcat. في مثالي، سأستخدم خادم قاعدة بيانات MySQL وأقوم بإنشاء جدول بسيط مع بعض الصفوف. سنقوم بإنشاء خدمة ويب ريست في Spring ستقوم بإرجاع استجابة JSON مع قائمة بجميع البيانات في الجدول.
إعداد قاعدة البيانات
CREATE TABLE `Employee` (
`id` int(11) unsigned NOT NULL,
`name` varchar(20) DEFAULT NULL,
`role` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Employee` (`id`, `name`, `role`)
VALUES
(1, 'Pankaj', 'CEO'),
(2, 'David', 'Manager');
commit;
مشروع مصدر بيانات Spring MVC
أنشئ مشروع Spring MVC في برنامج Spring Tool Suite حتى يكون رمز هيكل تطبيقنا الربيع جاهزًا. عند الانتهاء من التنفيذ، ستكون هيكلة المشروع كما هو موضح في الصورة أدناه.
تبعيات Spring JDBC و Jackson
سنحتاج إلى إضافة Spring JDBC و Jackson وسائق قاعدة بيانات MySQL كتبعيات في ملف pom.xml. يبدو ملف pom.xml النهائي الخاص بي كما هو موضح أدناه.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.spring</groupId>
<artifactId>SpringDataSource</artifactId>
<name>SpringDataSource</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.0.2.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
<jackson.databind-version>2.2.3</jackson.databind-version>
</properties>
<dependencies>
<!-- Spring JDBC Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind-version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
إذا لم تكن على دراية بـ Rest في Spring، يرجى قراءة مثال على خدمة ويب راحة Spring.
فئة النموذج
جسم موظفنا الذي يتم تصميمه على غرار جدول الموظفين يظهر كما هو موضح أدناه.
package com.journaldev.spring.jdbc.model;
import java.io.Serializable;
public class Employee implements Serializable{
private static final long serialVersionUID = -7788619177798333712L;
private int id;
private String name;
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
فئة تحكم الربيع
تبدو فئتنا التحكمية البسيطة كما يلي.
package com.journaldev.spring.jdbc.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.journaldev.spring.jdbc.model.Employee;
/**
* Handles requests for the Employee JDBC Service.
*/
@Controller
public class EmployeeController {
private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
@Autowired
@Qualifier("dbDataSource")
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
@RequestMapping(value = "/rest/emps", method = RequestMethod.GET)
public @ResponseBody List getAllEmployees() {
logger.info("Start getAllEmployees.");
List empList = new ArrayList();
//الشفرة JDBC - البداية
String query = "select id, name, role from Employee";
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List
النقاط المهمة حول فئة التحكم هي:
- سيتم ربط مصدر البيانات بتكوين Spring Bean بالاسم dbDataSource.
- نحن نستخدم JdbcTemplate لتجنب الأخطاء الشائعة مثل تسرب الموارد وإزالة شفرة JDBC المكررة.
- سيكون عنوان URI لاسترداد قائمة الموظفين هو https://{host}:{port}/SpringDataSource/rest/emps
- نحن نستخدم @ResponseBody لإرسال قائمة كائنات الموظفين كاستجابة، سيعتني الربيع بتحويلها إلى JSON.
تكوين فاصل الربيع
هناك طريقتان يمكننا من خلالهما البحث في JNDI وربطها بمصدر بيانات التحكم، يحتوي ملف تكوين فاصلي الربيع لدي على كلاهما ولكن أحدهما معلق. يمكنك التبديل بين هذين والاستجابة ستكون نفسها.
- استخدام علامة jee namespace لأداء البحث في JNDI وتكوينها كـ Spring Bean. نحتاج أيضًا إلى تضمين علامة jee namespace وتعريف المخطط في هذه الحالة.
- إنشاء فولة من النوع
org.springframework.jndi.JndiObjectFactoryBean
عن طريق تمرير اسم سياق JNDI. jndiName هو معلمة مطلوبة لهذا التكوين.
يبدو ملف تكوين فولة الربيع لدي مظهرًا مشابهًا للتالي.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:jee="https://www.springframework.org/schema/jee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/jee https://www.springframework.org/schema/jee/spring-jee.xsd
https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- Configure to plugin JSON as request and response in method handler -->
<beans:bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<beans:property name="messageConverters">
<beans:list>
<beans:ref bean="jsonMessageConverter" />
</beans:list>
</beans:property>
</beans:bean>
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</beans:bean>
<!-- Create DataSource Bean -->
<beans:bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
</beans:bean>
<!-- using JEE namespace for lookup -->
<!--
<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/MyLocalDB"
expected-type="javax.sql.DataSource" />
-->
<context:component-scan base-package="com.journaldev.spring.jdbc.controller" />
</beans:beans>
تكوين JNDI لمصدر بيانات Tomcat
الآن بعد أن انتهينا من مشروعنا، الجزء النهائي هو إعداد تكوين JNDI في حاوية Tomcat لإنشاء مورد JNDI.
<Resource name="jdbc/TestDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/TestDB"
username="pankaj"
password="pankaj123"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
أضف التكوين أعلاه في قسم GlobalNamingResources من ملف server.xml.
<ResourceLink name="jdbc/MyLocalDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" />
نحتاج أيضًا إلى إنشاء رابط المورد لاستخدام تكوين JNDI في تطبيقنا، الطريقة الأفضل لإضافته هي في ملف context.xml للخادم. لاحظ أن اسم ResourceLink يجب أن يتطابق مع اسم السياق JNDI الذي نستخدمه في تطبيقنا. تأكد أيضًا من وجود ملف MySQL jar في دليل lib الخاص بـ tomcat، خلاف ذلك لن يتمكن tomcat من إنشاء حوض تجمع قاعدة بيانات MySQL.
تشغيل مشروع عينة Spring DataSource JNDI
مشروعنا وتكوين الخادم تم الانتهاء منه، ونحن جاهزون لاختباره. قم بتصدير المشروع كملف WAR وضعه في دليل نشر تومكات. تظهر الاستجابة JSON للمكالمة الراحلة في الصورة أدناه. هذا كل شيء بالنسبة للتكامل مع سبرينغ وسائل الحاويات سيرفلت كونتيكست، قم بتنزيل المشروع المثالي من الرابط أدناه وقم بتجربته لمعرفة المزيد.
Source:
https://www.digitalocean.com/community/tutorials/spring-datasource-jndi-with-tomcat-example