Ich bevorzuge einen dritten Ansatz, der das Beste aus
Ansatz 1 und Ansatz 2 herausholt, die von user1016403 beschrieben werden .
Ansatz 3
- Speichern Sie die Datenbankeigenschaften auf dem
server.xml
- Verweisen Sie auf die
server.xml
Datenbankeigenschaften der WebanwendungMETA-INF/context.xml
Ansatz 3 Vorteile
Während der erste Punkt aus Sicherheitsgründen nützlich ist, ist der zweite Punkt nützlich, um auf den Wert der Servereigenschaften aus der Webanwendung zu verweisen, selbst wenn sich die Werte der Servereigenschaften ändern.
Darüber hinaus macht die Entkopplung von Ressourcendefinitionen auf dem Server von ihrer Verwendung durch die Webanwendung eine solche Konfiguration für Organisationen mit unterschiedlicher Komplexität skalierbar, bei denen verschiedene Teams auf verschiedenen Ebenen / Ebenen arbeiten: Das Serveradministratorteam kann ohne Konflikte mit dem Entwicklerteam arbeiten, wenn der Administrator dieselbe teilt JNDI-Name mit dem Entwickler für jede Ressource.
Implementierung von Ansatz 3
Definieren Sie den JNDI-Namen jdbc/ApplicationContext_DatabaseName
.
Deklarieren Sie die jdbc/ApplicationContext_DatabaseName
verschiedenen Eigenschaften und Werte von in Tomcat server.xml
wie folgt:
<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/>
Verknüpfen Sie die jdbc/ApplicationContext_DatabaseName
Eigenschaften der Webanwendung META-INF/context.xml
mit einem anwendungsprivaten JNDI-Kontext, der java:comp/env/
im name
Attribut angegeben ist:
<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 die JNDI-Ressource zu verwenden, geben Sie den JNDI-Namen jdbc/DatabaseName
im Bereitstellungsdeskriptor der Webanwendung an:
<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ühjahrskontext:
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Ansatz 3 Nachteile
Wenn der JNDI-Name geändert wird, müssen sowohl der server.xml
als auch der META-INF/context.xml
bearbeitet werden, und eine Bereitstellung wäre erforderlich. Trotzdem ist dieses Szenario selten.
Ansatz 3 Variationen
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/>
Fügen Sie eine Link-Webanwendung META-INF/context.xml
über einen anwendungsprivaten JNDI-Kontext hinzu, der java:comp/env/
im name
Attribut angegeben ist:
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
Fügen Sie abschließend die Verwendung der 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ühjahrskontext:
<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 Variationsfall ableitbar sein.
Viele Datenquellen in derselben Datenbank, die von vielen Webanwendungen auf demselben Server verwendet werden
In diesem Fall sind die server.xml
Konfigurationen eines Tomcat wie folgt :
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
endet 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>
so jemand über die Tatsache besorgt sein könnte , dass die gleichen name="jdbc/DatabaseName"
nachgeschlagen wird, und dann dazu verwendet, die von zwei verschiedenen auf dem gleichen Server bereitgestellten Anwendungen: Das ist kein Problem , weil die jdbc/DatabaseName
ein anwendungs private JNDI Kontext ist java:comp/env/
, so ApplicationContextX
durch die Verwendungjava:comp/env/
nicht kann (beabsichtigt) Suchen Sie nach der verknüpften Ressource global="jdbc/ApplicationContextY_DatabaseName"
.
Wenn Sie sich ohne diese Sorge entspannter fühlen, können Sie natürlich eine andere Namensstrategie verwenden wie:
<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>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
Wenn die Ressourcen Verbindungspools wären, würden Sie dann zwei separate Pools erhalten, einen pro Webanwendung? Wenn ich von beiden Webanwendungen auf eine Ressource verlinken würde, gäbe es nur einen Verbindungspool, richtig? Gibt es Gründe, das eine dem anderen vorzuziehen? (separate DB-Verbindungspools, einer pro Webanwendung und ein Verbindungspool, der von allen Webanwendungen gemeinsam genutzt wird)? Vielen Dank.YOUR_APP.xml
DateiIch bevorzuge Ansatz 2 (füge alles ein (nicht nur ein Attribut in die Konfiguration), aber anstatt sie global
server.xml
oder global zu platzierencontext.xml
, solltest du es in der anwendungsspezifischen Datei in deinem Tomcat platzieren.context.xml.default
YOUR_APP.xml
Die
YOUR_APP.xml
Datei befindet sich in$catalinaHome/conf/<engine>/<host>
(zum Beispielconf/Catalina/localhost/YOUR_APP.xml
).Die Konfiguration in anwendungsspezifisch
YOUR_APP.xml
ist nur für die spezifische Anwendung verfügbar.Siehe den von MuleSoft veröffentlichten Leitfaden. Weitere Informationen finden Sie in der offiziellen Dokumentation, Tomcat-Konfigurationsreferenz , Seite für den Kontextcontainer
Um diese Dokumentation zu zitieren:
quelle
Ansatz 4
Anstatt JNDI zu verwenden, arbeite ich mit
.properties
Dateien und erstelle komplexe Objekte während der Programminitialisierung, stattdessen zur Konfigurationszeit.Sie verwenden Spring bereits 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 völlig mit Ralph mit Deployment Descriptor unter Verwendung von in
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
, sondern JNDI ich wie die Schlüssel-Wert - Datei!Mit Spring ist das Injizieren der oben genannten Eigenschaften in Bohnenfelder einfach:
@Value("${db.user}") String defaultSchema;
anstelle von 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}}'/>
Zum Externalisieren von
.properties
Dateien verwende ich das moderne Tomcat 7 mit org.apache.catalina.loader.VirtualWebappLoader :<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/srv/web/app/"/>
Ihre Entwickler füllen sich also
virtualClasspath
mit lokalen externen vollständigen Pfaden, die pro Anwendung separat sind, und setzen sie lokalapp.properties
in dieses Verzeichnis.Siehe auch:
quelle
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" />
Schauen Sie sich die JNDI-URL-Unterstützung des GitHub-Projekts Tomcat an, um die JNDI-URL-Unterstützung für Tomcat-Server zu aktivieren.
quelle
Schritt 1: context.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
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
quelle