Onde colocar e como ler os arquivos de recursos de configuração no aplicativo baseado em servlet?

222

No meu aplicativo da web, tenho que enviar e-mail para um conjunto de usuários predefinidos [email protected], assim, desejo adicionar isso a um .propertiesarquivo e acessá-lo quando necessário. Este é um procedimento correto, se sim, onde devo colocar esse arquivo? Estou usando o Netbeans IDE, que possui duas pastas separadas para arquivos de origem e JSP.

sansknwoledge
fonte
JNDI talvez possa ser uma solução?
Basil Bourque

Respostas:

464

É a sua escolha. Existem basicamente três maneiras em um archive de aplicativo da web Java (WAR):


1. Coloque no caminho de classe

Para que você possa carregá-lo ClassLoader#getResourceAsStream()com um caminho relativo ao caminho de classe:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);

Aqui foo.propertiesdeve-se colocar uma das raízes que são cobertas pelo caminho de classe padrão de um aplicativo da web, por exemplo , aplicativos da web /WEB-INF/libe /WEB-INF/classesservidores /lib, ou JDK / JRE /lib. Se o arquivo de propriedades for específico do aplicativo da web, o melhor é colocá-lo /WEB-INF/classes. Se você estiver desenvolvendo um projeto WAR padrão em um IDE, solte-o na srcpasta (a pasta de origem do projeto). Se você estiver usando um projeto Maven, solte-o na /main/resourcespasta

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, no Tomcat, você pode configurá-lo como shared.loaderpropriedade deTomcat/conf/catalina.properties .

Se você o colocou foo.propertiesem uma estrutura de pacote Java como com.example, precisará 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 classes de contexto não deve começar com a /. Somente quando você estiver usando um carregador de classes "relativo", como SomeClass.class.getClassLoader(), então você realmente precisará 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 então do carregador de classes em questão. É visível apenas para o mesmo carregador de classes que carregou a classe. Portanto, se a classe for carregada, por exemplo, por um carregador de classes comum do servidor, em vez do carregador de classes webapp, e o arquivo de propriedades estiver dentro do próprio webapp, ficará invisível. O carregador de classes de contexto é a sua aposta mais segura para que você possa colocar o arquivo de propriedades "em qualquer lugar" no caminho de classe e / ou pretende substituir um fornecido pelo servidor a partir do aplicativo da web.


2. Coloque-o no conteúdo da web

Para que você possa carregá-lo ServletContext#getResourceAsStream()com um caminho relativo ao conteúdo da web:

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...

Observe que eu demonstrei colocar o arquivo na /WEB-INFpasta, caso contrário, ele seria acessível ao público por qualquer navegador da web. Observe também que o ServletContextestá em qualquer HttpServletclasse apenas acessível pelo herdado GenericServlet#getServletContext()e Filterpelo por FilterConfig#getServletContext(). Caso você não esteja em uma classe de servlet, geralmente é apenas via injetável @Inject.


3. Coloque-o no sistema de arquivos do disco local

Para que você possa carregá-lo da java.iomaneira usual com um caminho absoluto do sistema de arquivos em 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 em disco local são um impedimento absoluto em um aplicativo da web Java EE. Veja também o primeiro link "Consulte também" abaixo.


Qual escolher?

Basta considerar as vantagens / desvantagens em sua própria opinião sobre manutenção.

Se os arquivos de propriedades forem "estáticos" e nunca precisarem ser alterados durante o tempo de execução, você poderá mantê-los no WAR.

Se você preferir editar arquivos de propriedades fora do aplicativo da Web sem a necessidade de reconstruir e reimplementar o WAR todas as vezes, coloque-o no caminho de classe fora do projeto (se necessário, inclua o diretório no caminho de classe).

Se você preferir editar arquivos de propriedades programaticamente de dentro do aplicativo da Web usando o Properties#store()método, coloque-o fora do aplicativo da Web. Conforme o Properties#store()requerido Writer, você não pode usar o caminho do sistema de arquivos em disco. Por sua vez, esse caminho pode ser passado para o aplicativo Web como um argumento da VM ou propriedade do sistema. Como precaução, nunca usegetRealPath() . Todas as alterações na pasta de implantação serão perdidas em uma reimplementação pelo simples motivo de que as alterações não são refletidas no arquivo WAR original.

Veja também:

BalusC
fonte
2
"Pessoalmente, prefiro colocá-lo no caminho de classe fora do projeto (adicione um novo caminho ao caminho de classe)" confuso, você pode dar um exemplo?
quer
4
@ Blankman Ele provavelmente significa criar uma nova pasta, colocar todos os seus arquivos de configuração personalizados e adicionar essa pasta ao caminho da classe. Portanto: 1) Crie uma pasta chamada 'appconfs' em algum lugar (pode ser até /etc/appconfs2) Adicione essa pasta ao caminho de classe do servidor / domínio do aplicativo. O segundo passo é específico do servidor de aplicativos, não acho que exista um exemplo genérico para isso.
Tuukka Mustonen
Re: (Pontuação: 2) por que ambos "WEB-INF/filename.properties"e "/WEB-INF/filename.properties"(observe /o início) funcionam? Existe alguma razão para preferir um ao outro?
Mr_and_Mrs_D
Fui corrigido neste problema há um dia. Não consigo carregar meu arquivo de propriedades. Eu posso carregá-lo de dois lugares. Um é o diretório do sistema e o outro é a unidade local. Funciona com localhost. Mas eu quero implantá-lo na amazon.
Arun Raja
Estou usando o Netbeans IDE e mantenho o arquivo de propriedades em Páginas da Web / recursos. Eu tento acessá-lo como "./Web Pages / resources / config.properties". Não consigo acessar. Por favor me ajude.
Arun Raja
9

Aviso: se você colocar os arquivos de configuração em sua WEB-INF/classespasta, e o seu IDE, por exemplo, o Eclipse, fizer uma limpeza / reconstrução, os seus arquivos conf serão destruídos, a menos que eles estejam no diretório de origem Java. A grande resposta de BalusC alude a isso na opção 1, mas eu queria acrescentar ênfase.

Aprendi da maneira mais difícil que, se você "copia" um projeto da Web no Eclipse, ele faz uma limpeza / reconstrução de qualquer pasta de origem. No meu caso, eu adicionei um "diretório de fonte vinculada" da nossa biblioteca java do POJO, que seria compilado na WEB-INF/classespasta. Fazer uma limpeza / reconstrução nesse projeto (não no projeto de aplicativo da web) causou o mesmo problema.

Pensei em colocar meus confs na pasta POJO src, mas esses confs são todos para bibliotecas de terceiros (como Quartz ou URLRewrite) que estão na WEB-INF/libpasta, então isso não fazia sentido. Eu pretendo testar colocá-lo na pasta "src" dos projetos da web quando for abordado, mas essa pasta está vazia no momento e os arquivos conf parecem deselegantes.

Por isso, votei em colocar arquivos conf WEB-INF/commonConfFolder/filename.properties, ao lado da pasta classes, que é a opção 2 do Balus.

Ed Pike
fonte
1
se você colocar seu arquivo de configuração em uma subpasta WEB_INF, como alcançá-lo? Eu não tive sorte com dizer 'configfiles / prop.properties'
JesseBoyd
ok, isso funciona colocando o arquivo de propriedades em 'Java Resources / src /', não funciona em um dos meus pacotes e precisa estar na raiz do src. seu aviso sobre a pasta de classes sendo bloqueada é uma preocupação válida.
JesseBoyd
6

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.
Subhash Pavuskar
fonte
5

Ele só precisa estar no caminho de classe (ou seja, verifique se ele acaba em / WEB-INF / classes no .war como parte da compilação).

Taylor Leese
fonte
hi obrigado pela idéia, mas ele me diz que não consegue encontrar o arquivo especificado, sim seu o problema do caminho como dar o caminho
sansknwoledge
3

Você pode usar sua pasta de origem para que, sempre que você criar, esses arquivos sejam automaticamente copiados para o diretório de classes.

Em vez de usar o arquivo de propriedades, use o arquivo XML.

Se os dados forem muito pequenos, você poderá usar o web.xml para acessar as propriedades.

Observe que qualquer uma dessas abordagens exigirá a reinicialização do servidor de aplicativos para que as alterações sejam refletidas.

Kalpak
fonte
i colocado nas páginas pasta, mas incapaz de acesso não arquivo encontrado erro está chegando como definir caminho
sansknwoledge
1
se o seu arquivo terminar na pasta WEB-INF / classes, ele será automaticamente definido no caminho de classe
Kalpak
2

Suponha que seu código esteja procurando o arquivo digamos app.properties. Copie esse arquivo para qualquer diretório e adicione-o ao caminho de classe, criando um setenv.sh no diretório bin do tomcat.

No seu setenv.sh do tomcat (se esse 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 classes do Tomcat substituirá o do WEB-INF / classes /

Uma boa leitura: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Thar
fonte