Springboot Tomcat 单体项目如何实现快速jar包升级

同一个项目jar 启动由于项目端口一致导致启动失败,可以通过以下方式启动

大概思路:
1、 判断端口是否占用
2、占用则先通过其他端口启动
3、等待启动完毕后终止老进程
4、重新创建容器实例并且关联DispatcherServlet
在第三步和第四步之间,速度很快的,这样就达到了无缝更新代码的目的。

java 复制代码
@SpringBootApplication()
@EnableScheduling
public class WebMainApplication {
    public static void main(String[] args) {
        String[] newArgs = args.clone();
        int defaultPort = 8088;
        boolean needChangePort = false;
        if (isPortInUse(defaultPort)) {
            newArgs = new String[args.length + 1];
            System.arraycopy(args, 0, newArgs, 0, args.length);
            newArgs[newArgs.length - 1] = "--server.port=9090";
            needChangePort = true;
        }
        ConfigurableApplicationContext run = SpringApplication.run(WebMainApplication.class, newArgs);
        if (needChangePort) {
            String command = String.format("lsof -i :%d | grep LISTEN | awk '{print $2}' | xargs kill -9", defaultPort);
            try {
                Runtime.getRuntime().exec(new String[]{"sh", "-c", command}).waitFor();
                while (isPortInUse(defaultPort)) {
                }
                ServletWebServerFactory webServerFactory = getWebServerFactory(run);
                ((TomcatServletWebServerFactory) webServerFactory).setPort(defaultPort);
                WebServer webServer = webServerFactory.getWebServer(invokeSelfInitialize(((ServletWebServerApplicationContext) run)));
                webServer.start();

                ((ServletWebServerApplicationContext) run).getWebServer().stop();
            } catch (IOException | InterruptedException ignored) {
            }
        }

    }

    private static ServletContextInitializer invokeSelfInitialize(ServletWebServerApplicationContext context) {
        try {
            Method method = ServletWebServerApplicationContext.class.getDeclaredMethod("getSelfInitializer");
            method.setAccessible(true);
            return (ServletContextInitializer) method.invoke(context);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }

    }

    private static boolean isPortInUse(int port) {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            return false;
        } catch (IOException e) {
            return true;
        }
    }

    protected static Collection<ServletContextInitializer> getServletContextInitializerBeans(ConfigurableApplicationContext context) {
        return new ServletContextInitializerBeans(context.getBeanFactory());
    }


    private static ServletWebServerFactory getWebServerFactory(ConfigurableApplicationContext context) {
        String[] beanNames = context.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);

        return context.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
    }

}

具体逻辑想了解的可以访问文章原文链接 https://mp.weixin.qq.com/s/jaKN1YpvDycX_P13NAQNPw

相关推荐
计算机毕设VX:Fegn089517 分钟前
计算机毕业设计|基于springboot + vue小区人脸识别门禁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
让我上个超影吧2 小时前
基于SpringBoot和Vue实现CAS单点登录
前端·vue.js·spring boot
利刃大大3 小时前
【SpringBoot】validation参数校验 && JWT鉴权实现 && 加密/加盐
java·spring boot·jwt·加密
郑泰科技3 小时前
SpringBoot项目实践:之前war部署到服务器好用,重新打包部署到服务器报404
服务器·spring boot·后端
计算机毕设VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue个人博客系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
独自破碎E5 小时前
Spring Boot 3.x和2.x版本相比有哪些区别与改进?
java·spring boot·后端
幽络源小助理5 小时前
SpringBoot+Vue美食网站系统源码 | Java餐饮项目免费下载 – 幽络源
java·vue.js·spring boot
Coder_Boy_5 小时前
基于SpringAI企业级智能教学考试平台考试模块全业务闭环方案
java·人工智能·spring boot·aiops
莓有烦恼吖6 小时前
基于AI图像识别与智能推荐的校园食堂评价系统研究 04-评价系统模块
java·tomcat·web·visual studio
Coder_Boy_6 小时前
基于SpringAI的智能AIOps项目:部署相关容器化部署管理技术
人工智能·spring boot·k8s·运维开发