Skip to content

Electron 集成 SpringBoot 后端服务


目录结构

MyElectron
├── resources                   # 资源文件夹, 不会打包到app.asar中
  └── java                      # java资源
    ├── jre                     # jre目录
      ├── bin       
      └── lib  
    ├── app-java-server.bat     # java启动脚本
    └── app-starter.jar         # 后端服务的jar包
└── src
  ├── main                      # 主进程
  ├── preload                   # 预加载
  └── renderer                  # 渲染进程

操作步骤

  1. 使用SpringBoot框架写好后端服务,并使用maven打包成可执行的jar包。
  2. 在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.exejdk/lib/tools.jar复制到jre/binjre/lib下,这样就可以通过jps的绝对路径来使用啦 ~