Java与JavaScript的“合作”示例

Java与JavaScript的“合作”示例(Java与JavaScript的相互调用)

在一些项JavaWeb目中,我们可以看到在前端写了一些JavaScript的脚步,后端就可以执行脚本来处理业务逻辑。这里用一个简单的示例来说明他们的调用方法!

1、简单介绍

Java与JavaScript之间的相互调用是指在Java代码中调用JavaScript代码,或者在JavaScript代码中调用Java代码的过程。

Java与JavaScript之间的相互调用可以通过以下方式实现:

  1. 使用Java的ScriptEngine类执行JavaScript代码:Java提供了ScriptEngine类和相关的API,可以通过这些API在Java代码中执行JavaScript代码。通过ScriptEngine类,可以创建一个JavaScript引擎,并执行JavaScript代码。这种方式可以在Java代码中调用JavaScript函数或方法。
  2. 使用Java的javax.script包:Java的javax.script包提供了一组标准API,用于在Java代码中执行脚本语言(如JavaScript)的代码。通过这些API,可以创建一个JavaScript引擎,并在Java代码中调用JavaScript函数或方法。
  3. 使用Java的Web框架:在Web开发中,可以使用Java的Web框架(如Spring)将Java方法暴露给JavaScript。通过在Java代码中定义一个控制器或服务,可以将Java方法映射到一个URL,并通过AJAX请求从JavaScript中调用该URL,从而实现Java与JavaScript之间的交互。
  4. 使用Java的桥接技术:Java提供了一些桥接技术,如JavaFXWebView组件和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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值