V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jokerboozp
V2EX  ›  Java

怎么在 Java 后端执行 Node.js 代码并且返回结果给前端

  •  
  •   Jokerboozp · 257 天前 · 2783 次点击
    这是一个创建于 257 天前的主题,其中的信息可能已经有所发展或是发生改变。

    单位之前用的 Thingworx 物联网平台,里面有一个编写 Node.js 代码的编辑器,编辑之后可以直接运行显示结果。最近让我整体搬到新项目里面,说是前端没办法运行,要把 js 代码传给后端让后端运行。 里面有一些自定义的语法,我的想法是关键字匹配,如果匹配到关键字,就执行对应的操作,然后再把执行之后的结果和剩下的 js 拼接起来。 但是这样做的话就有点像一个 js 翻译器了,而且效率并不高。 我找了半天,实在没有好办法。各位大佬有没有好一点的解决方法。https://ice.frostsky.com/2023/08/14/3f6c0074202ec7d325673a21efe90f31.png

    第 1 条附言  ·  256 天前
    各位大佬说的都看了,感觉最优解应该还是写一个 Node 服务器来的方便。但是还有一个问题:
    js 里面会有“let dataInfo = Things["Localhost.PostgreSQL.Database.Thing"].Update({
    updateString: sql /* STRING */
    });”这样的代码,它需要连接数据库进行查询找到对应的 Update 方法的内容,我在 Node 服务器里面应该怎么执行这个操作呢?
    44 条回复    2023-08-28 10:15:10 +08:00
    biubiuGolang
        1
    biubiuGolang  
       257 天前
    GraalVM
    gitignore
        2
    gitignore  
       257 天前
    直接执行 shell 命令不行吗

    ```sh
    node --eval="JavaScript 脚本"
    ```
    brucedone
        3
    brucedone  
       257 天前
    一般都是 node.js 封装成 http 服务,java 后端来调用,尽量别同进程跨解释器,会有一定的兼容问题。
    mmdsun
        4
    mmdsun  
       257 天前
    Java 有 ScriptEngine 能执行一些简单的 js 代码,表达式之类的。
    复杂的话,你用 Java 运行 node 命令,读取流返回结果也行吧?
    pkoukk
        5
    pkoukk  
       257 天前
    如果只是简单的脚本的话,1# 的就可以
    如果需要解析依赖,或者 import 标准库的话,可以搞个 node 服务,把编辑后的脚步发到那个服务去执行
    mightybruce
        6
    mightybruce  
       257 天前
    如果是复杂的服务,还是通过服务调用服务的方式

    简单的执行逻辑可以通过一些 js runtime 以及 js ast 解析来做。
    virusdefender
        7
    virusdefender  
       257 天前
    runtime.getRuntime().exec 应该是最佳选择了
    guilinxiaobing
        8
    guilinxiaobing  
       257 天前
    远程调用最省心吧
    mightybruce
        9
    mightybruce  
       257 天前
    有一些 Java 实现的 JavaScript 引擎,可以直接被 java 调用,比如 Rhino 和 Nashorn
    Jokerboozp
        10
    Jokerboozp  
    OP
       257 天前
    @biubiuGolang
    @mmdsun
    @mightybruce
    javascript 引擎我试过,但是目前单位的 js 代码里会有一些例如“let dataInfo = Things["Localhost.PostgreSQL.Database.Thing"].Update({
    updateString: sql /* STRING */
    });”
    这样的内容,中括号里面的内容是数据库中的,然后他有一个 Update 方法,参数是用户写的 sql ,我想要执行 js 的话还需要把这段代码执行,然后再把上面那段代码替换成 sql 的执行结果。
    我觉得这样有点太不符合编码常理了
    Jokerboozp
        11
    Jokerboozp  
    OP
       257 天前
    @brucedone 意思是用 Node.js 写一个 http 服务器,然后我把 js 代码直接发给 Node 服务器,接收服务器返回的结果,然后再转发给前端这样嘛
    mightybruce
        12
    mightybruce  
       257 天前
    像这样的不是简单的 js 翻译,涉及到数据库驱动了, 不是表达式,正则,规则匹配引擎。你要么用 java 重写这部分逻辑,要么改装 node.js 变成 node.js 微服务调用 java 服务的形式。
    Jokerboozp
        13
    Jokerboozp  
    OP
       257 天前
    @mightybruce 嗯嗯。就是涉及到的东西实在太多,我才有点不知所措。目前看来最优解貌似是写一个 Node 服务器,然后我用 Java 转发结果。
    biubiuGolang
        14
    biubiuGolang  
       257 天前
    @pkoukk 复杂的也可以 import 标准和第三方都 ok
    biubiuGolang
        15
    biubiuGolang  
       257 天前
    @Jokerboozp 了解一下 esprima 提取出来执行 sql
    cl903254852
        16
    cl903254852  
       257 天前
    搞个 node 的服务,获取到编辑器的代码丢给 node 服务去执行,执行完通知 java ,java 把结果给前端。

    java 就是个中间人,负责传话的
    Jokerboozp
        17
    Jokerboozp  
    OP
       257 天前
    @cl903254852 两个问题:
    1 、如果 Java 只是一个传话的,那为什么还需要 Java 嘞。直接让前端把 js 代码传给 node 服务器就可以了吗不是?
    2 、js 里面会有“let dataInfo = Things["Localhost.PostgreSQL.Database.Thing"].Update({
    updateString: sql /* STRING */
    });”这样的代码,它需要连接数据库进行查询找到对应的 Update 具体是什么,我在 node 服务器里面应该怎么办呢?
    Jokerboozp
        18
    Jokerboozp  
    OP
       257 天前
    @biubiuGolang 可以,我去研究研究
    sofukwird
        19
    sofukwird  
       257 天前 via Android
    quickjs ?
    Jokerboozp
        20
    Jokerboozp  
    OP
       257 天前
    @sofukwird 这个好像不可以,js 代码里会有连接数据库或者查找数据之类的操作
    shyangs
        21
    shyangs  
       257 天前
    把 Java 寫的後端扔了,改用 Node.js 寫後端。
    cl903254852
        22
    cl903254852  
       257 天前
    @Jokerboozp 因为你是执行 node 代码,那肯定 node 环境是最稳妥的。 我的意思是,node 服务只针对你这个编辑器的场景即可,项目其他该用 java 用 java 。node 既然是服务端肯定能连数据库
    des
        23
    des  
       257 天前
    换 Nodejs 来搞吧,感觉其实都差不多,都要写 Things 相关的驱动
    不过我有点好奇,你这 12 行怎么是个同步操作?
    des
        24
    des  
       257 天前
    不建议提取 SQL 来执行,你这前端是个编辑器,鬼知道前端会传什么东西过来

    用 javascript 引擎来做也行,前提也是你得补足“ Things["Localhost.PostgreSQL.Database.Thing"] ” 相关的东西
    wganbleuthall
        25
    wganbleuthall  
       257 天前
    包装成一个 http 服务吧
    WispZhan
        26
    WispZhan  
       257 天前
    lisongeee
        27
    lisongeee  
       257 天前
    可以使用 webcontainer 直接在浏览器运行一个小型的 linux nodejs 进程

    https://webcontainers.io/guides/quickstart

    它由 https://stackblitz.com/ 开发,现在很多文档/问题讨论上的在线 demo 都是基于这个
    lisongeee
        28
    lisongeee  
       257 天前
    艹,你们这个还要连接数据库?那看起来是一个阉割版的远程 nodejs console ,那只能用 远程 nodejs 去执行了
    zhuangzhuang1988
        29
    zhuangzhuang1988  
       256 天前
    包装个 grpc?
    kid1412621
        31
    kid1412621  
       256 天前
    graal
    Jokerboozp
        32
    Jokerboozp  
    OP
       256 天前
    @zhuangzhuang1988 grpc 我还没学明白,有点难度。哈哈哈哈哈哈
    Jokerboozp
        33
    Jokerboozp  
    OP
       256 天前
    @lisongeee 就是因为要连数据库,然后还有一堆自定义的语法,所以我才头大。看了各位大佬的回复看来只有写一个 node 服务才行了
    Jokerboozp
        34
    Jokerboozp  
    OP
       256 天前
    @cl903254852 明白了明白了,多谢大佬
    musi
        35
    musi  
       256 天前 via iPhone
    看了一圈回复都没说到点子上,你这只需要实现 ecma262 规范的引擎也可以认为是 js 引擎基本上就可以执行代码了,你的自定义语法无非是 Thing 这个对象,那你在执行代码的时候提前去定义这个对象就好了,就你给出的代码来说,中括号是属性获取语法,其实就是在获取 Thing 对象的 Localhost.PostgreSQL.Database.Thing 属性,可以用 proxy 语法拦截 getter ,获取到这个 key ,然后是.update ,也就是 Thing 对象的 Localhost.PostgreSQL.Database.Thing 属性值是个对象,对象里面有个 update 方法,你再实现一下就行。
    musi
        36
    musi  
       256 天前 via iPhone
    另外就这个代码来说,只要做好鉴权前端是完全可以执行的
    Jokerboozp
        37
    Jokerboozp  
    OP
       256 天前
    @musi 但是我给出的这个是其中一个的代码,还有其他的 Thing 对象的属性,是由用户自定义来写的,每个属性有哪些方法也是用户自定义来写的。如果按照您说的这样,每一个属性我都实现方法的话,感觉不太能实现诶。刚开始写的时候我是用 jvm 的 js 引擎来写的,我觉得应对这种情况不太可行。
    musi
        38
    musi  
       256 天前 via iPhone
    @Jokerboozp 你还是没理解,属性不管是谁定义它只要定义了就行,平台方和用户方无所谓,你只需要封装特定的 sdk 就行
    musi
        39
    musi  
       256 天前 via iPhone
    @Jokerboozp 你中括号里面的内容,完全是语义化的,host.数据库类型.Datebase.表名,你用 proxy 拦截到 key 时就去找对应的数据库就行了,这也不是说一个属性定义一个方法,完全就是一个通用的方法
    Jokerboozp
        40
    Jokerboozp  
    OP
       256 天前 via iPhone
    @musi 不是的,他有的会写成 Things[thing]这样,这里面不一定是数据库,可能是另一个方法集合的名字,然后他又用里面的某一个方法
    musi
        41
    musi  
       256 天前 via iPhone
    @Jokerboozp 这就相当于一个参数了,不管你是用什么方式你都得自己去实现对应的参数应该执行的方法,不是说你用个 node.js 什么东西写个服务它就自己有这些东西,这个平台是你们自己定义的不是么
    musi
        42
    musi  
       256 天前 via iPhone
    我劝你也别折腾了,让你们公司前端做吧,专业的人做专业的事
    biubiuGolang
        43
    biubiuGolang  
       254 天前
    @Jokerboozp 在 GraalVM 上使用 polyglot 执行多语言是没啥问题的,这里面包括多语言事务和 sandbox 控制,以及在 js 中调用 java java 调用 js ,你如果有了后续的更新可以回一下贴 ~
    Jokerboozp
        44
    Jokerboozp  
    OP
       243 天前
    @biubiuGolang 单位用的 jdk8 ,GraalVM 的新版本不支持,只能用老版本,但是我电脑是 M1 pro 的 MacBook ,又跑不起来老版本的 GraalVM 。所以现在在试着用 J2V8 写
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2866 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:27 · PVG 20:27 · LAX 05:27 · JFK 08:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.