JCEF-JS与JAVA代码交互(4)

实现JS与JAVA代码交互,是做应用所必须的一步。通过JS调用JAVA代码,实现一切JAVA代码能实现的东西。可查阅 org.cef.browser.CefMessageRouter类的文档。

因为是异步方式,要获取java代码的处理结果,需要在回调处理结果。应该大多数人都不喜欢这种形式的调用。如果和JAVA代码交互步骤很多,JS代码会一层套一层,很不雅观。我们可以通过js的 Promise 来解决这个问题。

JAVA代码实现

/**
 * @Description:Js与Java代码交互测试
 * @author liuming
 */
public class JsTestFrame extends JFrame{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -9131822589633996915L;

	public static void main(String[] args) {
		//必须在main()方法的开头调用此方法才能执行特定于平台的启动初始化。在Linux上,这将初始化Xlib多线程,而在macOS上,这会动态加载CEF框架。
        if (!CefApp.startup(args)) {
            System.out.println("Startup initialization failed!");
            return;
        }
		String url=System.getProperty("user.dir")+"/jstest.html";
		new JsTestFrame(url);
	}
	
	public JsTestFrame(String url) {
		//是否Linux系统
		boolean useOSR=OS.isLinux();
		//是否透明
		boolean isTransparent=false;
		//添加Handler,在CEFAPP状态为终止时退出程序
		CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
            @Override
            public void stateHasChanged(org.cef.CefApp.CefAppState state) {
                // Shutdown the app if the native CEF part is terminated
                if (state == CefAppState.TERMINATED) System.exit(0);
            }
        });
		
        CefSettings settings = new CefSettings();
        settings.windowless_rendering_enabled = useOSR;
		//获取CefApp实例
        CefApp cefApp=CefApp.getInstance(settings);
        //创建客户端实例
        CefClient cefClient = cefApp.createClient();
        
        //添加一个JS交互
        jsActive(cefClient);
        
        //创建浏览器实例
        CefBrowser cefBrowser = cefClient.createBrowser(url, useOSR, isTransparent);
		
        //将浏览器UI添加到窗口中
		
		getContentPane().add(cefBrowser.getUIComponent(), BorderLayout.CENTER);
		
		pack();
		setTitle("测试JCEF-JS与JAVA代码交互");
        setSize(800, 600);
        setVisible(true);
        //添加一个窗口关闭监听事件
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                CefApp.getInstance().dispose();
                dispose();
            }
        });
	}
	
	/**
	 * 添加js交互
     * @author:liuming
     */
    public void jsActive(CefClient client) {
    	 //配置一个查询路由,html页面可使用 window.java({}) 和 window.javaCancel({}) 来调用此方法
		 CefMessageRouterConfig cmrc=new CefMessageRouterConfig("java","javaCancel");
		 //创建查询路由
		 CefMessageRouter cmr=CefMessageRouter.create(cmrc);
		 cmr.addHandler(new CefMessageRouterHandler() {
			
			@Override
			public void setNativeRef(String str, long val) {
				System.out.println(str+"  "+val);
			}
			
			@Override
			public long getNativeRef(String str) {
				System.out.println(str);
				return 0;
			}
			
			@Override
			public void onQueryCanceled(CefBrowser browser, CefFrame frame, long query_id) {
				System.out.println("取消查询:"+query_id);
			}
			
			@Override
			public boolean onQuery(CefBrowser browser, CefFrame frame, long query_id, String request, boolean persistent,
					CefQueryCallback callback) {
				System.out.println("request:"+request+"\nquery_id:"+query_id+"\npersistent:"+persistent);
				
				callback.success("Java后台处理了数据!请观察控制台打印信息以测试!");
				return true;
			}
		}, true);
		client.addMessageRouter(cmr);
	}
}

html实现,在工程根目录新建 jstest.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<title>JCEF帮助文档</title>
	<meta charset="utf-8">
	<meta name="renderer" content="webkit">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
	<a href="javascript:testToJava()">测试与java代码交互</a>
	<br>
	
	<br>
	<a href="javascript:testToJava2()">测试与java代码交互(同步的方式)</a>
	<br><br>
	<a href="javascript:testToJava3()">测试与java代码交互(同步的方式-1)</a>

</body>
<script>

function testToJava(){
	window.java({
	    request: '发送给JAVA的数据',
	    persistent:false,
	    onSuccess: function(response) {
	      alert("返回的数据:"+response);
	    },
	    onFailure: function(error_code, error_message) {}
	});
}

/***
 * 返回一个Promise对象,再利用await,实现js与java交互的同步处理
 */
function execJava(data){
	return new Promise(function(resolve, reject) {
		window.java({
		    request: data,
		    persistent:false,
		    onSuccess: function(response) {
		    	resolve(response);
		    },
		    onFailure: function(error_code, error_message) {}
		});
	});
}

/***
 * 此函数需要使用 async 声明
 */
async function testToJava2(){
	var data=await execJava("发送给JAVA的数据1");
	alert(data+"1");
	var data1=await execJava("发送给JAVA的数据2");
	alert(data+"2");
}


function testToJava3(){
	execJava("发送给JAVA的数据1")
	.then(function(data){
		alert(data+"1");
		return execJava("发送给JAVA的数据2");
	})
	.then(function(data){
		alert(data+"2");
	});
}
</script>
<!-- author:玄翼猫 -->
</html>

关于JS Promise的使用请自行查阅资料。

有两种形式,一种是 async + await ,一种是xx.then(funciton(){}).catch(function(){})。

第一种写法让代码看上去是按行运行的,比较直观。但是await的使用范围有所限制,所以建议使用第二种。

您也可以参考 PowerOfLongedJcef 中通过反射+注解的形式方便的进行JS与JAVA程序的交互。此项目暂未使用 Promise 形式。

本示例教程开源项目地址(码云的代码较新):
githubGitHub - lieyanfeimao/JcefTest: JCEF测试工程类,包含JAVA与JS交互,鼠标右键菜单,以Tab选项卡形式展示多浏览器窗口,也有相关的中文文档。
码云JcefTest: JCEF测试工程类,包含JAVA与JS交互,鼠标右键菜单,以Tab选项卡形式展示多个浏览器窗口

开源项目:

PowerOfLongedJcef【注:本项目在win10 64位系统上开发,不保证其他系统可以直接运行】

githubGitHub - lieyanfeimao/PowerOfLongedJcef: PowerOfLongedJcef,关于JCEF桌面程序的个人项目,项目环境为Win64。采用JCEF+EasyUi开发
码云PowerOfLongedJcef: PowerOfLongedJcef,关于JCEF桌面程序的个人项目,项目环境为Win64。使用JCEF+Easyui开发

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值