public class User implements Serializable {
private static final long serialVersionUID = 7439853194483038885L;
public String name;//必须用public
public Integer age;
public User() {
super();
}
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
//省略GET、SET
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
TestUtil类,JS调用Java方法用。
public class TestUtil {
public static Integer add(Integer a,Integer b) {
return a+b;
}
}
JS文件,Java调用JS用。
// JS使用JAVA方法
var ju=Java.type('TestUtil');
function test3(a,b){
return ju.add(a,b);
}
// JS将传入的参数整合为JSON,并返回
function test4(name,age){
var json={};
json.name=name;
json.age=age;
return json;
}
TestGraalVM类。
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.TypeLiteral;
import org.graalvm.polyglot.Value;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
public class TestGraalVM {
public static void main(String[] args) throws IOException {
Gson gson = new GsonBuilder().create();
// 必须设置allowAllAccess(true),否则JS无法使用JAVA方法
Context context = Context.newBuilder().allowAllAccess(true).build();
// 获取JS数组的某个值
Value array = context.eval("js", "[1,2,42,4]");
int result = array.getArrayElement(2).asInt();
System.out.println("JS数组第三个数值:" + result);
// 执行JS Function 无返回结果
System.out.println("=======执行JS Function 无返回结果=======");
String jsFunWithoutResult = "function test(a,b,c){var result= a+b+c;console.log('JS执行结果:'+result);}";
context.eval(Source.create("js", jsFunWithoutResult));
context.getBindings("js").getMember("test").execute(1, 2, 3);
System.out.println("======执行JS内置函数 有返回结果=====");
Value vMath = context.getBindings("js");
vMath.putMember("a", 1);
vMath.putMember("b", 2);
System.out.println("执行JS内置函数:" + context.eval(Source.create("js", "Math.max(a,b)")).asInt());
// 执行JS Function,并返回结果
System.out.println("=======执行JS Function 有返回结果=======");
String jsFun = "function add(x,y){var result=x+y;console.log('JS返回结果:'+result);return result;}";
context.eval(Source.create("js", jsFun));
Long re = context.getBindings("js").getMember("add").execute(10, 20).asLong();
System.out.println("执行JS Function,并返回结果: " + re);
// 获取JS定义的对象、数组。
String jsObj = "var intarr=[1,2,3];var msg = 'hello';var json={'name':'张三','age':18};var users=[{'name':'张三','age':18},{'name':'李四','age':22}]";
context.eval("js", jsObj);
System.out.println("======Int数组=====");
Value v = context.getBindings("js").getMember("intarr");
TypeLiteral> INT_LIST = new TypeLiteral>() {
};
List ll = v.as(INT_LIST);
for (Integer i : ll) {
System.out.println("JS定义的INT数组:" + i);
}
System.out.println("JS定义的字符串:" + context.getBindings("js").getMember("msg").asString());
System.out.println("=======JS定义的 JSON 实体类========");
User userPojo = gson.fromJson(gson.toJson(context.getBindings("js").getMember("json").as(Map.class)),
new TypeToken() {
}.getType());
System.out.println(userPojo.toString());
System.out.println("======JS定义的 JSON 实体类列表=====");
// JS的JSONArr转为JAVA实体类的写法一
Value uv = context.getBindings("js").getMember("users");
System.out.println("列表总数:" + uv.getArraySize());
for (int i = 0; i < uv.getArraySize(); i++) {
System.out.println(new User(uv.getArrayElement(i).getMember("name").asString(),
uv.getArrayElement(i).getMember("age").asInt()).toString());
}
// JS的JSONArr转为JAVA实体类的写法二
System.out.println("--------------------");
String jsonList = gson.toJson(context.getBindings("js").getMember("users").as(List.class));
List us = gson.fromJson(jsonList, new TypeToken>() {
}.getType());
for (User user : us) {
System.out.println(user.toString());
}
// GraalVM官方是很不推荐使用JS访问Java类或文件系统的,所以默认采用了安全的方法
// 但是在我们之前使用Nashorn的时候,因为其支持的ECMAScript版本较低,很多基本特性无法使用,例如没有Map、Set等。为了适应业务需要,有大量JS调用Java对象的代码,此处也写了相关的Demo。
// 不过还是不推荐这么做,GraalVM已经支持ES6,相关特性应该足以替代Java对象。
// 即便是JS做不到的功能,也推荐采用HTTP接口的方式进行调用。
System.out.println("=======JS Function 执行JAVA类方法=======");
String myJavaFun = "var ju=Java.type('TestUtil');function test2(a,b){return ju.add(a,b)}";
context.eval(Source.create("js", myJavaFun));
Integer i2 = context.getBindings("js").getMember("test2").execute(1, 2).asInt();
System.out.println(i2);
System.out.println("========JS 接收对象============");
User param = new User("姓名", 44);
//User类的属性在这里必须设置成public,只有这样,JS里面才能通过user.name的形式获取到值
String jsPojoParam = "function test5(user){console.log(user);console.log(user.name);console.log(user.age)}";
context.eval(Source.create("js", jsPojoParam));
context.getBindings("js").getMember("test5").execute(param);
System.out.println("=========JS文件===========");
//注意此处test.js的地址,在本机或服务器运行时,要根据实际路径进行修改
String jsFile = FileUtils.readFileToString(new File("test.js"), "utf-8");
context.eval(Source.create("js", jsFile));
Integer i3 = context.getBindings("js").getMember("test3").execute(1, 2).asInt();
System.out.println("执行Function:" + i3);
User user2 = gson.fromJson(
gson.toJson(context.getBindings("js").getMember("test4").execute("张三", 66).as(Map.class)),
new TypeToken() {
}.getType());
System.out.println("获取返回JSON:" + user2.toString());
System.out.println("=========ES 6===========");
context.eval(Source.create("js",
"var map=new Map();map.set('name','张三');map.set('age',55);map.set('name','李四');for(var [k,v] of map){console.log(k+'='+v)}"));
context.eval(Source.create("js",
"let arr=['苹果','桔子','梨'];console.log(...arr);let breakfast=arr.map(fruit => {return '吃'+fruit;});console.log(breakfast);"));
}
}