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

angular-electron调用java

Angular-Electron中调用Java程序

文章目录

  • Angular-Electron中调用Java程序
    • 1. 集成Java环境
    • 2. 准备 Java 文件 和 Jar 包
    • 3. 编译 Java 文件
    • 4. 执行 class 文件
    • 5. 问题和答案
    • 6. 完整代码展示

Angular-Electron项目中牵涉到的一些配置,在其他项目比如Electron-Vue项目中可能不太一样,但是思路一致,只需要找到自己的项目的配置方法即可。

1. 集成Java环境

集成环境比较简单,直接把Java环境整个放到项目里即可。但是有两点需要注意下:

  1. Java8Java17 为例,二者的文件构成不太一样:

    • 如果是 Java 8,那么安装之后会有一个jre目录,这是Java的运行时环境,集成时只需要把整个jre目录拷贝到项目中即可。
    • 如果是 Java17,因为OracleJava 9开始就简化了安装,选择不再单独安装 JREJava 17 只提供了 JDK,运行时环境(JRE)被集成在 JDK 中,因此只会看到一些可执行文件,而没有单独的 JRE 目录。集成时我们也只需要把包含有这几个可执行文件(java.exe, javac.exe....)的目录直接拷贝到项目中即可。
  2. Java环境文件位置

    因为后续需要执行Java命令,这要求命令执行时环境要处于 Java 环境下,所以 Java 环境文件的位置我们要在项目中能定位到。

    Angular-Electron项目为例

    • 我习惯在项目根目录下创建一个和 src 平级的 plugins 目录,把 Java 17 环境目录放到了 plugins 目录下,这样我在执行命令行需要定位目录时,只需要写:plugins/jre即可,如果是 Java 8 的话可能需要写 plugins/jre/bin

    • electron-build.json 中配置一下额外资源打包:

      {"extraResources": [{"from": "plugins","to": "plugins","filter": ["**/*"]}],
      }
      

      这样就可以在打包时把 plugins 时原封不动的打包进去,应用程序安装之后,就可以在resources目录下看到。

      题外话:在生产环境下的目录拼接,只需要在 Electron 主进程下获取下process.cwd(),然后渲染进程拿到这个项目运行绝对路径,然后再拼接上resouces/plugins/xxx 就能在生产环境下定位到 java 环境位置。

2. 准备 Java 文件 和 Jar 包

还是同样的,我把需要的 Java 文件以及 Jar 包也放到了 plugins 目录下,也是为了在生产环境下方便找到。

所以,目前我的 plugins 目录的构成是这样:

----- plugins------- jar
--------- pinyin4j
----------- pinyin4j-2.5.0.jar------- java
--------- PinyinConverter.java------- jre
--------- java.exe
--------- javac.exe
--------- ...

可以看到,我使用到了一个汉字转拼音的 jarpinyin4j,然后写了一个 javaPinyinConverter.java 测试。

PinyinConverter.java

import net.sourceforge.pinyin4j.PinyinHelper;public class PinyinConverter {public static void main(String[] args) {if (args.length == 0) {return;}String chineseInput = args[0];StringBuilder pinyinOutput = new StringBuilder();for (char c : chineseInput.toCharArray()) {String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);if (pinyinArray != null && pinyinArray.length > 0) {pinyinOutput.append(pinyinArray[0]).append(" ");} else {pinyinOutput.append(c).append(" "); // 如果没有拼音,原字符输出}}System.out.println(pinyinOutput.toString().trim());}
}

文件准备不是重点,这里主要是为防止后面出现jar包和java路径时造成阅读困难。

接下来正片开始:

3. 编译 Java 文件

说一些编译前的准备:

  1. 我写了一个从主进程中获取程序运行绝对路径的方法getProgramRunPath,所以后面不要被IPC.getProgramRunPath()方法影响。

  2. 因为目录有点多,所以我抽离了一个路径拼接方法joinPluginsFolderPath()

    joinPluginsFolderPath(p: string): string {return APP_CONFIG.production ? path.join('resources/plugins', p) : path.join('plugins', p);
    }
    

    传进来一个路径,自动根据当前的环境来判断是否要拼接前置路径。

OK,开始编译。

编译 Java 文件主主要用到的命令是:

javac -cp <classpath> <source-files># <classpath> 是用分号(在 Windows 上)或冒号(在 Unix/Linux 上)分隔的目录或 JAR 文件路径。# <source-files> 是要编译的 Java 源文件。

那对应到 PinyinConverter.java 实际使用上就是这样:

// 注意:rp 是我通过`IPC.getProgramRunPath()`拿到的项目运行绝对路径,这个方法后续会出现。// 其实就相当于:const javaFilePath = 'D:/xxx/xx/xxx/plugins/java/PinyinConverter.java'; 当然了生产环境下前面plugins前面还有个resources
// java 类
const javaFilePath = path.join(rp, this.joinPluginsFolderPath('java/PinyinConverter.java'));// jar包
const pinyin4jJar = path.join(rp, this.joinPluginsFolderPath('jar/pinyin4j/pinyin4j-2.5.0.jar'));// 编译命令
const compileCommand = `javac -cp ".;${pinyin4jJar}" "${javaFilePath}"`;

接下来,执行编译命令,命令执行需要在java环境下:

// 注意子进程 exec 方法的 cwd 配置,path.join(rp, this.joinPluginsFolderPath('jre') 相当于直接拼接了一个项目jre目录的绝对路径。这保证了命令的执行在java环境下。exec(compileCommand, { cwd: path.join(rp, this.joinPluginsFolderPath('jre')) }, (err, stdout, stderr) => {if(err) {console.error(`编译错误: ${stderr}`);reutrn;}
});

如果命令执行成功,那么你就会在 plugins/java目录下看到一个和 PinyinConverter.java 同级的 PinyinConverter.class文件。

接下来就进入第四步,执行class文件:

4. 执行 class 文件

执行 class 文件需要用到 java -cp 命令,具体是这样:

java -cp <classpath> <main-class># <classpath> 是用分号(在 Windows 上)或冒号(在 Unix/Linux 上)分隔的目录或 JAR 文件路径。 # <main-class> 是包含 main 方法的主类。
const runCommand = `java -cp ".;${pinyin4jJar};D:\\xxxx\\plugins\\java" PinyinConverter "你在我的剧本里杀青了"`;// 解释下这个命令:
// 命令中`D:\\xxxx\\plugins\\java` 指定的是编译后的class文件所在目录的绝对路劲,PinyinConverter 是类名。
// "你在我的剧本里杀青了" 这是传递给 PinyinConverter类方法的参数,这个转换的中文我写死了,也可以弄个变量 "${this.yourChinese}". 只要前面的拼接正确就行。

然后执行这个命令:

exec(runCommand, { cwd: path.join(rp, this.joinPluginsFolderPath('jre')) }, (err, stdout, stderr) => {if (err) {console.error(`执行错误: ${stderr}`);return;}console.log(`输出结果: ${stdout}`);
});

如果没有出错,那么就能在控制台看到输出结果。

5. 问题和答案

Q1:必须要执行编译吗?

A1: 不需要,可以私下里先编译好java程序,直接把java类放到目录下直接执行java类也是一样的。

Q2:生产环境下目录问题编译不出来对应的java类?

A2:这里提供一个解决问题的思路,具体问题具体分析,目录问题我指的是因为程序安装之后的目录没有权限读写导致java程序无法正常编译生成java

  1. 可以私下里先编译好运行时直接执行java类,这样避免去创建java类的操作。

  2. 指定java类的生成地址,用-d 参数指定:

const compileCommand = `javac -cp ".;${pinyin4jJar}" -d output "${javaFilePath}"`;
// -d output 指定了生成的 .class 文件存放在 output 目录。
  1. 换个java文件存放目录,比如可以通过electrongetPath方法获取下用户的userData目录。
    此时就不要把 .java 文件放到plugins目录下了,我们需要构建一个java程序代码字符串,然后获取到userData目录后,通过node的write方法创建一个.java文件并把 java程序代码字符串写进去,相当于在userData目录下手动构建了一个PinyinConverter.java文件
    这样后续执行编译时也不会出现权限问题。

Q3:Java程序没用到jar包?

Q3:那只需要改下命令,以编译命令为例:(执行命令同理)

// 编译命令 用到jar包
const compileCommand = `javac -cp ".;${pinyin4jJar}" "${javaFilePath}"`;// 编译命令 没用到jar包
const compileCommand = `javac -cp "${javaFilePath}"`;

6. 完整代码展示

@Component({selector: 'app-tplpage',templateUrl: './tplpage.component.html',styleUrl: './tplpage.component.scss'
})
export class TplpageComponent {public chinese = '你在我的剧本里杀青了';public pinyinConverter() {// 获取程序运行绝对路径IPC.getProgramRunPath().subscribe(rp => {// java 类const javaFilePath = path.join(rp, this.joinPluginsFolderPath('java/PinyinConverter.java'));// jar包const pinyin4jJar = path.join(rp, this.joinPluginsFolderPath('jar/pinyin4j/pinyin4j-2.5.0.jar'));// 编译命令const compileCommand = `javac -cp ".;${pinyin4jJar}" "${javaFilePath}"`;exec(compileCommand, { cwd: path.join(rp, this.joinPluginsFolderPath('jre')) }, (err, stdout, stderr) => {if (err) {console.error(`编译错误: ${stderr}`);return;}console.log(`编译成功`);// 执行编译命令(ae_archadm是项目文件夹名称)const runCommand = `java -cp ".;${pinyin4jJar};D:\\ae_archadm\\plugins\\java" PinyinConverter "${this.chinese}"`;exec(runCommand, { cwd: path.join(rp, this.joinPluginsFolderPath('jre')) }, (err, stdout, stderr) => {if (err) {console.error(`执行错误: ${stderr}`);return;}console.log(`输出结果: ${stdout}`);});});});}// 拼接地址public joinPluginsFolderPath(p: string): string {return APP_CONFIG.production ? path.join('resources/plugins', p) : path.join('plugins', p);}
}

http://www.mrgr.cn/news/57451.html

相关文章:

  • edge浏览器:你的连接不是专用连接
  • 服务器数据恢复—EXT3文件系统下邮件数据被误删的数据恢复案例
  • 腾讯云:数智教育专场-学习笔记
  • mysql表添加索引
  • 数据操作学习
  • ISO 21434:重塑汽车网络安全与数据保护的行业标准
  • 企业团队经典的激励理论:期望理论、赫茨伯格双因素理论、马斯洛需求层次理论、X理论和Y理论
  • 分布式系统中的Session管理:实现跨服务器的用户会话共享
  • 【数据结构】顺序表和链表
  • 【1024程序员节】之C++系列完结篇:Web编程
  • Java8项目如何升级到Java21?有啥坑?
  • 今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 10月24日,星期四
  • 代码随想录算法训练营第53天|107. 寻找存在的路径(并查集)
  • 【MyBatis面试题】
  • 数据资产入表:政策与实践全面解读
  • 经典WinCC移植到WinCC Professional
  • 行为设计模式 -责任链模式- JAVA
  • 1024程序员节 | 1024征文
  • 探索AI的文本匹配秘诀:使用Python实现关键词搜索与RAG知识库匹配
  • js数据类型,类型检测,类型转换
  • 分组密码工作模式
  • 在示波器上观察到李萨如图形应如何调节
  • 亚马逊扛不住了!其低价商城或在11月上线,开卷Temu和Shein
  • [专有网络VPC]使用ClassicLink连通经典网络与VPC
  • Python酷库之旅-第三方库Pandas(164)
  • Python酷库之旅-第三方库Pandas(165)