Electron
集成 SpringBoot
后端服务
- 示例中使用的Java版本是1.8
- Electron框架使用的是
electron-vite
, 项目地址:https://cn.electron-vite.org
目录结构
MyElectron
├── resources # 资源文件夹, 不会打包到app.asar中
└── java # java资源
├── jre # jre目录
├── bin
└── lib
├── app-java-server.bat # java启动脚本
└── app-starter.jar # 后端服务的jar包
└── src
├── main # 主进程
├── preload # 预加载
└── renderer # 渲染进程
操作步骤
- 使用SpringBoot框架写好后端服务,并使用maven打包成可执行的jar包。
- 在Electron的主进程中,编写java启动服务。在java启动服务中(server.ts),用来处理环境信息,包括jar包的路径、jre的路径、启动脚本路径和java服务端口等信息,然后调用启动脚本(app-java-server.bat)。在主进程中监听程序的启动和停止,来启停java服务。具体代码如下:
ts
// src/main/java/server.ts
import path from 'path'
import { execFile, execFileSync } from 'child_process'
/**
* 获取java资源路径(包含jre和可执行jar包)
*/
const getBasePath = () => {
if (is.dev) {
return path.join(__dirname, '../../resources/java')
} else {
const appPath = app.getAppPath()
const appDirPath = path.dirname(appPath)
return path.join(appDirPath, 'app.asar.unpacked', 'resources', 'java')
}
}
class JavaServer {
/**
* java 服务基础路径
*/
private basePath = getBasePath()
/**
* jre 路径
*/
private jrePath = path.join(this.basePath, 'jre')
/**
* jar包的名称
*/
private jarName = 'app-starter.jar'
/**
* jar包的路径
*/
private jarPath = path.join(this.basePath, this.jarName)
/**
* bat脚本路径
*/
private batPath = path.join(this.basePath, 'app-java-server.bat')
/**
* java服务使用的端口号
*/
private port: number = 8080
async start() {
if (!platform.isWindows) {
throw new Error('暂不支持非windows平台')
}
const args = [this.jarPath, this.jrePath, this.port, 'start']
execFile(this.batPath, args, {
cmd: path.dirname(this.batPath),
encoding: 'utf8'
})
return this.port
}
stop() {
const args = [this.jarPath, this.jrePath, this.port, 'stop']
execFileSync(this.batPath, args, {
cmd: path.dirname(this.batPath),
encoding: 'utf8'
})
}
}
export default new JavaServer()
bat
:: resources/java/app-java-server.bat
@echo off
set AppName=MyElectronJavaServer
set APP_PATH=%1
set JAR_HOME=%2
set APP_PORT=%3
set JAVAW_EXE=%JAR_HOME%\bin\javaw.exe
set JPS_EXE=%JAR_HOME%\bin\jps.exe
set JAVA_OPT=-server -Xms512M -Xmx512M -Xss512k -Dserver.port=%APP_PORT% -Dname=%AppName%
if "%~4" == "" (
set commond=start
) else (
set commond=%4
)
for /f "usebackq tokens=1" %%a in (`%JPS_EXE% -v ^| findstr %AppName%`) do (
set pid=%%a
)
if "%commond%" == "start" (
if not defined pid (
start %JAVAW_EXE% %JAVA_OPT% -jar %APP_PATH%
echo starting...
echo Start %AppName% success...
) else (
echo %AppName% is already running
)
) else if "%commond%" == "stop" (
if not defined pid (echo process %AppName% does not exists) else (
echo prepare to kill %AppName%
echo start kill %pid% ...
taskkill /f /pid %pid%
)
) else (
echo "only support 'start' or 'stop' command"
exit /b 1
)
exit /b 0
ts
// src/main/index.ts
import javaServer from './java/server'
// 项目启动时
app.on('ready', async () => {
// 启动java
await javaServer.start()
})
// 程序退出之前
app.on('before-quit', () => {
// 退出java
javaServer.stop()
})
注意
Java 1.8中的jdk和jre是分开的,而jps
命令正好是jdk包中的指令,如果想要在jre中也能使用jps
指令的话,需要将jdk/bin/jps.exe
和jdk/lib/tools.jar
复制到jre/bin
和jre/lib
下,这样就可以通过jps
的绝对路径来使用啦 ~