将Javascript属性连接到Java对象

时间:2016-09-27 17:50:43

标签: javascript java dom nashorn

问题

我正在尝试将Java对象提供给通常在网页的文档对象模型(DOM)上运行的脚本。在大多数情况下,这可以按预期运行。但是,在处理DOM元素的属性/属性时遇到了问题。

感兴趣的特定属性链是somediv.firstChild.href。我无法弄清楚如何动态获取firstChild属性值。我现在能想到的最简单的方法是使用source.replaceAll("firstChild", "firstChild()");强制firstChild属性来调用函数firstChild()。然而,这最终会开辟出新的蠕虫病毒。

问题

如何定义一个可以传递给可以通过DOM操作的javascript函数的对象?

背景

从C#中学习

在深入研究Java之前,我学会了C#。在C#中,setter和getter的概念非常普遍。如果这个接口方法在Java中可用,我的问题就会解决。

public string firstChild {
    get { return this.getFirstChild(); }
    set { this.setFirstChild(value); }
}

当前实施

该脚本目前通过将其包装在一个函数中来调用,我可以将windowdocument Java对象传递到函数工作区。

documentSpoofedDomElement的特殊顶级版本(扩展了它),但在功能上与下面显示的示例相同。 window是具有处理事件侦听器的最小函数的另一个对象。

在DOM上操作的Javascript(代码段)

var somediv = document.createElement('div');
somediv.style.display = "block"
somediv.innerHTML="<a href='/mywork/server/test.html'>The Test Server Homepage</a>";
var linkvalue = somediv.firstChild.href;

此代码段存储为字符串theOriginalSource,并在下一部分中使用。

评估Javascript的Java代码

String wrappedSource = "var scriptToInvoke = function(window, document){"
    + "\n" + theOriginalSource // from above
    + "\n};"

Object result = invocable.invokeFunction("scriptToInvoke", window, document);

此代码段包装了javascript代码段,以便我可以传入对象以用作windowdocument

欺骗DOM元素的Java类

public class SpoofedDomElement {
    public SpoofedDomElement firstChild;
    public String id;
    public String innerHtml;
    public String href;
    public SpoofedStyleProperties style = new SpoofedStyleProperties();
    public String tagname;
    ...
}

public class SpoofedStyleProperties {
    public String background = "transparent none repeat scroll 0% 0% auto padding-box border-box";
    public String color = null;
    public String display = "inline";
}

以上类处理代码的不相关部分(例如赋值somediv.style.display = "block")。但是当任何一个值发生变化时,处理firstChildinnerHtml的值时,它会开始崩溃。

过去的工作

N.B。我在所有问题中都包含此部分,以记录我为未来的Google用户所尝试的内容。这可能有助于某人通过帮助头脑风暴来达成解决方案。

尝试解决方案

我试图使用框架(HtmlUnit)来评估Javascript。但我无法控制执行哪些Javascript片段。

潜在解决方案

以下是我目前正在研究寻找解决方案的问题。如果我发现了什么,我会报告回来。

  • 有没有办法在Java中模拟C#getter / setter行为?
  • Javascript可以将firstChild评估为函数吗?
  • 有没有办法在Javascript中使用可以调用我的Java类函数的getter / setter创建包装器?
  • Nashorn(或类似)的Apache Commons库是否与完整的模拟框架(例如Selenium)一样重??

1 个答案:

答案 0 :(得分:1)

您似乎正在尝试从Java代码实现脚本对象的友好访问,以及尝试在Java库/库之上提供脚本友好的API。

第一部分[从Java访问脚本对象]

除了javax.script.Invocable接口之外,您还可以使用JSObject。 Nashorn将脚本对象公开为jdk.nashorn.api.scripting.JSObject / .ScriptObjectMirror

的实例

https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html

第二部分[从脚本中更友好地访问Java对象]

您可以使用“JSAdapter”在脚本本身编写脚本友好包装器。

文档和示例:

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-JSAdapterconstructor

如果你更喜欢用Java做,你可以实现自己的jdk.nashorn.api.scripting.JSObject / .AbstractJSObject。

文档和示例:

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-jsobject

其他nashorn特定脚本扩展也可用于捕获基于每个对象的未知属性/方法访问:

任何脚本对象中的

noSuchProperty 挂钩:

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-noSuchProperty

任何脚本对象中的

noSuchMethod 挂钩:

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-noSuchMethod

Object.bindProperties:

脚本API扩展可用于将一个对象的属性绑定到另一个 - 源对象也可以是Java对象。

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-Object.bindProperties

使用jdk9,可以使用Dynalink API进行更灵活的语言间链接[http://openjdk.java.net/jeps/276]

另见:

https://blogs.oracle.com/sundararajan/entry/dynamic_linker_api_for_the

https://blogs.oracle.com/sundararajan/entry/writing_pluggable_dynalink_linker_and

https://blogs.oracle.com/sundararajan/entry/nashorn_javascript_access_to_python

Nashorn OpenJDK存储库中有dynalink示例“samples / dynalink”目录:

http://hg.openjdk.java.net/jdk9/dev/nashorn/file/4a6ee1185fc8/samples/dynalink