使用Jsoup,我在html文件中提取JavaScript部分。并将其存储为java String Object。
我想使用 javax.script.ScriptEngine
在js的函数中提取函数列表,变量列表JavaScript部分有几个功能部分。
离)
function a() {
var a_1;
var a_2
...
}
function b() {
var b_1;
var b_2;
...
}
function c() {
var c_1;
var c_2;
...
}
我的目标就在下面。
一 b ç
A_1 a2 ...
B_1 B_2 ...
C_1 C_2 ...
如何提取功能列表和变量列表(或可能是值)?
答案 0 :(得分:0)
我认为你可以通过在引擎中加载javascript后使用javascript自省来实现这一点 - 例如功能:
ScriptEngine engine;
// create the engine and have it load your javascript
Bindings bind = engine.getBindings(ScriptContext.ENGINE_SCOPE);
Set<String> allAttributes = bind.keySet();
Set<String> allFunctions = new HashSet<String>();
for ( String attr : allAttributes ) {
if ( "function".equals( engine.eval("typeof " + attr) ) ) {
allFunctions.add(attr);
}
}
System.out.println(allFunctions);
我还没有找到一种方法来提取函数(局部变量)中的变量,而无需深入研究javascript脚本引擎的内部机制(因此使用不安全)。
答案 1 :(得分:0)
这很棘手。 ScriptEngine
API似乎不适合检查代码。所以,对于instance of
和cast
运算符,我有这种非常难看的解决方案。
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
for (Map.Entry<String, Object> scopeEntry : bindings.entrySet()) {
Object value = scopeEntry.getValue();
String name = scopeEntry.getKey();
if (value instanceof NativeFunction) {
log.info("Function -> " + name);
NativeFunction function = NativeFunction.class.cast(value);
DebuggableScript debuggableFunction = function.getDebuggableView();
for (int i = 0; i < debuggableFunction.getParamAndVarCount(); i++) {
log.info("First level arg: " + debuggableFunction.getParamOrVarName(i));
}
} else if (value instanceof Undefined
|| value instanceof String
|| value instanceof Number) {
log.info("Global arg -> " + name);
}
}
答案 2 :(得分:0)
我有类似的问题。也许这对其他人有帮助。 我用凹槽作为脚本朗。我的任务是从脚本中检索所有可调用的函数。然后按照某些标准过滤此功能。
不幸的是,这种方法仅适用于groovy ...
获取脚本引擎
public ScriptEngine getEngine() throws Exception {
if (engine == null)
engine = new ScriptEngineManager().getEngineByName(scriptType);
if (engine == null)
throw new Exception("Could not find implementation of " + scriptType);
return engine;
}
编译和评估脚本:
public void evaluateScript(String script) throws Exception {
Bindings bindings = getEngine().getBindings(ScriptContext.ENGINE_SCOPE);
bindings.putAll(binding);
try {
if (engine instanceof Compilable)
compiledScript = ((Compilable)getEngine()).compile(script);
getEngine().eval(script);
} catch (Throwable e) {
e.printStackTrace();
}
}
从脚本中获取函数。我没有找到其他方法如何从除了Reflection之外的脚本中获取所有可调用方法。是的,我知道这种方法取决于ScriptEngine实现,但它是唯一的:)
public List getInvokableList() throws ScriptException {
List list = new ArrayList();
try {
Class compiledClass = compiledScript.getClass();
Field clasz = compiledClass.getDeclaredField("clasz");
clasz.setAccessible(true);
Class scrClass = (Class)clasz.get(compiledScript);
Method[] methods = scrClass.getDeclaredMethods();
clasz.setAccessible(false);
for (int i = 0, j = methods.length; i < j; i++) {
Annotation[] annotations = methods[i].getDeclaredAnnotations();
boolean ok = false;
for (int k = 0, m = annotations.length; k < m; k++) {
ok = annotations[k] instanceof CalculatedField;
if (ok) break;
}
if (ok)
list.add(methods[i].getName());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
}
return list;
}
在我的任务中,我不需要所有的功能,为此我创建自定义注释并在脚本中使用它:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CalculatedField {
}
<强> Script example:
强>
import com.vssk.CalculatedField;
def utilFunc(s) {
s
}
@CalculatedField
def func3() {
utilFunc('Testing func from groovy')
}
通过名称调用脚本函数的方法:
public Object executeFunc(String name) throws Exception {
return ((Invocable)getEngine()).invokeFunction(name);
}