优秀平面设计作品网站,舞蹈网站模板,wordpress自适应自媒体主题,自定义短网址本篇是关于把springboot生成的jar打到electron里#xff0c;在生成的桌面程序启动时springboot服务就会自动启动。 虽然之后并不需要这种方案#xff0c;更好的是部署[一套服务端#xff0c;多个客户端]...但是既然搭建成功了#xff0c;也记录一下。 前端文件
1、main.js…本篇是关于把springboot生成的jar打到electron里在生成的桌面程序启动时springboot服务就会自动启动。 虽然之后并不需要这种方案更好的是部署[一套服务端多个客户端]...但是既然搭建成功了也记录一下。 前端文件
1、main.js
const { app, BrowserWindow, ipcMain, Notification, Menu,dialog} require(electron/main)
const path require(node:path)
const childProcess require(child_process);
const fs require(fs)let win null; // Electron主窗口实例
let backendProcess null; // Java子进程实例
const BACKEND_PORT 8080; // 后端固定端口可配置
const JAR_FILENAME helloworld-0.0.1-SNAPSHOT.jar; // JAR文件名需与resources目录下的文件一致function writeFile(_, data) {fs.writeFileSync(D:/hello.txt, data)
}function readFile() {const res fs.readFileSync(D:/hello.txt).toString();return res
}/*** 获取JAR包路径兼容开发/生产环境*/
function getJarPath() {if (app.isPackaged) {// 生产环境打包后资源目录为process.resourcesPathreturn path.join(process.resourcesPath, resources, JAR_FILENAME);} else {// 开发环境资源目录为项目根目录的resources文件夹return path.join(__dirname, resources, JAR_FILENAME);}
}/*** 4. 启动Java子进程核心逻辑*/
function startBackend() {const jarPath getJarPath();// 检查JAR包是否存在避免启动失败if (!fs.existsSync(jarPath)) {dialog.showErrorBox(错误, JAR包不存在${jarPath});app.quit();return;}// 构造Java启动参数可添加Spring Boot配置如端口、环境const args [-jar,jarPath,--server.port${BACKEND_PORT}, // 指定后端端口避免冲突--spring.profiles.activeprod // 指定生产环境配置可选];// 构造子进程选项跨平台优化const options {windowsHide: true, // Windows下隐藏命令行窗口避免弹出黑框env: { ...process.env }, // 传递环境变量cwd: path.dirname(jarPath) // 设置子进程工作目录避免相对路径问题};// 启动子进程使用spawn适合长时间运行的进程backendProcess childProcess.spawn(java, args, options);// 5. 监听后端输出调试用backendProcess.stdout.on(data, (data) {console.log([Backend], data.toString().trim());});// 6. 监听后端错误如Java未安装、端口冲突backendProcess.stderr.on(data, (data) {const errorMsg data.toString().trim();console.error([Backend Error], errorMsg);// 处理端口冲突示例if (errorMsg.includes(Port ${BACKEND_PORT} is already in use)) {dialog.showErrorBox(错误, 后端端口${BACKEND_PORT}已被占用请关闭占用程序后重试。);app.quit();}});// 7. 后端退出事件如异常崩溃backendProcess.on(exit, (code) {console.log([Backend], 进程退出代码${code});backendProcess null;// 若后端异常退出关闭Electron应用if (code ! 0 app.isReady()) {dialog.showErrorBox(错误, 后端进程异常退出请重启应用。);app.quit();}});
}function createWindow() {const win new BrowserWindow({width: 1000,height: 800,title: 简单网页,webPreferences: {preload: path.join(__dirname, preload.js)}})ipcMain.on(file-save, writeFile)ipcMain.handle(file-read, readFile)// 加载前端页面兼容开发/生产环境if (app.isPackaged) {console.log(pro)} else {console.log(dev)}//自定义菜单项let menuTemp [{label: 文件,submenu: [{label: 打开文件,click() {console.log(打开一个具体的文件)}},{ label: 打开文件夹 },{label: 关于,role: about}]},{ label: 编辑 }]//生成自定义菜单let menu Menu.buildFromTemplate(menuTemp)Menu.setApplicationMenu(menu)win.loadFile(index.html)// 创建并显示通知const notification new Notification({title: 主进程通知,body: 恭喜你学会了求雨之术风来~雨来~}).show();// 确保在窗口创建后调用 openDevToolswin.webContents.on(did-finish-load, () {win.webContents.openDevTools();});// 定时发送时间给渲染进程每1秒setInterval(() {if (win !win.isDestroyed()) {win.webContents.send(main-time, new Date().toLocaleTimeString());}}, 1000);
}
app.whenReady().then(() {startBackend(); // 启动后端先启动后端再创建窗口createWindow(); // 创建主窗口})// 应用退出前确保后端进程终止
app.on(will-quit, () {if (backendProcess) backendProcess.kill();
}); 2、index.html
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0meta http-equivContent-Security-Policy contentdefault-src self; connect-src self http://localhost:8080;
link relstylesheet hrefstyles.css
/headbodydiv idtime当前时间加载中.../divdiv classhint注意输入内容可以保存到d:/hello.txt点击读取可以读取该文件内容/divinput idinput typetextbutton idbtn2向D盘输入hello.txt/buttonbrbrhrbutton idbtn3读取D盘hello.txt/buttonbrbrhrbutton idsendRequest点击发送请求/buttondiv idresult/divscript typetext/javascript src./render.js/script
/body/html 3、render.js
const timeElement document.getElementById(time);
const btn2 document.getElementById(btn2);
const btn3 document.getElementById(btn3);
const btn4 document.getElementById(sendRequest);
const resultDiv document.getElementById(result);
const input document.getElementById(input);btn2.onclick () {myAPI.saveFile(input.value)
}btn3.onclick async () {let data await myAPI.readFile()alert(data)
}// 定义常量
const API_URL http://localhost:8080/getcode;
const METHOD GET;// 绑定按钮点击事件
btn4.onclick async () {try {// 发送 GET 请求const response await fetch(API_URL, { method: METHOD });// 检查响应状态if (!response.ok) {throw new Error(HTTP error! status: ${response.status});}// 解析字符串数据const data await response.text(); // 使用 text() 方法解析字符串// 将数据回显到页面上resultDiv.innerHTML p classsuccess请求成功br返回数据:/ppre${data}/pre;} catch (error) {resultDiv.innerHTML p classerror请求失败请检查网络或后端服务是否正常运行/p;}
};// 监听主进程发送的时间消息
myAPI.onMainTime((time) {timeElement.textContent 当前时间${time};
}); 4、preload.js
const { contextBridge, ipcRenderer } require(electron)contextBridge.exposeInMainWorld(myAPI, {saveFile: (data) {ipcRenderer.send(file-save, data)},readFile: () {return ipcRenderer.invoke(file-read)},// 监听主进程发送的时间消息onMainTime: (callback) {ipcRenderer.on(main-time, (event, time) callback(time))}
}) 5、package.json scripts: {start: electron .,build: electron-builder --win --x64,package: electron-packager . construction --win --out build --archx64 --version1.0.0 --overwrite --iconstatic/images/128.ico,make: electron-forge make},build: {appId: com.xiaoyumao.demo,extraResources: {from: resources/helloworld-0.0.1-SNAPSHOT.jar,to: resources/helloworld-0.0.1-SNAPSHOT.jar},win: {target: [{target: nsis,arch: [x64]}]},nsis: {oneClick: false,perMachine: true,allowToChangeInstallationDirectory: true}}, Electron中集成jar
1、先得有jar包
使用springboot技术快速生成一个web应用。写一个getcode接口 GetMapping(/getcode)public String getcode(){UUID randomUUID UUID.randomUUID();String uuidWithoutHyphens randomUUID.toString().replace(-, );return 随机编码uuidWithoutHyphens;}
在浏览器测试的访问一下 没啥问题后用maven进行打包生成可以独立运行的jar 2、child_process启动jar
由Electron主进程Node环境创建的独立进程来启动jar child_process.spawn() 用于创建一个子进程并实时监听其输入和输出。 java -jar C:\Users\lenovo\electron-basics\resources\helloworld-0.0.1-SNAPSHOT.jar --server.port80803、resource目录 还需要在package.json配置extraResources 用于在构建 Electron 应用程序时将额外的资源文件打包到最终的应用程序安装包中。它的主要作用是确保应用程序所需的资源文件能够正确地随应用一起发布而不会丢失。 extraResources: {from: resources/helloworld-0.0.1-SNAPSHOT.jar,to: resources/helloworld-0.0.1-SNAPSHOT.jar},
在 Electron 中process.resourcesPath 指向的是应用程序的资源目录。 if (app.isPackaged) {// 生产环境打包后资源目录为process.resourcesPathreturn path.join(process.resourcesPath, resources, JAR_FILENAME);}
在这里资源文件都放在了electron本身生成的resources目录中 4、假如没有JAVA_HOME环境
有些情况就是电脑它没有javahome环境或者有但是配置的不是我们想要的jdk1.8。。
所以我决定打包的时候把jre环境也打进去jar启动原理就是下面这样的
C:\Users\lenovo\electron-basics\resources\jre\bin\java -jar C:\Users\lenovo\electron-basics\resources\helloworld-0.0.1-SNAPSHOT.jar --server.port8080在resource目录下把jre环境放进去。 package.json就得改变了 extraResources: [{from: resources/jre,to: resources/jre},{from: resources/helloworld-0.0.1-SNAPSHOT.jar,to: resources/helloworld-0.0.1-SNAPSHOT.jar}],
在main.js中关于启动jar包的命令、对java环境的检查等都要用xxx\jre\bin\java去检查
在安装软件后目录是这样的 现在就算没有JAVA_HOME也照样可以运行 JSP应用
如果项目之前是用jsp写的那么能不能啥都不改的情况下直接访问l