Prefiero un tercer enfoque que toma lo mejor del
enfoque 1 y el enfoque 2 descritos por el usuario 1016403 .
Enfoque 3
- Guarde las propiedades de la base de datos en el
server.xml
- hacer referencia a las
server.xml
propiedades de la base de datos desde la aplicación webMETA-INF/context.xml
Beneficios del enfoque 3
Si bien el primer punto es útil por razones de seguridad, el segundo punto es útil para hacer referencia al valor de las propiedades del servidor desde la aplicación web, incluso si los valores de las propiedades del servidor cambiarán.
Además, el desacoplamiento de las definiciones de recursos en el servidor de su uso por la aplicación web hace que dicha configuración sea escalable entre organizaciones con diversa complejidad donde diferentes equipos trabajan en diferentes niveles / capas: el equipo de administradores del servidor puede trabajar sin entrar en conflicto con el equipo de desarrolladores si el administrador comparte lo mismo Nombre JNDI con el desarrollador de cada recurso.
Implementación del enfoque 3
Defina el nombre JNDI jdbc/ApplicationContext_DatabaseName
.
Declare las jdbc/ApplicationContext_DatabaseName
diversas propiedades y valores de Tomcat server.xml
usando algo como esto:
<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/>
Vincular las jdbc/ApplicationContext_DatabaseName
propiedades de la aplicación web META-INF/context.xml
mediante un contexto JNDI privado de la aplicación java:comp/env/
especificado en el name
atributo:
<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>
Finalmente, para utilizar el recurso JNDI, especifique el nombre JNDI jdbc/DatabaseName
en el descriptor de implementación de la aplicación 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>
y en el contexto de primavera:
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Enfoque 3 inconvenientes
Si se cambia el nombre JNDI, tanto el server.xml
como el META-INF/context.xml
tendrán que ser editados y será necesaria una implementación; sin embargo, este escenario es raro.
Enfoque 3 variaciones
Muchas fuentes de datos utilizadas por una aplicación web
Simplemente agregue configuraciones a Tomcat's server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
...
</GlobalNamingResources/>
Agregue la aplicación web de enlace META-INF/context.xml
mediante un contexto JNDI privado de la aplicación java:comp/env/
especificado en el name
atributo:
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
Finalmente, agregue el uso de recursos JNDI en el descriptor de implementación de la aplicación 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>
...
y en el contexto de primavera:
<jee:jndi-lookup id="DatabaseName1DataSource"
jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
jndi-name="jdbc/DatabaseName2" ... />
...
Muchas fuentes de datos utilizadas por muchas aplicaciones web en el mismo servidor
Simplemente agregue la configuración a Tomcat's server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
la otra configuración debe ser deducible del caso de variación anterior.
Muchas fuentes de datos a la misma base de datos utilizada por muchas aplicaciones web en el mismo servidor
En tal caso, las server.xml
configuraciones de un Tomcat como:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
termina en dos aplicaciones web diferentes META-INF/context.xml
como:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
y, como:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
por lo que alguien podría estar preocupado por el hecho de que lo mismo name="jdbc/DatabaseName"
sea buscado y luego utilizado por dos aplicaciones diferentes implementadas en el mismo servidor: esto no es un problema porque jdbc/DatabaseName
es un contexto JNDI privado de la aplicación java:comp/env/
, ApplicationContextX
porjava:comp/env/
lo que al usar no se puede (por diseño) busque el recurso vinculado global="jdbc/ApplicationContextY_DatabaseName"
.
Por supuesto, si se sintió más relajado sin esta preocupación, podría usar una estrategia de nomenclatura diferente como:
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>
y, como:
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... /> <Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
Si los recursos fueran grupos de conexiones, ¿esto le daría dos grupos separados, uno por aplicación web? Considerando que, si me vincule desde ambas aplicaciones web a un recurso, solo habría un grupo de conexiones, ¿correcto? ¿Alguna razón para preferir uno al otro? (grupos de conexiones de base de datos separados uno por aplicación web frente a un grupo de conexiones compartido por todas las aplicaciones web)? Gracias.YOUR_APP.xml
archivoPrefiero el enfoque 2 (ponga todo (no solo algún atributo en la configuración), pero en lugar de colocarlos en el global
server.xml
o globalcontext.xml
, debe colocarlo en el archivo específico de la aplicación en su Tomcat.context.xml.default
YOUR_APP.xml
El
YOUR_APP.xml
archivo se encuentra en$catalinaHome/conf/<engine>/<host>
(por ejemploconf/Catalina/localhost/YOUR_APP.xml
).La configuración en la aplicación específica
YOUR_APP.xml
solo está disponible para la aplicación específica.Consulte la guía publicada por MuleSoft. Y consulte la documentación oficial, Referencia de configuración de Tomcat , página para The Context Container
Para citar esa documentación:
fuente
Enfoque 4
En lugar de usar JNDI, trabajo con
.properties
archivos y construyo objetos complejos durante la inicialización del programa en lugar de en el tiempo de configuración.Ya usas Spring y es fácil de construir
DataSource
por:<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>
Estoy completamente de acuerdo con Ralph con el uso del descriptor de implementación en,
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml
pero en su lugar, JNDI me gusta el archivo de valor clave simple.Con Spring, inyectar las propiedades anteriores en los campos de frijoles es fácil:
@Value("${db.user}") String defaultSchema;
en lugar de JNDI:
@Inject ApplicationContext context; Enviroment env = context.getEnvironment(); String defaultSchema = env.getProperty("db.user");
Tenga en cuenta también que EL permite esto (valores predeterminados y sustitución recursiva profunda):
@Value('${db.user:testdb}') private String dbUserName; <property name='username' value='${db.user.${env}}'/>
Para externalizar el
.properties
archivo, utilizo Tomcat 7 moderno que tiene org.apache.catalina.loader.VirtualWebappLoader :<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/srv/web/app/"/>
Por lo tanto, sus devops se llenan
virtualClasspath
con rutas completas externas locales que están separadas por aplicación y se colocanapp.properties
en ese directorio.Ver también:
fuente
También puede utilizar el soporte de URL JNDI para diferentes configuraciones de aplicaciones para pruebas, pruebas de integración y producción.
<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" />
Consulte el soporte de URL JNDI de Tomcat del proyecto GitHub para habilitar el soporte de URL JNDI para servidores Tomcat.
fuente
paso 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>
Paso 2: web.xml
Paso 3: cree una clase para conectarse
Connection connection = null; Context context = (Context) new InitialContext().lookup("java:comp/env"); DataSource ds = (DataSource) context.lookup("refname"); connection = ds.getConnection();
Todo esta listo
fuente