Tutorials  /  Security

Spring DataSource JNDI Tomcat: Ein Leitfaden

Ccentron Redaktion · Januar 2024 ·5 Min. Lesezeit ·Security, Tutorial

Zuvor haben wir gesehen, wie Datenbankoperationen mit Spring JDBC-Integration implementiert werden. Aber meistens werden Unternehmensanwendungen in einem Servlet-Container wie Tomcat, JBoss usw. bereitgestellt.

Spring DataSource JNDI Tomcat

Wir wissen, dass DataSource mit JNDI der bevorzugte Weg ist, um Connection Pooling zu erreichen und Vorteile von Container-Implementierungen zu nutzen. Heute werden wir uns anschauen, wie wir eine Spring-Webanwendung konfigurieren können, um JNDI-Verbindungen zu nutzen, die von Tomcat bereitgestellt werden. Für mein Beispiel werde ich den MySQL-Datenbankserver verwenden und eine einfache Tabelle mit einigen Zeilen erstellen. Wir werden einen Spring Rest-Webservice erstellen, der die JSON-Antwort mit einer Liste aller Daten in der Tabelle zurückgibt.

SEC

Passende Infrastruktur bei centron

Absicherung endet nicht beim Server: Cloud Firewalls filtern den Datenverkehr vor der VM – zentral verwaltet, ohne Aufpreis je Regel. Cloud Firewalls ansehen →

Datenbank-Setup

SQL
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 DataSource MVC-Projekt

Erstellen Sie ein Spring MVC-Projekt in der Spring Tool Suite, sodass unser Spring-Anwendungsskelett bereit ist. Sobald wir mit unserer Implementierung fertig sind, wird die Struktur unseres Projekts wie im folgenden Bild aussehen.

Spring JDBC und Jackson-Abhängigkeiten

Wir müssen Spring JDBC, Jackson und den MySQL-Datenbanktreiber als Abhängigkeiten in der pom.xml-Datei hinzufügen. Meine endgültige pom.xml-Datei sieht wie folgt aus.

Code
<?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 Unterstützung -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        
        <!-- MySQL Treiber -->
        <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>
                <!-- Ausschluss von Commons Logging zu Gunsten von 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>

Wenn Sie nicht mit Rest in Spring vertraut sind, lesen Sie bitte Spring Restful Webservice Beispiel.

Model-Klasse

Unsere Employee-Bean, die nach der Employee-Tabelle modelliert ist, sieht wie folgt aus.

Go
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;
    }
    
}

Spring Controller-Klasse

Unsere einfache Controller-Klasse sieht wie folgt aus.

Go
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 Code - Start
        String query = "select id, name, role from Employee";
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        List<Map<String,Object>> empRows = jdbcTemplate.queryForList(query);
        
        for(Map<String,Object> empRow : empRows){
            Employee emp = new Employee();
            emp.setId(Integer.parseInt(String.valueOf(empRow.get("id"))));
            emp.setName(String.valueOf(empRow.get("name")));
            emp.setRole(String.valueOf(empRow.get("role")));
            empList.add(emp);
        }
        
        return empList;
    }

}

Wichtige Punkte über die Controller-Klasse

  • DataSource wird durch Spring Bean-Konfiguration mit dem Namen dbDataSource verdrahtet.
  • Wir verwenden JdbcTemplate, um häufige Fehler wie Ressourcenlecks zu vermeiden und JDBC-Boilerplate-Code zu entfernen.
  • URI, um die Liste der Mitarbeiter abzurufen, wird https://{host}:{port}/SpringDataSource/rest/emps sein
  • Wir verwenden @ResponseBody, um die Liste der Mitarbeiterobjekte als Antwort zu senden, Spring kümmert sich um die Umwandlung in JSON.

Spring Bean-Konfiguration

Es gibt zwei Wege, durch die wir JNDI-Lookup durchführen und es an den Controller DataSource anbinden können, meine Spring-Bean-Konfigurationsdatei enthält beide, aber eine davon ist auskommentiert. Sie können zwischen diesen umschalten und die Antwort wird dieselbe sein.

Verwendung des jee-Namensraum-Tags, um den JNDI-Lookup durchzuführen und ihn als Spring Bean zu konfigurieren. In diesem Fall müssen wir auch den jee-Namensraum und die Schema-Definition einbeziehen.

Erstellung eines Beans vom Typ org.springframework.jndi.JndiObjectFactoryBean, indem der JNDI-Kontextname übergeben wird. jndiName ist ein erforderlicher Parameter für diese Konfiguration.

Meine Spring-Bean-Konfigurationsdatei sieht wie folgt aus.

Code
<?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-Kontext: definiert die Anforderungsverarbeitungsinfrastruktur dieses Servlets -->

    <!-- Aktiviert das Spring MVC @Controller-Programmiermodell -->
    <annotation-driven />

    <!-- Behandelt HTTP-GET-Anfragen für /resources/**, indem statische Ressourcen im Verzeichnis ${webappRoot}/resources effizient bereitgestellt werden -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Löst Ansichten, die von @Controllers für das Rendering ausgewählt wurden, in .jsp-Ressourcen im Verzeichnis /WEB-INF/views auf -->
    <beans:bean>
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <!-- Konfiguriert das Einbinden von JSON als Anfrage und Antwort in Methoden-Handlern -->
    <beans:bean>
        <beans:property name="messageConverters">
            <beans:list>
                <beans:ref bean="jsonMessageConverter" />
            </beans:list>
        </beans:property>
    </beans:bean>

    <!-- Konfiguriert Bean zur Umwandlung von JSON in POJO und umgekehrt -->
    <beans:bean></beans:bean>
    
    <!-- Erstellt DataSource Bean -->
     
    <beans:bean>
        <beans:property name="jndiName" value="java:comp/env/jdbc/MyLocalDB"/>
    </beans:bean>
     
     <!-- Verwendung des JEE-Namensraums für Lookup -->
     <!-- <jee:jndi-lookup jndi-name="jdbc/MyLocalDB" expected-type="javax.sql.DataSource" /> -->
      
    <context:component-scan base-package="com.journaldev.spring.jdbc.controller" />

</beans:beans>

Tomcat DataSource JNDI-Konfiguration

Nun, da wir mit unserem Projekt fertig sind, ist der letzte Teil, die JNDI-Konfiguration im Tomcat-Container durchzuführen, um die JNDI-Ressource zu erstellen.

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

Fügen Sie die obige Konfiguration im Abschnitt GlobalNamingResources der server.xml-Datei hinzu.

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

Wir müssen auch den ResourceLink erstellen, um die JNDI-Konfiguration in unserer Anwendung zu verwenden, am besten fügen Sie ihn in der server.xml-Datei des Tomcat-Servers hinzu. Beachten Sie, dass der Name des ResourceLink mit dem JNDI-Kontextnamen übereinstimmen sollte, den wir in unserer Anwendung verwenden. Stellen Sie außerdem sicher, dass das MySQL-Jar im Tomcat lib-Verzeichnis vorhanden ist, da Tomcat sonst keinen MySQL-Datenbankverbindungspool erstellen kann.

Ausführung des Spring DataSource JNDI-Beispielprojekts

Unser Projekt und die Serverkonfiguration sind abgeschlossen und wir sind bereit, es zu testen. Exportieren Sie das Projekt als WAR-Datei und platzieren Sie es im Tomcat-Bereitstellungsverzeichnis. Die JSON-Antwort für den Rest-Aufruf wird im folgenden Bild gezeigt.

Spring JNDI ResponseDas ist alles für den Spring DataSource JNDI Tomcat Guide - Willkommen zum Spring DataSource JNDI Tomcat Beispiel-Tutorial.
Jetzt 200 € Guthaben sichern

Testen Sie Ihr Setup auf ccloud³

Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.

centron Redaktion Technische Redaktion

Das Redaktionsteam von centron schreibt Anleitungen aus dem Betriebsalltag: getestet auf unserer eigenen Plattform, betrieben im Rechenzentrum in Hallstadt bei Bamberg.

Kategorie Security
Teilen
Noch offene Fragen?

Unser Team hilft Ihnen bei Ihrem konkreten Setup weiter – von Menschen, die die Plattform selbst betreiben.

War dieses Tutorial hilfreich?

Ihre Antwort wird anonym gespeichert und hilft uns, die Tutorials zu verbessern.

Kommentare

Noch keine Kommentare – stellen Sie die erste Frage zu diesem Tutorial.

Zum Kommentieren anmelden

Kommentare stehen centron-Kunden offen. Melden Sie sich in Ihrem Konto an, um eine Frage zu diesem Tutorial zu stellen.

Weiterlesen

Das könnte Sie auch interessieren

Jetzt kostenlos anfangen

Melden Sie sich an und erhalten Sie in den ersten 60 Tagen ein Guthaben von 200 € bei centron.

Dieses Werbeangebot gilt nur für neue Konten. Angebot ausschließlich für Gewerbetreibende.

Jetzt loslegen Sales kontaktieren