当前位置: 首页 > news >正文

SpringBoot单体服务无感更新启动,动态检测端口号并动态更新

SpringBoot单体服务无感更新启动

package com.basaltic.warn;import cn.hutool.core.io.IoUtil;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import springfox.documentation.oas.annotations.EnableOpenApi;import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;@MapperScan("com.basaltic.warn.sys.mapper")
@SpringBootApplication
@EnableTransactionManagement
@EnableOpenApi
@EnableScheduling
@EnableAsync
public class BasalticOneNewApplication {@SneakyThrowspublic static void main(String[] args) {AtomicInteger port = new AtomicInteger(7089);SpringApplication app = new SpringApplication(BasalticOneNewApplication.class);try {app.addInitializers((context) -> {String portStr = context.getEnvironment().getProperty("server.port");System.out.println("The port is: " + portStr);if (StringUtils.isNotBlank(portStr) && StringUtils.isNumeric(portStr)) {port.set(Integer.parseInt(portStr));}});app.run(args);} catch (Exception e) {String[] newArgs = args.clone();boolean needChangePort = false;if (isPortInUse(port.get())) {newArgs = new String[args.length + 1];System.arraycopy(args, 0, newArgs, 0, args.length);newArgs[newArgs.length - 1] = "--server.port=7069";needChangePort = true;}ConfigurableApplicationContext run = SpringApplication.run(BasalticOneNewApplication.class, newArgs);if (needChangePort) {String osName = System.getProperty("os.name");while (isPortInUse(port.get())) {if (osName.startsWith("Windows")) {killWinTidByPort(port.get());} else {killLinuxTidByPort(port.get());}System.out.println("已经占用");TimeUnit.SECONDS.sleep(2);}String[] beanNames = run.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);ServletWebServerFactory webServerFactory = run.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);((TomcatServletWebServerFactory) webServerFactory).setPort(port.get());Method method = ServletWebServerApplicationContext.class.getDeclaredMethod("getSelfInitializer");method.setAccessible(true);ServletContextInitializer invoke = (ServletContextInitializer) method.invoke(run);webServerFactory.getWebServer(invoke).start();((ServletWebServerApplicationContext) run).getWebServer().stop();}}}private static boolean isPortInUse(int port) {try (ServerSocket serverSocket = new ServerSocket(port)) {return false;} catch (Exception e) {return true;}}@SneakyThrowspublic static void killLinuxTidByPort(int port) {String command = String.format("lsof -i :%d | grep LISTEN | awk '{print $2}' | xargs kill -9", port);Runtime.getRuntime().exec(new String[]{"sh", "-c", command}).waitFor();}@SneakyThrowspublic static void killWinTidByPort(int port) {Process process = new ProcessBuilder("cmd.exe", "/c", "taskkill /F /PID " + getWinTidByPort(port)).start();process.waitFor(3, TimeUnit.SECONDS);}@SneakyThrowspublic static int getWinTidByPort(int port) {Process process = new ProcessBuilder("cmd.exe", "/c", "netstat -ano | findstr :" + port).start();process.waitFor(3, TimeUnit.SECONDS);ArrayList<String> lines = IoUtil.readUtf8Lines(process.getInputStream(), new ArrayList<>());for (String line : lines) {if (StringUtils.isBlank(line)) {continue;}String tidStr = line.substring(line.trim().lastIndexOf(" ")).trim();if (StringUtils.isNotBlank(tidStr) && StringUtils.isNumeric(tidStr)) {int tid = Integer.parseInt(tidStr);if (tid != 0) {return tid;}}}return 0;}
}

相关文章:

SpringBoot单体服务无感更新启动,动态检测端口号并动态更新

SpringBoot单体服务无感更新启动 package com.basaltic.warn;import cn.hutool.core.io.IoUtil; import lombok.SneakyThrows; import org.apache.commons.lang3.StringUtils; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplic…...

CSS基础知识04

文本溢出通常是指在限定的空间内不能容纳所输入的文字&#xff0c;导致文字超出了容器的边界 一、文本溢出 1.1.css属性处理 所用到的属性 属性属性值overflowvisible&#xff1a;默认值&#xff0c;内容不会被修剪&#xff0c;会呈现在元素框之外。hidden&#xff1a;内容会…...

python程序对服务器cpu和内存资源占用的管理。

背景 在服务器上部署了一套目标检测的程序&#xff0c;做成while true 的轮询检测数据更新的定时任务。 结果没想到那台服务器还有一套可视化程序要给领导演示看&#xff0c;结果演示的时候平台各种报错。 然后通过top查看了一下资源利用率发现python的程序cpu 130。&#xf…...

java算法性能调优:详尽探讨时间复杂度与空间复杂度的分析与优化“

接下来我将带领大家进入Java数据结构的深入学习&#xff0c;让我们一同享受Java数据结构中的奥秘。 一、引言 二、时间复杂度 三、空间复杂度 四、Java中的时间复杂度和空间复杂度 五、优化时间复杂度和空间复杂度 七、时间复杂度和空间复杂度的重要性 一&#xff1a;时间…...

人工智能:塑造未来的工作与生活

目录 人工智能技术的应用前景与影响 人工智能的历史与现状 人工智能的应用领域 人工智能的前景与挑战 个人视角&#xff1a;人工智能的应用前景与未来 人工智能在生活中的潜力 面对人工智能带来的挑战 我的观点与建议 结语 人工智能技术的应用前景与影响 随着人工智能…...

RK3568笔记六十九: 事件回调处理之Libevent 简单使用

若该文为原创文章,转载请注明原文出处。 一、前言 在项目开发过程中,事件处理使用相当多,特别是在UI处理的过程中,UI不能在非UI程里直接操作,否则会出现内存等异常,即不能在子线程里操作UI,所以用事件消息的方式通知UI线程刷新UI界面,在这一细节上掉了好多次坑。 Lib…...

MySQL如何解决幻读?

目录 一、什么是幻读&#xff1f; 1.1 幻读的定义 1.2 幻读的示例 1.3 幻读产生的原因&#xff1f; 1.4 读已提交&#xff08;Read Committed&#xff09; 1.4.1 确定事务等级 1.4.2 非锁定读取 准备 示例 结论 1.4.3 锁定读取 准备 示例 分析 结论 1.5 可重复读…...

Javascript_设计模式(二)

什么是迭代器模式?一般用在什么场景? 迭代器模式是一种行为型设计模式&#xff0c;它用于提供一种顺序访问聚合对象中各个元素的方法&#xff0c;而又不暴露该对象的内部表示。通过使用迭代器模式&#xff0c;可以遍历一个聚合对象&#xff0c;而无需关心该对象的内部结构和…...

时间同步服务器

1、时间同步服务&#xff1a;在多台主机协作时&#xff0c;确保时间同步&#xff0c;防止时间不一致造成的故障。 2、时间按同步实现&#xff1a; ntp 、chrony 3、命令&#xff1a;timedatectl timedatectl set-time "2024-02-13 10:41:55" timedatect…...

react+hook+vite项目使用eletron打包成桌面应用+可以热更新

使用Hooks-Admin的架构 Hooks-Admin: &#x1f680;&#x1f680;&#x1f680; Hooks Admin&#xff0c;基于 React18、React-Router V6、React-Hooks、Redux、TypeScript、Vite2、Ant-Design 开源的一套后台管理框架。https://gitee.com/HalseySpicy/Hooks-Adminexe桌面应用…...

STM32 ADC --- DMA乒乓缓存

STM32 ADC — DMA乒乓缓存 文章目录 STM32 ADC --- DMA乒乓缓存软件切换实现乒乓利用DMA双缓冲实现乒乓 通过cubeMX配置生成HAL工程这里使用的是上篇文章&#xff08;STM32 ADC — DMA采样&#xff09;中生成的工程配置 软件切换实现乒乓 cubeMX默认生成的工程中是打开DMA中断…...

SpringCloud基础 入门级 学习SpringCloud 超详细(简单通俗易懂)

Spring Cloud 基础入门级学习 超详细&#xff08;简单通俗易懂&#xff09; 一、SpringCloud核心组件第一代&#xff1a;SpringCloud Netflix组件第二代&#xff1a;SpringCloud Alibaba组件SpringCloud原生组件 二、SpringCloud体系架构图三、理解分布式与集群分布式集群 四、…...

【Windows 常用工具系列 20 -- MobaXterm 登录 WSL】

文章目录 MobaXterm 登录 WSL MobaXterm 登录 WSL 在 WSL 启动之后&#xff0c;打开 MobaXterm&#xff1a; 在 Distribution 中选择自己本地安装的 ubuntu 版本&#xff0c;我这里使用的是ubuntu-20.4&#xff0c;然后在 runmethod 中选择 Localhost connection. 连接成功之…...

【vmware+ubuntu16.04】ROS学习_博物馆仿真克隆ROS-Academy-for-Beginners软件包处理依赖报错问题

首先安装git 进入终端&#xff0c;输入sudo apt-get install git 安装后&#xff0c;创建一个工作空间名为tutorial_ws&#xff0c; 输入 mkdir tutorial_ws#创建工作空间 cd tutorial_ws#进入 mkdir src cd src git clone https://github.com/DroidAITech/ROS-Academy-for-Be…...

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…...

深入了解Pod

Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。 1、Pod 是由一组紧耦合的容器组成的容器组,当然…...

基于Spider异步爬虫框架+JS动态参数逆向+隧道代理+自定义中间件的猎聘招聘数据爬取

在本篇博客中&#xff0c;我们将介绍如何使用 Scrapy 框架结合 JS 逆向技术、代理服务器和自定义中间件&#xff0c;来爬取猎聘网站的招聘数据。猎聘是一个国内知名的招聘平台&#xff0c;提供了大量的企业招聘信息和职位信息。本项目的目标是抓取指定城市的招聘信息&#xff0…...

Spring 中的 BeanDefinitionParserDelegate 和 NamespaceHandler

一、BeanDefinitionParserDelegate Spring在解析xml文件的时候&#xff0c;在遇到<bean>标签的时候&#xff0c;我们会使用BeanDefinitionParserDelegate对象类解析<bean>标签的内容&#xff0c;包括<bean>标签的多个属性&#xff0c;例如 id name class in…...

BERT模型核心组件详解及其实现

摘要 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Transformer架构的预训练模型&#xff0c;在自然语言处理领域取得了显著的成果。本文详细介绍了BERT模型中的几个关键组件及其实现&#xff0c;包括激活函数、变量初始化…...

图论-代码随想录刷题记录[JAVA]

文章目录 前言深度优先搜索理论基础所有可达路径岛屿数量岛屿最大面积孤岛的总面积沉默孤岛Floyd 算法dijkstra&#xff08;朴素版&#xff09;最小生成树之primkruskal算法 前言 新手小白记录第一次刷代码随想录 1.自用 抽取精简的解题思路 方便复盘 2.代码尽量多加注释 3.记录…...

告别论文焦虑:百考通AI,让你的本科毕业论文像“闯关升级”一样简单

又到了一年毕业季&#xff0c;对于广大本科生而言&#xff0c;那座名为“毕业论文”的大山&#xff0c;是否又一次压得你喘不过气&#xff1f;面对空白的Word文档&#xff0c;你是否感到无从下手&#xff1f;导师的催促、复杂的格式、浩如烟海的文献、以及令人心慌的查重……这…...

灰度发布与流量切换

Skeyevss FAQ&#xff1a;灰度发布与流量切换 试用安装包下载 | SMS | 在线演示 项目地址&#xff1a;https://github.com/openskeye/go-vss 1. 目标 新版本 先小流量验证&#xff0c;指标正常再全量&#xff1b;出问题 快速回滚。对 SIP 类系统&#xff0c;还要考虑 会话粘…...

别再死磕GAN了!用PyTorch从零实现DDPM扩散模型,手把手带你跑通CIFAR-10生成

从GAN到DDPM&#xff1a;用PyTorch实战扩散模型的图像生成革命 当我在2022年第一次看到DALLE 2生成的超现实图像时&#xff0c;作为一名长期使用GAN的开发者&#xff0c;我意识到生成式AI正在经历一场静默的革命。传统GAN虽然能生成惊艳的结果&#xff0c;但其训练过程就像在钢…...

Cadence Allegro实战:除了Shape Keepout,还有哪些方法能精准控制铺铜区域?

Cadence Allegro实战&#xff1a;5种精准控制铺铜区域的进阶技巧 在复杂PCB设计中&#xff0c;铺铜区域的控制往往决定了信号完整性和EMC性能。Shape Keepout虽然是设计师最熟悉的工具&#xff0c;但Allegro其实提供了更丰富的"Areas"类命令集。本文将深入解析Route …...

如何高效下载B站视频:3分钟掌握智能下载工具完整指南

如何高效下载B站视频&#xff1a;3分钟掌握智能下载工具完整指南 【免费下载链接】BiliDownloader BiliDownloader是一款界面精简&#xff0c;操作简单且高速下载的b站下载器 项目地址: https://gitcode.com/gh_mirrors/bi/BiliDownloader 你是否曾经遇到过这样的情况&a…...

告别论文 “双杀” 困局:okbiye 如何用一套闭环方案,破解重复率与 AIGC 检测双重难题

okbiye-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/AI PPT降重复率 - Okbiye智能写作https://www.okbiye.com/reduceAIGC 当你对着导师的红笔批注&#xff0c;第三次修改论文时&#xff0c;有没有想过一个问题&#xff1a;为什么你改了又改的句子&#xff0c;重…...

告别MobaXterm!VSCode Remote-SSH + SFTP插件,实现本地与Linux服务器的无缝代码同步

VSCode全栈远程开发&#xff1a;SSH连接、代码同步与Python环境管理一体化实战 远程开发已成为现代工作流的重要组成部分&#xff0c;但传统工具链的割裂体验让许多开发者头疼。本文将展示如何用VSCode构建完整的远程开发环境&#xff0c;从SSH连接到代码同步&#xff0c;再到P…...

保姆级教程:用Node-RED把传感器数据传到ThingsBoard仪表盘(MQTT全流程)

从零构建物联网数据可视化&#xff1a;Node-RED与ThingsBoard的实战融合 在智能家居、工业监测等物联网场景中&#xff0c;如何将物理世界的传感器数据转化为直观的可视化图表&#xff1f;本文将手把手带您完成从硬件数据采集到云端展示的完整链路实现。不同于单纯的理论讲解&a…...

书匠策AI论文生存指南:降重降AIGC,2025届毕业生的“反内卷外挂“

&#x1f3ac; 开场&#xff1a;一场关于"论文能不能活着毕业"的生存实验 朋友们&#xff0c;今天咱不开学术讲座&#xff0c;咱开一场生存发布会。 2025年写毕业论文是什么体验&#xff1f;你辛辛苦苦码了两万字&#xff0c;满怀信心点了查重——好家伙&#xff0…...

GPT-4V食物识别实测:准确率真能到87.5%?我们复现了那篇论文的实验

GPT-4V食物识别技术深度测评&#xff1a;从实验室数据到真实场景的挑战 当一张摆盘精致的牛排照片被上传到GPT-4V界面&#xff0c;三秒后系统不仅识别出"肋眼牛排"&#xff0c;还精确标注出"约350克"和"780千卡"时&#xff0c;这种看似科幻的场景…...