web-dev-qa-db-fra.com

Devez-vous configurer les propriétés de connexion à la base de données dans server.xml ou context.xml

J'essaie de configurer les propriétés de connexion à la base de données à l'aide de JNDI pour une application Web Spring.

J'envisage deux approches comme ci-dessous:

Approche 1:

Dans votre configuration de printemps, vous pouvez avoir quelque chose comme:

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

Ensuite, dans votre fichier webapp /META-INF/context.xml, vous devriez également avoir quelque chose de similaire:

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

Et dans votre web.xml vous devriez quelque chose comme:

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


Approche 2:

Configuration dans le contexte Spring comme ceci:

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

Vous pouvez déclarer la ressource JNDI dans le fichier server.xml de Tomcat en procédant comme suit:

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

Et référencez la ressource JNDI du web context.xml de Tomcat comme ceci:

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


Ma question est la suivante: quel est le meilleur endroit pour conserver les propriétés de la base de données? Doivent-ils être placés dans-serveur.xml ou context.xml ?

De plus, si j'ai 2 bases de données, devrais-je utiliser deux configs? 

En outre, est-il préférable de les placer directement dans server.xml ou context.xml? Ou dois-je configurer via la console graphique du gestionnaire Tomcat?

Merci!

74
user1016403

Je préfère une troisième approche qui tire le meilleur parti de Approach 1 et Approche 2décrite par user1016403 .

Approche 3

  1. Enregistrer les propriétés de la base de données sur le server.xml
  2. référencer les propriétés de la base de données server.xml à partir de l'application Web META-INF/context.xml

Approche 3 avantages

Alors que le premier point est utile pour des raisons de sécurité, le second point est utile pour référencer la valeur des propriétés du serveur à partir de l'application Web, même si les valeurs des propriétés du serveur changent.

En outre, le découplage des définitions de ressources sur le serveur de leur utilisation par l'application Web permet une telle configuration évolutive pour des organisations de complexité variable où différentes équipes travaillent sur différents niveaux/couches: l'équipe des administrateurs de serveur peut travailler sans se heurter à l'équipe de développeurs si l'administrateur partage le même Nom JNDI avec le développeur pour chaque ressource.

Mise en œuvre de l'approche 3

Définissez le nom JNDI jdbc/ApplicationContext_DatabaseName.

Déclarez les différentes propriétés et valeurs du jdbc/ApplicationContext_DatabaseName dans le server.xml de Tomcat en utilisant quelque chose comme ceci:

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

Liez les propriétés du jdbc/ApplicationContext_DatabaseName à partir de l'application Web META-INF/context.xml par un contexte JNDI privé à l'application Java:comp/env/ spécifié dans l'attribut name:

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

Enfin, pour utiliser la ressource JNDI, spécifiez le nom JNDI jdbc/DatabaseName dans le descripteur de déploiement de l'application Web:

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

et au printemps:

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

Approche 3 inconvénients

Si le nom JNDI est modifié, le server.xml et le META-INF/context.xml devront être modifiés et un déploiement sera nécessaire. néanmoins ce scénario est rare.

Approche 3 variations

Plusieurs sources de données utilisées par une application Web

Ajoutez simplement des configurations au server.xml de Tomcat:

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

Ajouter une application Web lien META-INF/context.xml par un contexte JNDI privé à l'application Java:comp/env/ spécifié dans l'attribut name:

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

Enfin, ajoutez l'utilisation des ressources JNDI dans le descripteur de déploiement de l'application Web:

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

et au printemps:

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


Plusieurs sources de données utilisées par de nombreuses applications Web sur le même serveur

Ajoutez simplement la configuration au server.xml de Tomcat:

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

les autres configurations doivent être déductibles de la variante précédente.


Plusieurs sources de données vers la même base de données utilisée par plusieurs applications Web sur le même serveur 

Dans ce cas, les configurations server.xml de Tomcat telles que:

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

se termine dans deux applications Web différentes META-INF/context.xml comme:

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

et comme:

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

par conséquent, une personne peut être inquiète du fait que le même name="jdbc/DatabaseName" soit recherché puis utilisé par deux applications différentes déployées sur le même serveur: ce n'est pas un problème, car le jdbc/DatabaseName est un contexte JNDI privé à l'application Java:comp/env/, donc ApplicationContextXen utilisant Java:comp/env/ ne peut pas (par conception) rechercher la ressource liée à global="jdbc/ApplicationContextY_DatabaseName".

Bien sûr, si vous vous sentez plus détendu sans cette inquiétude, vous pouvez utiliser une stratégie de dénomination différente, telle que:

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

et comme:

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

Je préfère l’approche 2 (tout mettre (pas seulement quelques attributs dans la config),

mais au lieu de les placer dans le server.xml global ou le context.xml global, vous devez le placer dans le fichier spécifique à l'application. context.xml.default YOUR_APP.xml dans votre Tomcat.

Le fichier YOUR_APP.xml se trouve dans $catalinaHome/conf/<engine>/<Host> (par exemple, conf/Catalina/localhost/YOUR_APP.xml).

La configuration dans YOUR_APP.xml spécifique à l'application n'est disponible que pour l'application spécifique.

22
Ralph

Approche 4

Au lieu d'utiliser JNDI, je travaille avec les fichiers .properties et construit un objet complexe lors de l'initialisation du programme à la place lors de la configuration.

Vous utilisez déjà Spring et il est facile de construire DataSource par:

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

Je suis tout à fait d'accord avec Ralph quant à l'utilisation du descripteur de déploiement dans $CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml mais à la place de JNDI, j'aime bien le fichier clé-valeur!

Avec Spring, l’injection des propriétés ci-dessus dans les champs de haricots est facile:

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

au lieu de JNDI:

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

Notez également que EL autorise cela (valeurs par défaut et substitution récursive profonde):

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

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

Pour externaliser le fichier .properties, j’utilise la version moderne de Tomcat 7 qui a org.Apache.catalina.loader.VirtualWebappLoader :

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

Ainsi, vos devops remplissent virtualClasspath avec des chemins complets externes externes distincts pour chaque application et insèrent app.properties dans ce répertoire.

Voir également:

9
gavenkoa

Vous pouvez également utiliser la prise en charge d'URL JNDI pour différentes configurations d'application pour les tests, les tests d'intégration et la production. 

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

Consultez le projet GitHub Prise en charge des URL JNDI Tomcat pour activer la prise en charge des URL JNDI pour les serveurs Tomcat.

0
Ben Asmussen

étape 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>

Étape 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>

Étape 3: créer une classe pour établir une connexion

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

Tout est mis

0
tamil arasan