Como acelerar o desenvolvimento no Spring Boot com o DevTools e tornar esse processo mais agradável e produtivo?
Personalização
Como de costume no desenvolvimento do Spring Boot, a configuração é bastante simples. Tudo que você precisa fazer é adicionar a dependência correta e pronto. O Spring Boot o encontra e configura automaticamente o DevTools de acordo.
Se você estiver usando o Maven:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
Se você estiver usando o Gradle:
configurations { developmentOnly runtimeClasspath { extendsFrom developmentOnly } } dependencies { developmentOnly("org.springframework.boot:spring-boot-devtools") }
Observe que a dependência é declarada como opcional. Isso é importante porque essa declaração de dependência impede que a dependência do DevTools seja aplicada transitivamente a outros módulos, dependendo do seu projeto.
Reinicialização automática
Sempre que ocorrerem alterações no arquivo no caminho de classe, o DevTools reiniciará automaticamente o aplicativo em funcionamento com as novas alterações. Para desenvolvimento local, isso pode ser útil, pois você não precisa reimplementar o aplicativo manualmente.
Isso por si só não seria tão útil, pois a reinicialização ainda pode levar muito tempo. Felizmente, essa reinicialização é muito mais rápida do que uma reinicialização regular devido ao truque complicado que o DevTools usa.
O fato é que, ao desenvolver um aplicativo, você geralmente altera uma classe ou várias e deseja verificar os resultados em seu aplicativo em execução para obter feedback. Você faz pequenas alterações em seu aplicativo, enquanto a maioria das classes carregadas vem de estruturas e bibliotecas de terceiros.
Sob o capô do Spring DevTools, são usadas duas carregadeiras de classe -
base e
reinicialização . As classes que não são alteradas são carregadas pela base do carregador de
base . As classes com as quais você trabalha são carregadas usando o carregador de
reinicialização . Cada vez que você reinicia, o carregador de inicialização é recriado. Portanto, reiniciar o aplicativo é muito mais rápido que o normal e pode ser uma alternativa real para recarregar uma classe dinâmica usando ferramentas como o JRebel.
Inicialização de reinicialização no IDE
Uma reinicialização é acionada toda vez que um arquivo é alterado no seu caminho de classe. No entanto, esse processo depende do seu IDE. Isso significa que apenas alterar seus arquivos java não é suficiente. O importante é quando seu IDE realmente atualiza arquivos .class no seu caminho de classe.
Ao usar o IntelliJ IDEA, você precisa executar o comando build em seu projeto (
Ctrl + F9 ou
Build → Build Project ). Você também pode
configurar o comando build para executar automaticamente no IDEA . Além disso, você pode abrir a configuração de inicialização do Spring Boot e determinar o que acontece quando a atualização do aplicativo é iniciada (
Ctrl + F10 ):

Na primeira caixa de combinação, você pode selecionar
Atualizar arquivo acionador para iniciar o DevTools reiniciar toda vez que a ação
Atualizar for executada. Como alternativa, você pode até selecionar a opção
Hot Swap e tentar reiniciar o aplicativo usando o DevTools apenas se a execução do
Hot Swap falhar.
Na segunda caixa de combinação, você pode configurar a reinicialização de todos os recursos e modelos estáticos quando a janela IDEA perder o foco (por exemplo, ao alternar para a janela do navegador).
No Eclipse, é fácil o suficiente para salvar seus arquivos.
Apenas Desenvolvimento
O Spring Boot DevTools destina-se apenas ao desenvolvimento e não à operação de produção do aplicativo. Se seu aplicativo detectar que você está trabalhando em um ambiente de produção, o DevTools será automaticamente desativado.
Para esse propósito, sempre que você inicia seu aplicativo como um artefato totalmente empacotado, como um jar com um servidor de aplicativos integrado, ele é considerado um aplicativo de produção:
java -jar devtools-example-1.0.0.jar
O mesmo se aplica quando seu aplicativo é iniciado por meio de um carregador de classes especial, por exemplo, em um servidor de aplicativos.
Pelo contrário, quando você executa artefatos descompactados (por exemplo, no seu IDE), seu aplicativo é considerado no modo de desenvolvimento. O mesmo se aplica ao uso do spring-boot-plugin para executar o aplicativo:
Maven:
mvn spring-boot:run
Gradle:
gradle bootRun
LiveReload
O LiveReload é uma ferramenta útil que permite atualizar instantaneamente uma página em um navegador sempre que você fizer alterações em arquivos como HTML, CSS, imagens e muito mais. Até processa arquivos conforme necessário - isso significa compilação automática de arquivos SASS ou LESS.

O Spring DevTools inicia automaticamente uma instância local do servidor LiveReload que rastreia seus arquivos. Tudo o que você precisa fazer é instalar a
extensão do navegador e pronto. Não é apenas útil para o desenvolvimento da interface externa do seu aplicativo (caso você o distribua como parte do artefato do aplicativo Spring), mas também pode ser usado para monitorar e recarregar a saída da API REST.
Substituição de propriedade
Ao desenvolver um aplicativo localmente, você normalmente tem necessidades de configuração diferentes das do trabalho em um ambiente de produção. Um exemplo seria o armazenamento em cache. Em um ambiente de produção, a dependência de vários caches (como caches de modelo de mecanismo, cabeçalhos de cache para recursos estáticos etc.) é extremamente importante. Durante o desenvolvimento, ele pode usar dados antigos e não refletir as alterações mais recentes. Outro exemplo seria o log avançado, que pode ser útil no desenvolvimento, mas muito detalhado para o ambiente de produção.
É muito difícil gerenciar dois tipos de configuração você mesmo. A boa notícia é que o Spring Boot DevTools, por padrão, configura muitas propriedades para o seu desenvolvimento local.
spring.thymeleaf.cache=false spring.freemarker.cache=false spring.groovy.template.cache=false spring.mustache.cache=false server.servlet.session.persistent=true spring.h2.console.enabled=true spring.resources.cache.period=0 spring.resources.chain.cache=false spring.template.provider.cache=false spring.mvc.log-resolved-exception=true server.servlet.jsp.init-parameters.development=true spring.reactor.stacktrace-mode.enabled=true
Você pode encontrar uma lista de todas as propriedades na classe
DevToolsPropertyDefaultsPostProcessor .
Conexão remota
Além do desenvolvimento local, você também pode se conectar a um aplicativo remoto executando o DevTools. Esta ferramenta não se destina a ambientes de produção, pois pode representar um sério risco à segurança. No entanto, pode ser muito útil em um ambiente de pré-produção.
Habilitando a conexão remota
A conexão remota não está ativada por padrão. Você precisa ativá-lo explicitamente modificando o arquivo pom:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludeDevtools>false</excludeDevtools> </configuration> </plugin> </plugins> </build>
Ou com gradle, você precisa definir
excludeDevtools = false :
bootWar { excludeDevtools = false }
Em seguida, você precisa definir uma senha que será usada para autenticação ao se conectar ao aplicativo remoto:
spring.devtools.remote.secret=somesecret
Conectar-se a um aplicativo remoto
Após iniciar o aplicativo remoto, você pode iniciar a sessão de conexão remota. Agora tudo o que você precisa fazer é executar
org.springframework.boot.devtools.RemoteSpringApplication com a URL do seu aplicativo remoto como argumento. Observe que você deve usar
https, se possível.
Iniciar uma conexão remota é fácil no seu IDE. No IDEA, você só precisa criar uma nova configuração de inicialização. Vá para
Executar → Editar configurações ... e crie uma nova configuração com o ícone
+ no canto superior esquerdo. Selecione um tipo de aplicativo.
Para a classe Main, selecione
RemoteSpringApplication no módulo DevTools e transmita a URL do seu aplicativo remoto como argumento para o programa.

Após iniciar esta configuração, você verá uma saída semelhante se a conexão com o aplicativo remoto tiver sido bem-sucedida.

Após conectar-se a um aplicativo remoto, o DevTools monitora as alterações no caminho da classe da mesma maneira que no desenvolvimento local. No entanto, em vez de uma reinicialização local, ele transfere as alterações para o servidor remoto e inicia uma reinicialização lá. Isso pode ser muito mais rápido do que criar um aplicativo e implantá-lo em uma máquina remota.
Configuração global
Você pode personalizar o DevTools usando propriedades de configuração, como em qualquer outro aplicativo Spring. Isso geralmente significa editar o
application.properties do seu projeto. Essa configuração é separada para cada aplicativo.
No entanto, em alguns cenários, pode ser conveniente ter uma configuração global para TODOS os aplicativos em execução no mesmo computador. Você pode criar um arquivo de propriedades chamado
.spring-boot-devtools.properties localizado no diretório
$ HOME . A declaração declarada neste arquivo se aplica a todos os aplicativos que usam o DevTools.
Limitações
Recarga ao vivo
Um aplicativo Spring usando o DevTools inicia automaticamente o servidor LiveReload. Infelizmente, apenas uma instância deste servidor pode ser iniciada por vez. Mais precisamente, apenas a primeira instância funcionará. Isso se aplica não apenas a várias instâncias de aplicativos Spring com DevTools, mas também a outros aplicativos que também usam o LiverReload, como o
Gatsby no modo de desenvolvimento.
Se você deseja configurar o aplicativo Spring para que não inicie o servidor LiveReload, isso pode ser feito no seu arquivo
application.properties :
spring.devtools.livereload.enabled=false
Gancho de desligamento
O DevTools depende do atributo do
gancho de desligamento da classe
SpringApplication . A classe não funcionará corretamente se você desabilitou o atributo manualmente usando:
springApplication.setRegisterShutdownHook(false);
O atributo é ativado por padrão, portanto, você não precisa se preocupar com isso, a menos que o desative explicitamente.
Colisões com bibliotecas de terceiros
Embora o DevTools normalmente funcione corretamente, eles podem ter conflitos com bibliotecas de terceiros. Em particular, há um problema conhecido com a desserialização usando o
ObjectInputStream padrão.
No caso de um conflito desse tipo, você pode desativar a reinicialização automática configurando:
spring.devtools.restart.enabled=false
Reiniciar não funcionará mais. No entanto, o carregador de classes de
reinicialização ainda será usado. Se você precisar desativar completamente o carregador de classes, faça isso antes de iniciar o aplicativo:
public static void main(String[] args) { System.setProperty("spring.devtools.restart.enabled", "false"); SpringApplication.run(MyApp.class, args); }
Mesmo se você não usar a reinicialização automática, ainda poderá usar outros recursos do DevTools.
Habilitando a inicialização atrasada
Você pode marcar componentes individuais como inicializados lentamente usando anotações
. Esse recurso está disponível há algum tempo. A partir do Spring Boot 2.2, é possível alternar a inicialização atrasada para todos os componentes do bean usando
spring.main.lazy-initialization = true .
Isso pode ser usado sozinho ou
em combinação com o DevTools para uma reinicialização ainda mais rápida .
O DevTools permite reiniciar seu aplicativo a quente na mesma JVM. Uma vantagem significativa de uma reinicialização a quente é que ela oferece ao JIT mais opções para otimizar o código usado para iniciar seu aplicativo. Após várias reinicializações, o tempo inicial de 2500 ms é reduzido em quase 80% e se aproxima de 500 ms. Com a inicialização lenta, podemos obter melhores resultados. Ao instalar o
spring.main.lazy-initialization, nosso aplicativo é reiniciado após 400 ms diretamente no IDE.
O uso de inicialização atrasada para todos os seus grãos em um aplicativo de produção é duvidoso. Este procedimento fornece ganhos superiores no desempenho de inicialização devido a solicitações mais longas pela primeira vez para componentes de bean individuais. Mais importante, seu aplicativo não para de funcionar rapidamente. Mas, em vez de travar imediatamente após iniciar o aplicativo, ele falhará somente após solicitar diretamente o componente configurado incorretamente. Isso pode ser muito perigoso, pois você não encontrará muitos erros até que seja tarde demais. No entanto, a inicialização com atraso em massa pode ser útil para acelerar o tempo de desenvolvimento, pois ao trabalhar com uma determinada função, você normalmente trabalha apenas em parte do aplicativo e não usa o restante. O compromisso ideal seria permitir a inicialização em massa atrasada apenas para o desenvolvimento local (por exemplo, usando um perfil de mola) e desativá-lo para ambientes superiores implantados.
Conclusão
O DevTools acelera e simplifica o desenvolvimento de aplicativos Spring Boot, fornecendo a funcionalidade de reinicialização automática e LiveReload. Além disso, ele define várias propriedades para valores mais adequados ao desenvolvimento local. Além disso, permite que você se conecte remotamente ao seu aplicativo e, ao mesmo tempo, use a maioria de suas funções. Ao iniciar o aplicativo em produção, o DevTools não é usado. Veja a
documentação oficial para detalhes.