Sollten Sie Datenbankverbindungseigenschaften in server.xml oder context.xml einrichten

Lesezeit: 11 Minuten

Benutzer-Avatar
Benutzer1016403

Ich versuche, die Datenbankverbindungseigenschaften mit JNDI für eine Spring-Webanwendung einzurichten.

Ich erwäge zwei Ansätze wie folgt:

Ansatz 1:

In Ihrer Spring-Konfiguration haben Sie möglicherweise Folgendes:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/facs"/>

Dann sollten Sie in Ihrer webapp /META-INF/context.xml-Datei auch etwas Ähnliches haben:

<?xml version='1.0' encoding='utf-8'?>

<!-- antiResourceLocking="true" -->
<Context path="/podd-apn"
         reloadable="true"
         cachingAllowed="false"
         antiResourceLocking="true"
         >

  <Resource name="jdbc/facs"              
            type="javax.sql.DataSource" username="${database.username}" password="${database.password}"
            driverClassName="org.postgresql.Driver" 
            url="${database.url}"
            maxActive="8" maxIdle="4"
            global="jdbc/facs" 
            />


</Context>

Und in Ihrer web.xml sollten Sie so etwas wie:

<!-- JNDI -->
  <resource-ref>
    <description>FACs Datasource</description>
    <res-ref-name>jdbc/facs</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref> 

Ansatz 2:

Setup im Spring-Kontext wie folgt:

<jee:jndi-lookup id="dbDataSource"
   jndi-name="jdbc/DatabaseName"
   expected-type="javax.sql.DataSource" />

Sie können die JNDI-Ressource in Tomcats server.xml deklarieren, indem Sie Folgendes verwenden:

<GlobalNamingResources>
  <Resource name="jdbc/DatabaseName" auth="Container" type="javax.sql.DataSource"
              username="dbUsername" password="dbPasswd"
              url="jdbc:postgresql://localhost/dbname"
              driverClassName="org.postgresql.Driver"
              initialSize="5" maxWait="5000"
              maxActive="120" maxIdle="5"
              validationQuery="select 1"
              poolPreparedStatements="true"/>
</GlobalNamingResources/>

Und verweisen Sie wie folgt auf die JNDI-Ressource aus Tomcats web context.xml:

<ResourceLink name="jdbc/DatabaseName"
   global="jdbc/DatabaseName"
   type="javax.sql.DataSource"/>

Meine Frage ist, wo ist der beste Ort, um Datenbankeigenschaften aufzubewahren? Sollen sie eingebaut werden server.xml oder Kontext.xml?

Sollte ich auch zwei Konfigurationen verwenden, wenn ich 2 Datenbanken habe?

Ist es außerdem empfehlenswert, sie direkt in server.xml oder context.xml zu platzieren? Oder muss ich über die GUI-Konsole von Tomcat Manager konfigurieren?

Vielen Dank!

Benutzer-Avatar
Taringamberini

Ich bevorzuge einen dritten Ansatz, der das Beste daraus macht
Ansatz 1 und Ansatz 2 beschrieben von user1016403.

Ansatz 3

  1. Speichern Sie Datenbankeigenschaften auf der server.xml
  2. verweise auf die server.xml Datenbankeigenschaften aus der Webanwendung META-INF/context.xml

Ansatz 3 Vorteile

Während der erste Punkt aus Sicherheitsgründen nützlich ist, ist der zweite Punkt nützlich, um den Wert der Servereigenschaften aus der Webanwendung zu referenzieren, selbst wenn sich die Werte der Servereigenschaften ändern.

Darüber hinaus macht die Entkopplung der Ressourcendefinitionen auf dem Server von ihrer Verwendung durch die Webanwendung eine solche Konfiguration über Organisationen mit unterschiedlicher Komplexität skalierbar, in denen verschiedene Teams auf verschiedenen Ebenen/Ebenen arbeiten: Das Serveradministratorteam kann ohne Konflikte mit dem Entwicklerteam arbeiten, wenn der Administrator dasselbe teilt JNDI-Name mit dem Entwickler für jede Ressource.

Umsetzung von Ansatz 3

Definieren Sie den JNDI-Namen jdbc/ApplicationContext_DatabaseName.

Deklarieren Sie die jdbc/ApplicationContext_DatabaseName‘s verschiedene Eigenschaften und Werte in Tomcat’s server.xml so etwas verwenden:

<GlobalNamingResources>
  <Resource name="jdbc/ApplicationContext_DatabaseName" auth="Container" type="javax.sql.DataSource"
              username="dbUsername" password="dbPasswd"
              url="jdbc:postgresql://localhost/dbname"
              driverClassName="org.postgresql.Driver"
              initialSize="5" maxWait="5000"
              maxActive="120" maxIdle="5"
              validationQuery="select 1"
              poolPreparedStatements="true"/>
</GlobalNamingResources/>

Verlinken Sie die jdbc/ApplicationContext_DatabaseName‘s-Eigenschaften aus der Webanwendung META-INF/context.xml durch einen anwendungsprivaten JNDI-Kontext java:comp/env/ angegeben in der name Attribut:

<Context path="/ApplicationContext" ... >
  <!--
    "global" attribute links to GlobalNamingResources in the ${catalina.base}/conf/server.xml (server administrator team)
    "name" attribute is relative to the application-private JNDI context java:comp/env/ and is looked up from the java web application (application developer team)
  -->
  <ResourceLink global="jdbc/ApplicationContext_DatabaseName" name="jdbc/DatabaseName" type="javax.sql.DataSource"/>
</Context>

Um schließlich die JNDI-Ressource zu verwenden, geben Sie den JNDI-Namen an jdbc/DatabaseName im Deployment-Deskriptor der Webanwendung:

<resource-ref>
    <description>DatabaseName's Datasource</description>
    <res-ref-name>jdbc/DatabaseName</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref> 

und im Frühlingskontext:

<jee:jndi-lookup id="DatabaseNameDataSource"
   jndi-name="jdbc/DatabaseName"
   expected-type="javax.sql.DataSource" />

Ansatz 3 Nachteile

Wenn der JNDI-Name geändert wird, werden sowohl die server.xml und die META-INF/context.xml muss bearbeitet werden und ein Deploy wäre notwendig; dennoch ist dieses Szenario selten.

Ansatz 3 Varianten

Viele Datenquellen, die von einer Webanwendung verwendet werden

Fügen Sie einfach Konfigurationen zu Tomcat hinzu server.xml:

<GlobalNamingResources>
  <Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
  <Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
  ...
</GlobalNamingResources/>

Link-Webanwendung hinzufügen META-INF/context.xml durch einen anwendungsprivaten JNDI-Kontext java:comp/env/ angegeben in der name Attribut:

<Context path="/ApplicationContext" ... >
  <ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
  <ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
  ...
</Context>

Fügen Sie schließlich die Nutzung von JNDI-Ressourcen im Bereitstellungsdeskriptor der Webanwendung hinzu:

<resource-ref>
    <description>DatabaseName1's Datasource</description>
    <res-ref-name>jdbc/DatabaseName1</res-ref-name> ... 
</resource-ref> 
<resource-ref>
    <description>DatabaseName2's Datasource</description>
    <res-ref-name>jdbc/DatabaseName2</res-ref-name> ... 
</resource-ref>
...

und im Frühlingskontext:

<jee:jndi-lookup id="DatabaseName1DataSource"
   jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
   jndi-name="jdbc/DatabaseName2" ... />
...

Viele Datenquellen, die von vielen Webanwendungen auf demselben Server verwendet werden

Fügen Sie einfach die Konfiguration zu Tomcat hinzu server.xml:

<GlobalNamingResources>
  <Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
  <Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
  <Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
  <Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
  ...
</GlobalNamingResources/>

die andere Konfiguration sollte aus dem vorherigen Änderungsfall ableitbar sein.

Viele Datenquellen zu derselben Datenbank, die von vielen Webanwendungen auf demselben Server verwendet wird

In diesem Fall ein Kater server.xml Konfigurationen wie:

<GlobalNamingResources>
  <Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
  <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />

landet in zwei verschiedenen Webanwendungen META-INF/context.xml wie:

<Context path="/ApplicationContextX" ... >
  <ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>

und wie:

<Context path="/ApplicationContextY" ... >
  <ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>

also könnte sich jemand Sorgen darüber machen, dass das Gleiche der Fall ist name="jdbc/DatabaseName" nachgeschlagen und dann von zwei verschiedenen Anwendungen verwendet wird, die auf demselben Server bereitgestellt werden: Dies ist kein Problem, da die jdbc/DatabaseName ist ein anwendungsprivater JNDI-Kontext java:comp/env/Also ApplicationContextX durch die Nutzung java:comp/env/ kann (absichtlich) nicht nach der verknüpften Ressource suchen global="jdbc/ApplicationContextY_DatabaseName".

Wenn Sie sich ohne diese Sorge entspannter gefühlt haben, können Sie natürlich eine andere Benennungsstrategie verwenden, wie zum Beispiel:

<Context path="/ApplicationContextX" ... >
  <ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>

und wie:

<Context path="/ApplicationContextY" ... >
  <ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>

  • Frage zu Ihrem Szenario “Viele Datenquellen zu derselben Datenbank, die von vielen Webanwendungen auf demselben Server verwendet wird” … <Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... /> Wenn die Ressourcen Verbindungspools wären, würden Sie dadurch zwei separate Pools erhalten, einen pro Webapp? Wenn ich hingegen von beiden Webapps auf eine Ressource verlinken würde, gäbe es nur einen Verbindungspool, richtig? Irgendwelche Gründe, das eine dem anderen vorzuziehen? (separate DB-Verbindungspools, einer pro Webapp im Vergleich zu einem Verbindungspool, der von allen Webapps geteilt wird)? Vielen Dank.

    – Rebekka

    12. Juli 2014 um 2:39 Uhr

  • @Rebeccah – F1: Wenn es sich bei den Ressourcen um Verbindungspools handeln würde, würden Sie dann zwei separate Pools erhalten, einen pro Webanwendung? A1: Ja, das würde es.

    – Taringamberini

    14. Juli 2014 um 8:04 Uhr

  • @Rebeccah – Q2: Wohingegen, wenn ich von beiden Webapps zu einer Ressource verlinken würde, es nur einen Verbindungspool geben würde, richtig? A2: Richtig.

    – Taringamberini

    14. Juli 2014 um 8:05 Uhr

  • @Rebeccah – Q3: Irgendwelche Gründe, das eine dem anderen vorzuziehen? (separate DB-Verbindungspools, einer pro Webapp im Vergleich zu einem Verbindungspool, der von allen Webapps geteilt wird)? A3: Ich bevorzuge “separate DB-Verbindungspools, einen pro Webapp”, weil ich nicht möchte, dass die intensive Nutzung von webAppX zu einer Verlangsamung von webAppY führt, da der Verbindungspool von webAppX erschöpft ist. Darüber hinaus konnte das Datenbanküberwachungs- und Protokollierungssystem nicht zwischen webAppX- und webAppY-Anforderungen unterscheiden, sodass das Verstehen und Isolieren von Problemen schwierig oder schlimmer noch unmöglich ist.

    – Taringamberini

    14. Juli 2014 um 8:06 Uhr

Benutzer-Avatar
Ralf

YOUR_APP.xml Datei

Ich bevorzuge Ansatz 2 (alles einfügen (nicht nur ein Attribut in die config), sondern anstatt sie in die Datei global server.xml oder global context.xml Sie sollten es in der anwendungsspezifischen platzieren context.xml.default YOUR_APP.xml Datei in Ihrem Tomcat.

Das YOUR_APP.xml Datei befindet sich in $catalinaHome/conf/<engine>/<host> (zum Beispiel conf/Catalina/localhost/YOUR_APP.xml).

Die Konfiguration ist anwendungsspezifisch YOUR_APP.xml ist nur für die spezifische Anwendung verfügbar.

Sehen der Führer herausgegeben von MuleSoft. Und siehe die offizielle Dokumentation, Tomcat-KonfigurationsreferenzSeite für Der Kontextcontainer

Um diese Dokumentation zu zitieren:

Einzelne Context-Elemente können explizit definiert werden:

• …

• In einzelnen Dateien (mit der Erweiterung „.xml“) in der $CATALINA_BASE/conf/[enginename]/[hostname]/ Verzeichnis. Der Kontextpfad und die Version werden vom Basisnamen der Datei abgeleitet (dem Dateinamen abzüglich der Erweiterung .xml).

• …

  • Danke für deine Antwort. wenn ich alle Eigenschaften in unseren Anwendungen META-INF/context.xml platziere? ist es der beste Aufbewahrungsort?

    – Benutzer1016403

    25. Februar 2013 um 11:52 Uhr

  • Ich denke nicht, dass es ein guter Ansatz ist, einige Eigenschaftenwerte INNERHALB (z. B. in META-INF/context.xml) der Anwendung zu platzieren, da Sie die Anwendung dann neu kompilieren und bereitstellen müssen, wenn sich die Eigenschaften ändern. – Das wäre also fast das Gleiche wie überhaupt keine Eigenschaften zu verwenden und die Werte direkt in der Spring config.xml zu platzieren

    – Ralf

    25. Februar 2013 um 12:12 Uhr


  • Was ist dann der empfohlene Ort, um sie aufzubewahren?

    – Benutzer1016403

    25. Februar 2013 um 12:29 Uhr

  • Ich würde nur hinzufügen, anstatt diese für alle Apps mit context.xml.default zu definieren, können Sie anwendungsspezifische Kontextkonfigurationsdateien wie yourapp.xml im selben Ordner verwenden, wodurch Sie auf zwei Bereitstellungen desselben Krieges verweisen können verschiedene Datenbanken.

    – nutze die4ce

    21. Oktober 2013 um 22:15 Uhr

  • Keine hilfreiche Antwort. Es gibt nur eine Präferenz an und liefert keine Begründung.

    – DavidS

    27. Juni 2017 um 18:04 Uhr

Benutzer-Avatar
gegebenkoa

Ansatz 4

Anstatt JNDI zu verwenden, arbeite ich mit .properties Dateien und Erstellen Sie ein komplexes Objekt während der Programminitialisierung stattdessen zur Konfigurationszeit.

Sie verwenden bereits Spring und es ist einfach zu konstruieren DataSource durch:

<context:property-placeholder location="classpath:app.properties"/>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@${db.host}:${db.port}:${db.user}"/>
    <property name="username" value="${db.user}"/>
    <property name="password" value="${db.pass}"/>
</bean>

Ich stimme vollkommen zu Ralf mit Verwendung des Bereitstellungsdeskriptors in $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xmlaber statt JNDI mag ich eine einfache Schlüsselwertdatei!

Mit Spring ist das Injizieren der oben genannten Eigenschaften in Bohnenfelder einfach:

@Value("${db.user}") String defaultSchema;

statt JNDI:

@Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");

Beachten Sie auch, dass EL dies zulässt (Standardwerte und tiefe rekursive Substitution):

@Value('${db.user:testdb}') private String dbUserName;

<property name="username" value="${db.user.${env}}"/>

Externalisieren .properties Datei verwende ich modernes Tomcat 7, das hat org.apache.catalina.loader.VirtualWebappLoader:

<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
        virtualClasspath="/srv/web/app/"/>

Ihre Devops füllen sich also virtualClasspath mit lokalen externen vollständigen Pfaden, die pro Anwendung getrennt sind und lokal abgelegt werden app.propertieszu diesem dir.

Siehe auch:

  • Hinzufügen eines Verzeichnisses zum Tomcat-Klassenpfad
  • Kann ich in Tomcat einen benutzerdefinierten Klassenpfad pro Anwendung erstellen
  • Externalisierung der Tomcat-Webanwendungskonfiguration aus der .war-Datei
  • So lesen Sie eine Eigenschaftendatei außerhalb meines Webapp-Kontexts in Tomcat
  • Konfigurieren Sie Tomcat so, dass die Eigenschaftendatei zum Laden von DB-Verbindungsinformationen verwendet wird
  • Externalisieren Sie die Tomcat-Konfiguration

Schritt 1: Kontext.xml

    <Context path="/projectname">
  <Resource auth="Container" 
            driverClassName="com.mysql.jdbc.Driver"
            logAbandoned="true" 
            maxActive="100" ``
            maxIdle="30" 
            maxWait="10000" 
            name="refname" 
            removeAbandoned="true" 
            removeAbandonedTimeout="60" 
            type="javax.sql.DataSource" 
            url="jdbc:mysql://localhost:8080/dbname" 
            username="root"
            password="root"/>
</Context>

Schritt 2: web.xml

<resource-ref>
        <description>DB Connection</description>
        <res-ref-name>refname</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

Schritt 3: Erstellen Sie eine Klasse, um eine Verbindung herzustellen

Connection connection = null;        
            Context context = (Context) new InitialContext().lookup("java:comp/env");
            DataSource ds = (DataSource) context.lookup("refname");
            connection = ds.getConnection();

Alles ist eingestellt

Sie können die JNDI-URL-Unterstützung auch für verschiedene Anwendungskonfigurationen für Test, Integrationstest und Produktion verwenden.

<Context>
...
<Resource auth="Container" factory="com.benasmussen.jndi.url.URLFactory" 
name="url/MyUrl" type="java.net.URL" url="file:///your/path/to/file"/>
...
</Context>

<jee:jndi-lookup id="myUrl" jndi-name="java:comp/env/url/MyUrl" expected-type="java.net.URL" />

Sehen Sie sich das GitHub-Projekt an Tomcat JNDI-URL-Unterstützung um die JNDI-URL-Unterstützung für Tomcat-Server zu aktivieren.

1227390cookie-checkSollten Sie Datenbankverbindungseigenschaften in server.xml oder context.xml einrichten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy