que - servlets java
¿Dónde colocar y cómo leer los archivos de recursos de configuración en una aplicación basada en servlet? (6)
En mi aplicación web tengo que enviar un correo electrónico a un conjunto de usuarios predefinidos como [email protected]
, por lo que deseo agregarlo a un archivo .properties
y acceder a él cuando sea necesario. ¿Es este un procedimiento correcto? Si es así, ¿dónde debería colocar este archivo? Estoy usando Netbeans IDE que tiene dos carpetas separadas para los archivos de origen y JSP.
Aviso: si coloca archivos de configuración en su carpeta WEB-INF/classes
, y su IDE, digamos Eclipse, realiza una limpieza / reconstrucción, atacará sus archivos conf a menos que se encuentren en el directorio de origen de Java. La gran respuesta de BalusC alude a eso en la opción 1, pero quería agregar énfasis.
Aprendí de la manera más dura que si "copia" un proyecto web en Eclipse, realiza una limpieza / reconstrucción desde cualquier carpeta de origen. En mi caso, había agregado un "directorio de origen vinculado" de nuestra biblioteca java POJO, que compilaría en la carpeta WEB-INF/classes
. Hacer un proceso de limpieza / reconstrucción en ese proyecto (no el proyecto de aplicación web) causó el mismo problema.
Pensé en poner mis confs en la carpeta de POJO src, pero estos confs son todos para librerías de terceros (como Quartz o URLRewrite) que están en la carpeta WEB-INF/lib
, por lo que no tenía sentido. Planeo probar ponerlo en la carpeta "src" de proyectos web cuando llegue a ella, pero esa carpeta está actualmente vacía y tener archivos conf en ella parece poco elegante.
Así que voto por poner archivos conf en WEB-INF/commonConfFolder/filename.properties
, junto a la carpeta de clases, que es la opción 2 de Balus.
Ej: en el archivo web.xml la etiqueta
<context-param>
<param-name>chatpropertyfile</param-name>
<!-- Name of the chat properties file. It contains the name and description of rooms.-->
<param-value>chat.properties</param-value>
</context-param>
Y chat.propiedades puedes declarar tus propiedades como esta.
Por ejemplo:
Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
Es tu elección. Básicamente, hay tres formas en un archivo de aplicación web Java (WAR):
1. Ponlo en classpath
Para que pueda cargarlo por ClassLoader#getResourceAsStream()
con una ruta relativa a classpath:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Aquí se supone que foo.properties
se coloca en una de las raíces que están cubiertas por la ruta de clase predeterminada de una aplicación web, por ejemplo, las aplicaciones /WEB-INF/lib
y /WEB-INF/classes
, server /lib
o JDK / JRE''s /lib
. Si el archivo de propiedades es específico de la aplicación web, lo mejor es colocarlo en /WEB-INF/classes
. Si está desarrollando un proyecto WAR estándar en un IDE, colóquelo en la carpeta src
(la carpeta de origen del proyecto). Si está utilizando un proyecto de Maven, colóquelo en la carpeta /main/resources
.
Alternativamente, también puede ponerlo en algún lugar fuera de la ruta de clase predeterminada y agregar su ruta a la ruta de clase del servidor de aplicaciones. En Tomcat, por ejemplo, puede configurarlo como propiedad shared.loader
de Tomcat/conf/catalina.properties
.
Si ha colocado foo.properties
en una estructura de paquete Java como com.example
, debe cargarlo como se muestra a continuación
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...
Tenga en cuenta que esta ruta de un cargador de clases de contexto no debe comenzar con un /
. Solo cuando está utilizando un cargador de clases "relativo" como SomeClass.class.getClassLoader()
, entonces debe comenzar con un /
.
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...
Sin embargo, la visibilidad del archivo de propiedades depende entonces del cargador de clases en cuestión. Solo es visible para el mismo cargador de clases que el que cargó la clase. Por lo tanto, si la clase está cargada, por ejemplo, por el servidor del cargador de clases común en lugar del cargador de clases de la aplicación web, y el archivo de propiedades está dentro de la aplicación web, entonces es invisible. El cargador de clases de contexto es su apuesta más segura, por lo que puede colocar el archivo de propiedades "en todas partes" en la ruta de clases y / o tiene la intención de anular un archivo provisto por el servidor desde la aplicación web.
2. Ponlo en webcontent
Para que pueda cargarlo mediante ServletContext#getResourceAsStream()
con una ruta relativa al contenido ServletContext#getResourceAsStream()
:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...
Tenga en cuenta que he demostrado colocar el archivo en la carpeta /WEB-INF
, de lo contrario, habría sido de acceso público para cualquier navegador web. También tenga en cuenta que ServletContext
encuentra en cualquier clase HttpServlet
la que solo se puede acceder mediante GenericServlet#getServletContext()
y en Filter
by FilterConfig#getServletContext()
. En caso de que no esté en una clase de servlet, generalmente es inyectable a través de @Inject
.
3. Ponerlo en el sistema de archivos del disco local.
Para que pueda cargarlo de la manera java.io
habitual con una ruta de sistema de archivo de disco local absoluta:
InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...
Tenga en cuenta la importancia de utilizar una ruta absoluta. Las rutas de acceso relativas del sistema de archivos del disco local son una opción absoluta en una aplicación web Java EE. Vea también el primer enlace "Vea también" a continuación.
¿Cuál elegir?
Solo sopesar las ventajas / desventajas en su propia opinión de mantenimiento.
Si los archivos de propiedades son "estáticos" y nunca deben cambiarse durante el tiempo de ejecución, puede mantenerlos en el WAR.
Si prefiere poder editar archivos de propiedades desde fuera de la aplicación web sin la necesidad de reconstruir y volver a implementar el WAR cada vez, colóquelo en el classpath fuera del proyecto (si es necesario, agregue el directorio al classpath).
Si prefiere poder editar archivos de propiedades mediante programación desde el interior de la aplicación web utilizando el método Properties#store()
, colóquelo fuera de la aplicación web. Como el Properties#store()
requiere un Writer
, no puede utilizar una ruta del sistema de archivos de disco. A su vez, esa ruta se puede pasar a la aplicación web como un argumento de VM o propiedad del sistema. Como medida de precaución, nunca use getRealPath()
. Todos los cambios en la carpeta de implementación se perderán en un nuevo despliegue por la sencilla razón de que los cambios no se reflejan en el archivo WAR original.
Ver también:
Solo necesita estar en el classpath (también debe asegurarse de que termine en / WEB-INF / classes en .war como parte de la compilación).
Suponga que su código está buscando el archivo, por ejemplo, app.properties. Copie este archivo en cualquier directorio y agregue este dir a classpath, creando un setenv.sh en el directorio bin de tomcat.
En su setenv.sh de tomcat (si este archivo no existe, cree uno, tomcat cargará este archivo setenv.sh. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"
No debe tener sus archivos de propiedades en ./webapps//WEB-INF/classes/app.properties
El cargador de clases de Tomcat anulará el de WEB-INF / classes /
Una buena lectura: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
Usted puede con su carpeta de origen, de modo que cada vez que compile, esos archivos se copiarán automáticamente en el directorio de clases.
En lugar de usar el archivo de propiedades, use el archivo XML.
Si los datos son demasiado pequeños, incluso puede usar web.xml para acceder a las propiedades.
Tenga en cuenta que cualquiera de estos enfoques requerirá el reinicio del servidor de aplicaciones para que se reflejen los cambios.