Java与JavaScript的“合作”示例
Java与JavaScript的“合作”示例(Java与JavaScript的相互调用)
在一些项JavaWeb目中,我们可以看到在前端写了一些JavaScript的脚步,后端就可以执行脚本来处理业务逻辑。这里用一个简单的示例来说明他们的调用方法!
1、简单介绍
Java与JavaScript之间的相互调用是指在Java代码中调用JavaScript代码,或者在JavaScript代码中调用Java代码的过程。
Java与JavaScript之间的相互调用可以通过以下方式实现:
- 使用Java的
ScriptEngine
类执行JavaScript代码:Java提供了ScriptEngine
类和相关的API,可以通过这些API在Java代码中执行JavaScript代码。通过ScriptEngine
类,可以创建一个JavaScript引擎,并执行JavaScript代码。这种方式可以在Java代码中调用JavaScript函数或方法。 - 使用Java的
javax.script
包:Java的javax.script
包提供了一组标准API,用于在Java代码中执行脚本语言(如JavaScript)的代码。通过这些API,可以创建一个JavaScript引擎,并在Java代码中调用JavaScript函数或方法。 - 使用Java的Web框架:在Web开发中,可以使用Java的Web框架(如Spring)将Java方法暴露给JavaScript。通过在Java代码中定义一个控制器或服务,可以将Java方法映射到一个URL,并通过AJAX请求从JavaScript中调用该URL,从而实现Java与JavaScript之间的交互。
- 使用Java的桥接技术:Java提供了一些桥接技术,如
JavaFX
的WebView
组件和Rhino
引擎,可以在Java代码中嵌入JavaScript,并在Java代码和JavaScript之间进行相互调用。
需要注意的是Java与JavaScript之间的相互调用需要考虑两种语言的语法和类型系统的差异。在进行相互调用时,需要确保方法的参数和返回值类型是兼容的,并进行必要的类型转换。
2、代码示例
具体原理自行查阅
2.1、主要代码段
这里的Java类主演演示Java与JavaScript的相互调用!具体说明在代码注释中有介绍!
import com.chinacoal.microservice.model.StatusFlowRequest;
import com.chinacoal.microservice.service.ScriptToJavaService;
import com.chinacoal.microservice.service.StatusFlowService;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.Map;
@Service
@Log4j2
public class A implements StatusFlowService {
@Autowired
private ScriptToJavaService scriptToJavaService;
@Override
public Object statusFlow(StatusFlowRequest flowRequest) throws Exception {
log.debug("1、开始测试");
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript");
try {
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
// 定义Map类型的java变量
Map<String, Object> att = new HashMap<>();
att.put("s", "A00");
att.put("a", "1");
att.put("b", 2);
att.put("c", flowRequest);
// TODO 将 Java 变量传递给 JavaScript 环境
engine.put("_data", gson.toJson(flowRequest));
engine.put("_attribute", gson.toJson(att));
// TODO 将 Java方法传递给 JavaScript 环境
// 创建一个Java对象,并将其作为全局变量暴露给JavaScript;调用时直接用类名.方法名()
// 例如1:MyJavaClass myJavaObject = new MyJavaClass();
// 例如2:将通过@Autowired 注入的服务类 scriptToJavaService 暴漏给 Javascript
engine.put("javaClass", scriptToJavaService);
engine.put("log", log);
// JavaScript代码
String script = "print('---- 脚本开始执行 ----');" + // 打印日志到后端控制台
"log.debug(\"执行脚本打印log日志\");" + // 调用日志接口在后端打印日志
"var attribute = JSON.parse(_attribute); " + // 取到java暴露给JavaScript的全局变量
"var status = attribute.s; " +
"print('脚本打印_data:' + JSON.stringify(_data));" +
"print('脚本打印_attribute:' + JSON.stringify(attribute));" +
"var javaReturn = javaClass.testScriptToJava(status);" + // 在JavaScript中调用Java方法并取到java返回值
"print('脚本打印 javaReturn:' + javaReturn);" +
"'exec success!';"; // JavaScript返回内容到Java执行结果中
// TODO 执行 JavaScript 代码,与Java互相调用
Object result = engine.eval(script);
// TODO 从脚本中执行结果中获取JavaScript变量的值
Object status = engine.get("status");
// 打印结果
System.out.println("---> Java 取脚本返回" + result);
System.out.println("---> Java 取脚本变量值:" + status);
} catch (ScriptException se) {
log.error("执行脚本异常:", se);
} catch (Exception e) {
log.error("执行程序异常:", e);
}
return flowRequest;
}
}
完整的JavaScrip代码
print('---- 脚本开始执行 ----'); // 打印日志到后端控制台
log.debug("执行脚本打印log日志"); // 调用日志接口在后端打印日志
var attribute = JSON.parse(_attribute); // 取到java暴露给JavaScript的全局变量
var status = attribute.s;
print('脚本打印_data:' + JSON.stringify(_data));
print('脚本打印_attribute:' + JSON.stringify(attribute));
var javaReturn = javaClass.testScriptToJava(status); // 在JavaScript中调用Java方法并取到java返回值
print('脚本打印 javaReturn:' + javaReturn);
'exec success!';
2.2、JavaScript调用Java Service类
这里不重要,为了展示调用的java方法
public interface ScriptToJavaService {
/**
* javascript 调用java方法
*
* @param data 请求参数
* @return boolean 返回
*/
String testScriptToJava(String data);
}
实现类
import com.chinacoal.microservice.service.ScriptToJavaService;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
@Service
@Log4j2
public class ScriptToJavaServiceImp implements ScriptToJavaService {
/**
* javascript 调用java方法
*
* @param data 请求参数
* @return boolean 返回
*/
@Override
public String testScriptToJava(String data) {
log.debug("---------> javascript 调用java方法 <----------");
log.debug("---------> 接收到javascript传参:" + data);
return "java service return!";
}
}
3、调用后执行结果
这里展示控制台输出结果:
2023-09-07 10:01:55.503 DEBUG 24621 --- [nio-8089-exec-3] c.chinacoal.microservice.service.impl.A : 1、开始测试
---- 脚本开始执行 ----
脚本打印_data:"{\"id\":\"1\",\"action\":\"sign_in\",\"snapAttachment\":\"\"}"
脚本打印_attribute:{"a":"1","b":2,"s":"A00","c":{"id":"1","action":"sign_in","snapAttachment":""}}
2023-09-07 10:01:55.546 DEBUG 24621 --- [nio-8089-exec-3] c.c.m.s.impl.ScriptToJavaServiceImp : ---------> javascript 调用java方法 <----------
2023-09-07 10:01:55.546 DEBUG 24621 --- [nio-8089-exec-3] c.c.m.s.impl.ScriptToJavaServiceImp : ---------> 接收到javascript传参:A00
脚本打印 javaReturn:java service return!
2023-09-07 10:01:55.621 DEBUG 24621 --- [nio-8089-exec-3] c.chinacoal.microservice.service.impl.A : 执行脚本打印log日志
---> Java 取脚本返回exec success!
---> Java 取脚本变量值:A00