Se você usar o Logback como um componente de logout em seu aplicativo, a maioria deles configurará o arquivo `logback.xml`. Além disso, no ambiente de produção, você pode modificar diretamente o nível de log no arquivo logback.xml e pode entrar em vigor sem reiniciar o aplicativo. Então, como essa função é implementada?
Se você usar o logback como um componente de logout em seu aplicativo, a maioria deles configurará o arquivo logback.xml. Além disso, no ambiente de produção, você pode modificar diretamente o nível de log no arquivo logback.xml e pode entrar em vigor sem reiniciar o aplicativo.
Então, como essa função é implementada?
I. Descrição do problema e análise
Em resposta ao problema acima, primeiro jogue um caso real. No meu site pessoal Z+, todos os gadgets são adicionados dinamicamente e ocultos por meio de arquivos de configuração. Como existe apenas um servidor, os arquivos de configuração são simplificados e colocados diretamente em um diretório no servidor.
Agora, quando tenho um problema, preciso perceber a mudança quando o conteúdo desse arquivo mudar, o aplicativo pode sentir a alteração, recarregar o conteúdo do arquivo e atualizar o cache interno do aplicativo
Uma das maneiras mais fáceis de pensar é a pesquisa para determinar se o arquivo foi modificado. Se for modificado, será recarregado e atualizado. Portanto, as principais questões que precisam se preocupar são as seguintes:
Ii. Design e implementação
Depois que o problema é abstraído, a solução correspondente é mais clara
Então, uma implementação muito simples é mais fácil:
classe pública FileUptest {Private Long Last Time; @Test public void testFileUpdate () {arquivo file = new File ("/tmp/alarmConfig"); // Primeiro, o último registro de data e hora modificado do arquivo lasttime = file.LASTModified (); // A tarefa cronometrada determina se o arquivo mudou a cada segundo, ou seja, determina se as alterações de última geração de alterações agendadas dentexecutorService ScheduledExecutorService = executores.newscheduledThreadpool (1); scheduledExecutorService.scheduleatfixedrate (new runnable () {@Override public void run () {if (file.lastmodified ()> lasttime) {System.out.println ("File Update! time:" + file.Lastmodified (); lasttime = File.LastmodiFed (); Timeunit.Seconds); tente {thread.sleep (1000 * 60); } catch (interruptedException e) {e.printStackTrace (); }}}O exposto acima é uma implementação muito simples e muito básica, que pode basicamente atender às nossas necessidades. Então, qual é o problema dessa implementação?
O que acontece se ocorrer uma exceção durante a execução de uma tarefa de tempo?
Faça algumas modificações no código acima
classe pública FileUptest {Private Long Last Time; private vazio tt () {lança new nullPointerException (); } @Test public void testFileUpDate () {arquivo file = new File ("/tmp/alarmConfig"); lasttime = file.lastmodified (); AgendadoExecutorService ScheduleDexecutorService = executores.newscheduledThreadPool (1); scheduledExecutorService.scheduleatfixedrate (new runnable () {@Override public void run () {if (file.lastmodified ()> lastTime) {System.out.println ("File Update! Time:" + file.Lastmodified ();); lasttime = File.LastmodiFed (). Timeunit.Seconds); tente {thread.sleep (1000 * 60 * 10); } catch (interruptedException e) {e.printStackTrace (); }}}No teste real, descobri que o código acima foi acionado apenas quando a primeira modificação foi modificada, mas a modificação novamente seria inútil. Ou seja, quando uma exceção foi lançada, a tarefa de tempo não seria mais executada. A principal razão para esse problema é que o agendado
Confira as instruções de comentário do código -fonte do SchedExecutorService diretamente
Se qualquer execução da tarefa encontrar uma exceção, as execuções subsequentes forem suprimidas. Além disso, a tarefa será finalizada apenas via cancelamento ou rescisão do executor.
Portanto, ao usar esta postura, você deve garantir que sua tarefa não jogue exceções; caso contrário, você não poderá jogar mais tarde
A solução correspondente é relativamente simples, apenas pegue -a
Iii. Edição avançada
O anterior é uma versão de implementação básica. Obviamente, no círculo Java, existem basicamente muitas necessidades comuns que podem ser encontradas para usar as ferramentas de código aberto correspondentes. Obviamente, isso não é exceção, e deve ser a série Apache que todos têm mais atributos.
Primeiro de tudo, dependências maven
<Depencency> <voundid> Commons-Io </frugId> <TarifactId> Commons-IO
Principalmente, usamos o FileAlterationObServer, FileAlterationListener e FileAlterationMonitor nesta ferramenta para implementar cenários de requisitos relacionados. Claro, é muito simples de usar, então não sei como explicá -lo. Basta olhar para o código copiado de um do meu projeto de código aberto rápido alarm.
public class PropertiesConflistenerHelper {public estático boolean registringChanGelistener (arquivo de arquivo, função <arquivo, mapa <string, alarmConfig >> func) {try {// intervalo de pesquisa de 5 segundos intervalos de comprimento = timeunit.seconds.tomillis (5); // Como a audição é realizada nos diretórios, o diretório raiz do arquivo é obtido diretamente aqui arquivo dir = file.getparentfile (); // Crie um observador de arquivo para filtrar FileAlterationObServer Observer = new FileAlterationObServer (Dir, FileFilterutils.and (FILEFILTERUTILS.FILEFILTER (), FILEFILTERUTILS.NAMEFILEFILTER (FILEG.GETNAME ())); // Defina o arquivo Alterar o ouvinte Observer.addlistener (new MyFileListener (func)); FileAlterationMonitor Monitor = New FileAlterationMonitor (intervalo, observador); monitor.start (); retornar true; } catch (Exceção e) {log.error ("Registre as propriedades Altere o erro do ouvinte! E: {}", e); retornar falso; }} classe final estática myFileListener estende FileAlterationListeneRadaptor {função privada <arquivo, mapa <string, alarmConfig >> func; public myFilElistener (função <arquivo, mapa <string, alarmConfig>> func) {this.func = func; } @Override public void onFileChange (arquivo de arquivo) {map <string, alarmConfig> ans = func.apply (arquivo); // Se o carregamento falhar, imprima um log.warn ("PropertiesConfig alterado! Reload Ans: {}", Ans); }}}Para a implementação acima, algumas breves explicações:
Uma pergunta, o que acontece se uma exceção for lançada quando o método FUNC for executado?
Os resultados reais dos testes são os mesmos que acima. Depois de fazer uma exceção, você ainda precisa ter cuidado e não executa a exceção.
Então, vamos dar uma olhada na lógica de implementação acima e deduzir diretamente o módulo principal.
public void run () {while (true) {if (this.Running) {iterator var1 = this.observers.iterator (); while (var1.hasnext ()) {filealterationObserver observador = (filealterationObServer) var1.Next (); observer.CheckandNotify (); } if (this.running) {try {thread.sleep (this.interval); } catch (interruptedException var3) {; } continuar; } } retornar; }}Fica basicamente claro a partir do exposto que toda a lógica de implementação é diferente do nosso primeiro método de tarefa cronometrada. Aqui usamos diretamente os threads e loops mortos, e os métodos de sono são usados para pausar internamente. Portanto, quando ocorre uma exceção, é equivalente a jogá -lo diretamente e o fio se ajoelha.
Versão JDK suplementar
O JDK1.7 fornece um serviço de relógios, que também pode ser usado para monitorar alterações de arquivo. Eu não fui exposto a isso antes, então descobri que existe isso. Depois procurei as informações relacionadas ao uso e descobri que elas são bastante simples. Vi uma postagem no blog que explica que é orientada por eventos e tem maior eficiência. Aqui está uma demonstração de exemplo simples
@Testpublic void testfileUpwather () lança IoException {// Instruções, o ouvinte aqui também deve ser o caminho do diretório caminho = paths.get ("/tmp"); WatchService Watcher = filesystems.getDefault (). Newwatchservice (); path.register (observador, entrada_modify); novo thread (() -> {try {while (true) {watchkey key = watcher.take (); para (watchEvent <?> event: key.pollevents ()) {if (event.kind () == overflow) {// evento pode ser perdido ou descartado continuando;} pathename = (() event.Contet (); } se (! tente {thread.sleep (1000 * 60 * 10); } catch (interruptedException e) {e.printStackTrace (); }}4. Resumo
O uso do Java para implementar o monitoramento de alterações de arquivo de configuração envolve principalmente dois pontos
No geral, essa implementação é relativamente simples. Seja uma implementação personalizada ou dependendo do Compos-Io, não tem muito custo técnico, mas uma coisa a observar é:
Para evitar a situação acima, uma implementação que pode ser feita é usar a notificação de mensagem assíncrona do EventBus. Após a alteração do arquivo, envie uma mensagem e adicione uma anotação @subscribe ao método específico de recarregar o conteúdo do arquivo. Isso não apenas percebe a dissociação, mas também evita exceções de serviço causadas por exceções (se você estiver interessado nessa implementação, pode comentar e explicar)
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.