持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
为什么需要去重启项目
实际开发中有的特殊场景需要重启项目才会使得一些配置或者其他的属性生效。也可以理解为热部署,但是是和springboot的热部署不一样的。
需要在启动类上面添加两个变量
ConfigurableApplicationContext context 使用静态变量 存储上下文信息
String[] args 使用静态变量 存储 参数
@SpringBootApplication
public class FlowableApplication {
private static ConfigurableApplicationContext context;
private static String[] args;
public static void main(String[] args) {
FlowableApplication.args=args;
FlowableApplication.context=SpringApplication.run(FlowableApplication.class, args);
}
//重启项目代码
public static void restart() {
context.close();
log.info("args = " + args);
log.info("关闭成功 = " + context);
log.info("项目重启start........" + context);
FlowableApplication.context = SpringApplication.run(FlowableApplication.class, args);
log.info("项目重启end........" + context);
}
}
ConfigurableApplicationContext类时springboot
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
// 应用上下文配置时,这些符号用于分割多个配置路径
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
//BeanFactory中,ConversionService类所对应的bean的名字。如果没有此类的实例的话 * 则使用默认的转换规则
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
//LoadTimeWaver类所对应的Bean在容器中的名字。如果提供了该实例,上下文会使用临时的ClassLoader * 这样,LoadTimeWaver就可以使用bean确切的类型了
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
// Environment类在容器中实例的名字
String ENVIRONMENT_BEAN_NAME = "environment";
// System系统变量在容器中对应的Bean的名字
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
//System 环境变量在容器中对应的Bean的名字
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
//工厂中的bean名称
String APPLICATION_STARTUP_BEAN_NAME = "applicationStartup";
//关闭钩子函数线程名称
String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";
//设置容器ID
void setId(String var1);
/** * 设置此容器的父容器 * 需要注意的是,父容器一经设定就不应该修改。并且一般不会在构造方法中对其进行配置,因为很多时候。 * 其父容器还不可用。比如WebApplicationContext。 */
void setParent(@Nullable ApplicationContext var1);
/** 设置当前容器环境变量*/
void setEnvironment(ConfigurableEnvironment var1);
/** 返回此应用程序上下文的环境,允许进一步自定义*/
ConfigurableEnvironment getEnvironment();
/** 这允许在启动期间应用程序上下文记录指标 设置应用启动 */
void setApplicationStartup(ApplicationStartup var1);
ApplicationStartup getApplicationStartup();
/** 添加BeanFactoryPostProcessor,BeanFactoryPostProcessor功能比较强大,它可以修改容器的内部bean factory,改变`bean`的创建*/
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor var1);
/** * 向容器增加一个ApplicationListener,增加的Listener用于发布上下文事件如refresh和shutdown等需要注意的是,如果此上下文还没有启动,那么在此注册的Listener将会在上下文refresh的时候,全部被调用 如果上下文已经是active状态的了,就会在multicaster中使用 */
void addApplicationListener(ApplicationListener<?> var1);
/** 设置类加载器*/
void setClassLoader(ClassLoader var1);
void addProtocolResolver(ProtocolResolver var1);
/** 加载资源配置文件(XML、properties,Whatever)。由于此方法是一个初始化方法,因此如果调用此方法失败的情况下,要将其已经创建的Bean销毁。 换句话说,调用此方法以后,要么所有的Bean都实例化好了,要么就一个都没有实例化 */
void refresh() throws BeansException, IllegalStateException;
/** 向JVM注册一个回调函数,用以在JVM关闭时,销毁此应用上下文。 */
void registerShutdownHook();
void close();
/** 检测此FactoryBean是否被启动过。 */
boolean isActive();
/** 返回此应用上下文的容器。千万不要使用此方法来对BeanFactory生成的Bean做后置处理,因为单例Bean在此之前已经生成。这种情况下应该使用BeanFactoryPostProcessor来在Bean生成之前对其进行处理。通常情况下,内容容器只有在上下文是激活的情况下才能使用。因此,在使用此方法前,可以调用 isActive来判断容器是如可用 */
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
下面我贴一下controller 代码
@RestController
@RequestMapping("/test")
public class RestartControlller {
@PostMapping("/restart")
public void sysLogSava() {
startproject();
}
public void startproject () {
Thread restartThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
FlowableApplication.restart();
} catch (InterruptedException ignored) {
}
}
});
//设置为true时说明该线程是一个守护线程 且无法修改所以这里要设置为 false 且需要线程重启前设置
restartThread.setDaemon(false);
restartThread.start();
}
}
注意:代码重启就把热部署 的maven注释掉,不然就会出现第二次重启ConfigurableApplicationContex报空指针异常
实践是检验真理的唯一方法! 明天见🥰🥰🥰