什么是热部署
事先我创建一个springboot项目。
主程序代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SpringBootApplication
public class MySpringBootApplication {
private static final Logger logger = LoggerFactory.getLogger(MySpringBootApplication.class);
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
SpringApplication.run(MySpringBootApplication.class, args);
long endTime = System.currentTimeMillis();
long startupTime = endTime - startTime;
logger.info("Spring Boot application started in {} milliseconds", startupTime);
}
}
当我冷启动的时候,日志如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.13)
2024-02-27 20:53:57.318 INFO 8368 --- [ main] c.z.helloworld2.MySpringBootApplication : Starting MySpringBootApplication using Java 1.8.0_201 on B515-54 with PID 8368 (D:\Eclipse_Project\lx\helloworld2\target\classes started by user in D:\Eclipse_Project\lx\helloworld2)
2024-02-27 20:53:57.320 INFO 8368 --- [ main] c.z.helloworld2.MySpringBootApplication : No active profile set, falling back to 1 default profile: "default"
2024-02-27 20:53:58.044 INFO 8368 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8090 (http)
2024-02-27 20:53:58.045 INFO 8368 --- [ main] o.a.catalina.core.AprLifecycleListener : An older version [1.2.21] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30]
2024-02-27 20:53:58.045 INFO 8368 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.21] using APR version [1.6.5].
2024-02-27 20:53:58.045 INFO 8368 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [false].
2024-02-27 20:53:58.045 INFO 8368 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2024-02-27 20:53:58.048 INFO 8368 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1a 20 Nov 2018]
2024-02-27 20:53:58.057 INFO 8368 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-27 20:53:58.057 INFO 8368 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68]
2024-02-27 20:53:58.156 INFO 8368 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-27 20:53:58.157 INFO 8368 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 795 ms
2024-02-27 20:53:58.361 INFO 8368 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
2024-02-27 20:53:58.426 INFO 8368 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8090 (http) with context path ''
2024-02-27 20:53:58.433 INFO 8368 --- [ main] c.z.helloworld2.MySpringBootApplication : Started MySpringBootApplication in 1.413 seconds (JVM running for 1.683)
2024-02-27 20:53:58.435 INFO 8368 --- [ main] c.z.helloworld2.MySpringBootApplication : Spring Boot application started in 1540 milliseconds
从打印日志看,花费1540毫秒。
然后我让程序实现热部署,关闭再启动,日志如下:
20:56:32.539 [Thread-0] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@274cb5b1
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.13)
2024-02-27 20:56:32.820 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Starting MySpringBootApplication using Java 1.8.0_201 on B515-54 with PID 8872 (D:\Eclipse_Project\lx\helloworld2\target\classes started by user in D:\Eclipse_Project\lx\helloworld2)
2024-02-27 20:56:32.821 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : No active profile set, falling back to 1 default profile: "default"
2024-02-27 20:56:32.871 INFO 8872 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2024-02-27 20:56:32.871 INFO 8872 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2024-02-27 20:56:33.663 INFO 8872 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8090 (http)
2024-02-27 20:56:33.664 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : An older version [1.2.21] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30]
2024-02-27 20:56:33.664 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.21] using APR version [1.6.5].
2024-02-27 20:56:33.664 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [false].
2024-02-27 20:56:33.664 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2024-02-27 20:56:33.667 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1a 20 Nov 2018]
2024-02-27 20:56:33.678 INFO 8872 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-27 20:56:33.678 INFO 8872 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68]
2024-02-27 20:56:33.729 INFO 8872 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-27 20:56:33.729 INFO 8872 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 858 ms
2024-02-27 20:56:33.951 INFO 8872 --- [ restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
2024-02-27 20:56:34.011 INFO 8872 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2024-02-27 20:56:34.034 INFO 8872 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8090 (http) with context path ''
2024-02-27 20:56:34.041 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Started MySpringBootApplication in 1.495 seconds (JVM running for 1.803)
2024-02-27 20:56:34.043 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Spring Boot application started in 1501 milliseconds
这时花费1501毫秒。然后我修改启动类,日志如下:
2024-02-27 20:58:05.615 INFO 8872 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Restarting due to 1 class path change (0 additions, 0 deletions, 1 modification)
2024-02-27 20:58:05.685 INFO 8872 --- [ Thread-6] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.13)
2024-02-27 20:58:05.771 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Starting MySpringBootApplication using Java 1.8.0_201 on B515-54 with PID 8872 (D:\Eclipse_Project\lx\helloworld2\target\classes started by user in D:\Eclipse_Project\lx\helloworld2)
2024-02-27 20:58:05.772 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : No active profile set, falling back to 1 default profile: "default"
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8090 (http)
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : An older version [1.2.21] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30]
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.21] using APR version [1.6.5].
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [false].
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
2024-02-27 20:58:05.906 INFO 8872 --- [ restartedMain] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1a 20 Nov 2018]
2024-02-27 20:58:05.907 INFO 8872 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-27 20:58:05.907 INFO 8872 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68]
2024-02-27 20:58:05.914 INFO 8872 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-27 20:58:05.915 INFO 8872 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 141 ms
2024-02-27 20:58:05.953 INFO 8872 --- [ restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html]
2024-02-27 20:58:05.973 INFO 8872 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2024-02-27 20:58:05.978 INFO 8872 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8090 (http) with context path ''
2024-02-27 20:58:05.980 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Started MySpringBootApplication in 0.229 seconds (JVM running for 93.739)
2024-02-27 20:58:05.982 INFO 8872 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
2024-02-27 20:58:05.982 INFO 8872 --- [ restartedMain] c.z.helloworld2.MySpringBootApplication : Spring Boot application started in 233 milliseconds
花费233毫秒。
分析如下:
热部署始终使用同一个进程,冷启动创建一个新的进程。在热部署例子中,修改了两个类,但类路径上是先删除后增加两个字节码文件,导致两次热部署,但明显用时比冷启动要短。在类路径上删除启动类字节码后,热部署时不会删除它,要是删除它,应用就运行不了,但删除controller类字节码后,热部署时spring容器就会删除它,导致某段时间访问时,出现404。
结论:
热部署就是重启:自定义开发代码,包括类、页面、配置文件等,加载位置是restart类加载器,如下:
18:22:39.453 [Thread-0] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@316ec5b4
冷启动的话还包括重载:jar包,加载位置是base类加载器。
如何实现热部署
springboot使用内嵌的Tomcat,Tomcat也是spring容器的一个对象,那么这个对象如何知道自定义代码发生了变化?需要有个工具帮助它,如下:
在pom文件中添加spring-boot-devtools热部署依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
手动热部署:
build-》build project,激活热部署
自动热部署:
设置自动构建
eclipse:
idea:
IDEA配置热部署_idea热部署配置_微风粼粼的博客-CSDN博客
1、file-》settings-》build..-》compiler->build project automatically
2、ctrl+Alt+shift+/ ->registry...->选中compiler.automake.allow.when.app.running(如果存在)
激活方式:焦点离开idea 5秒后 重启
热部署测试
修改HelloController的方法的返回值
热部署配置范围
默认不触发重启的目录列表
/META-INF/maven
/META-INF/resources
/resources
/static
/public
/templates
设置不触发重启的项
spring.devtools.restart.exclude=config/application.properties,static/**
禁用热部署
spring.devtools.restart.enabled=false
由于其他人也会通过配置启用热部署,导致自己的配置失效,那么我们可以在更高一层配置。
我们可以通过第六级完成更高一层的配置
@SpringBootApplication
public class HotStartApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled","false");
SpringApplication.run(HotStartApplication.class, args);
}
}