Onde colocar e como ler arquivos de recursos de configuração no aplicativo baseado em servlet?
-
23-09-2019 - |
Pergunta
No meu aplicativo da web, tenho que enviar email para o conjunto de usuários predefinidos como finance@xyz.com
, então desejo adicionar isso a um .properties
Arquive e acesse quando necessário. Este é um procedimento correto; nesse caso, onde devo colocar esse arquivo? Estou usando o NetBeans IDE, que está tendo duas pastas separadas para arquivos de origem e JSP.
Solução
É a sua escolha. Existem basicamente três maneiras em um arquivo de aplicativos da web java (guerra):
1. Coloque em Classpath
Para que você possa carregá -lo por ClassLoader#getResourceAsStream()
com um caminho de classe de patrimônio:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Aqui foo.properties
deve ser colocado em uma das raízes cobertas pelo caminho de classe padrão de um WebApp, por exemplo, WebApp's /WEB-INF/lib
e /WEB-INF/classes
, servidor /lib
, ou JDK/JRE's /lib
. Se o PropertiesFile for específico do webApp, o melhor é colocá-lo em /WEB-INF/classes
. Se você está desenvolvendo um projeto de guerra padrão em um IDE, entre src
Pasta (a pasta de origem do projeto). Se você está usando um projeto maven, entre /main/resources
pasta.
Como alternativa, você também pode colocá -lo em algum lugar fora do caminho de classe padrão e adicionar seu caminho ao caminho de classe do AppServer. Por exemplo, tomcat, você pode configurá -lo como shared.loader
propriedade de Tomcat/conf/catalina.properties
.
Se você colocou o foo.properties
em uma estrutura de pacote Java como com.example
, então você precisa carregá -lo como abaixo
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...
Observe que esse caminho de um carregador de classe de contexto não deve começar com um /
. Somente quando você está usando um carregador de classe "relativo", como SomeClass.class.getClassLoader()
, então você realmente precisa iniciá -lo com um /
.
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...
No entanto, a visibilidade do arquivo de propriedades depende do carregador de classe em questão. É visível apenas para o mesmo carregador de classe que o que carregou a classe. Portanto, se a classe for carregada pelo servidor EG Common ClassLoader em vez do WebApp Classloader, e o arquivo Properties estiver dentro do próprio webApp, será invisível. O carregador de classe de contexto é a sua aposta mais segura para que você possa colocar o arquivo de propriedades "em todos os lugares" no caminho de classe e/ou pretende ser capaz de substituir um servidor fornecido no WebApp.
2. Coloque no webcontent
Para que você possa carregá -lo por ServletContext#getResourceAsStream()
Com um caminho relativo do WebContent:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...
Observe que eu demonstrei colocar o arquivo em /WEB-INF
Pasta, caso contrário, teria sido acessível ao público por qualquer webbrowser. Observe também que o ServletContext
está em qualquer HttpServlet
classe apenas acessível pelo herdado GenericServlet#getServletContext()
e em Filter
por FilterConfig#getServletContext()
. Caso você não esteja em uma aula de servlet, geralmente é apenas injetável via @Inject
.
3. Coloque no sistema de arquivos de disco local
Para que você possa carregá -lo o usual java.io
caminho com um caminho absoluto do sistema de arquivos de disco local:
InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...
Observe a importância de usar um caminho absoluto. Os caminhos relativos do sistema de arquivos de disco local são um absoluto no-go em um aplicativo da Web Java EE. Veja também o primeiro link "veja também" abaixo.
Qual escolher?
Basta pesar as vantagens/desvantagens em sua opinião própria da manutenção.
Se os arquivos das propriedades forem "estáticos" e nunca precisarem mudar durante o tempo de execução, você poderá mantê -los na guerra.
Se você preferir ser capaz de editar arquivos de propriedades de fora do aplicativo da Web sem a necessidade de reconstruir e reimpor a guerra todas as vezes, coloque -o no caminho de classe fora do projeto (se necessário, adicione o diretório ao caminho de classe).
Se você preferir poder editar arquivos de propriedades programaticamente de dentro do aplicativo da web usando Properties#store()
Método, coloque -o fora do aplicativo da web. Enquanto o Properties#store()
requer uma Writer
, você não pode dar a volta usando um caminho do sistema de arquivos de disco. Por sua vez, esse caminho pode ser passado para o aplicativo da Web como um argumento da VM ou propriedade do sistema. Como precaução, Nunca usar getRealPath()
. Todas as alterações na pasta de implantação serão perdidas em uma reimplantação pela simples razão de que as alterações não são refletidas de volta no arquivo de guerra original.
Veja também:
Outras dicas
Palavra de aviso: se você colocar arquivos de configuração em seu WEB-INF/classes
Pasta, e seu IDE, digamos Eclipse, faz uma limpeza/reconstrução, ela arrastará seus arquivos confiados, a menos que estejam no diretório de origem Java. A ótima resposta de Balusc alude a isso na opção 1, mas eu queria acrescentar ênfase.
Aprendi da maneira mais difícil que, se você "copiar" um projeto da Web no Eclipse, ele faz uma limpeza/reconstrução de qualquer pasta de origem. No meu caso, eu havia adicionei um "diretor de origem vinculado" da nossa biblioteca Pojo Java, ele compilaria para o WEB-INF/classes
pasta. Fazer uma limpeza/reconstrução nesse projeto (não o projeto do aplicativo da web) causou o mesmo problema.
Pensei em colocar meus confs na pasta Pojo SRC, mas esses confs são todos para libs de terceiros (como quartzo ou urlrewrite) que estão no WEB-INF/lib
Pasta, então isso não fazia sentido. Eu pretendo testar colocá -lo na pasta "SRC" da Web quando eu me deparar com ela, mas essa pasta está atualmente vazia e ter arquivos confiados parece deselega.
Então eu voto para colocar arquivos confiados em WEB-INF/commonConfFolder/filename.properties
, próximo para a pasta de classes, que é a opção 2 de Balus.
Ex: no arquivo web.xml a tag
<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>
E chat.properties você pode declarar suas propriedades como esta
Para ex:
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.
Ele só precisa estar no caminho de classe (também conhecido como certifique-se de que acaba sob /Web-Inf /Classes no .war como parte da construção).
Você pode com sua pasta de origem, sempre que criar, esses arquivos são copiados automaticamente para o diretório de classes.
Em vez de usar o arquivo Propriedades, use o arquivo XML.
Se os dados forem muito pequenos, você pode até usar o web.xml para acessar as propriedades.
Observe que qualquer uma dessas abordagens exigirá o reinício do servidor de aplicativos para que as alterações sejam refletidas.
Suponha que seu código esteja procurando o arquivo, digamos App.Properties. Copie este arquivo para qualquer DIR e adicione este diretor ao ClassPath, criando um setenv.sh no bin dir do tomcat.
No seu setenv.sh do tomcat (se este arquivo não existir, crie um, o TomCat carregará esse arquivo setenv.sh.
#!/bin/sh
CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"
Você não deve ter seus arquivos de propriedades em ./webapps//web-inf/classes/app.properties
O carregador de classe Tomcat substituirá o de Web-Inf/Classes/
Uma boa leitura:https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html