`
fox1984
  • 浏览: 61778 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java调用ruby

 
阅读更多
由于spring只能调用jruby 0.9 - 1.0版本,为了调用更高版本的jruby 引擎,需要通过RS223接口来实现,以下是工作的一些总结希望对大家有帮助。


1、对RS232的一些封装,方便调用
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.lang.StringUtils;

public class JrubyUtil {
	private LoadedScriptFile loaded = new LoadedScriptFile(
			SuperScriptEngineFactory.JRUBY_ENGINE_NAME);
	
	public Object getInstance(Class<?> impl) {
		return loaded.getInstance(
			ScriptFileHelper.getJrubyScriptFile(impl, SuperScriptEngineFactory.JRUBY_ENGINE_NAME), impl);
	}
	
	public Object getInstance(Class<?> impl, String fun) {
		return loaded.getInstance(
			ScriptFileHelper.getJrubyScriptFile(impl, SuperScriptEngineFactory.JRUBY_ENGINE_NAME), impl, fun);
	}	
}

/**
 * 封装rs-223的实现,适用于各种脚本语言
 */
class SuperScriptEngine {
	protected ScriptEngine engine;
	
	/**
	 * 
	 * @param name 所需要使用引擎名称
	 */
	public SuperScriptEngine(String name) {
		ScriptEngineManager manager = new ScriptEngineManager();
		engine = manager.getEngineByName(name);	
		System.out.println(engine.getFactory().getEngineName());
	}
	
	/**
	 * 
	 * @param in 脚本文件的文件流
	 * @return   编译完成的脚本对象
	 */
	public CompiledScript compiled(InputStream in) {
		CompiledScript compileScript = null;
		try {
			if (engine instanceof Compilable) {
				Compilable compile = (Compilable) engine;
				compileScript = compile.compile(
						new InputStreamReader(in));
			}
		} catch (ScriptException e) {
			e.printStackTrace();
		} 
		return compileScript;
	}

	/**
	 * @param impl	脚本所需实现的接口
	 * @param in	脚本文件的文件流
	 * @param fun	脚本中负责初始化的函数名
	 * @return  	返回接口实现的对象
	 * <p>fun函数最后必须返回实现的对象,如果为空则脚本结束的返回值必须返回对象</p>
	 */	
	public Object getInterface(Class<?> impl, InputStream in, String fun) {
		Object interfaceInstance = null;
		Object result = null;
		try {
			if (engine instanceof Invocable) {
				result = engine.eval(
					new InputStreamReader(in));
				Invocable invocable = (Invocable) engine;
				if (StringUtils.isBlank(fun)) {
					interfaceInstance = invocable.getInterface(result, impl);
				} else {
					result = invocable.invokeFunction(fun);
					interfaceInstance = invocable.getInterface(result, impl);
				}
			} 
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return interfaceInstance;
	}
	
	/**
	 * 
	 * @param impl	脚本所需实现的接口
	 * @param in	脚本文件的文件流
	 * @return  返回接口实现的对象
	 * <p>脚本中最后必须返回实现的对象</p>
	 */
	public Object getInterface(Class<?> impl, InputStream in) {
		return getInterface(impl, in, "");
	}

	/**
	 * @param impl			脚本所需实现的接口
	 * @param compileScript	编译后的脚本对象
	 * @param fun			脚本中负责初始化的函数名
	 * @return  			返回接口实现的对象
	 * <p>fun函数最后必须返回实现的对象,如果为空则脚本结束的返回值必须返回对象</p>
	 */
	public Object getInterface(Class<?> impl, CompiledScript compileScript, String fun) {
		Object interfaceInstance = null;
		Object result = null;
		try {
			ScriptEngine engine = compileScript.getEngine();
			if (engine instanceof Invocable) {
				result = compileScript.eval();
				Invocable invocable = (Invocable) engine;
				if(StringUtils.isBlank(fun)) {
					interfaceInstance = invocable.getInterface(result, impl);
				} else {
					result = invocable.invokeFunction(fun);
					interfaceInstance = invocable.getInterface(result, impl);
				}
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return interfaceInstance;	
	}
	
	/**
	 * @param  	脚本所需实现的接口
	 * @param 	编译后的脚本对象
	 * @return  返回接口实现的对象
	 * <p>脚本中最后必须返回实现的对象</p>
	 */
	public Object getInterface(Class<?> impl, CompiledScript compileScript) {
		return getInterface(impl, compileScript, null);
	}
	
	/**
	 * @param str 文本形式的脚本代码
	 * @return    执行后脚本的返回值
	 */
	public Object eval(String str) {
		Object result = null;
		try {
			result = engine.eval(str);
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 
	 * @param str     脚本代码
	 * @param context 脚本引擎上下文
	 * @return        执行后脚本的返回值
	 */
	public Object eval(String str, ScriptContext context) {
		Object result = null;
		try {
			result = engine.eval(str, context);
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 
	 * @param in 脚本文件流
	 * @return   执行后脚本的返回值
	 */
	public Object eval(InputStream in) {
		Object result = null;
		try {
			result = engine.eval(new InputStreamReader(in));
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 
	 * @param in 		脚本文件流
	 * @param context 	脚本引擎上下文 
	 * @return   		执行后脚本的返回值
	 */	
	public Object eval(InputStream in, ScriptContext context) {
		Object result = null;
		try {
			result = engine.eval(new InputStreamReader(in), context);
		} catch (ScriptException e) {
			e.printStackTrace();
		}
		return result;
	}	
}

/**
 * 封装rs-223的实现,适用于各种脚本语言,jruby引擎的实现
 */
class JrubySuperScriptEngine extends SuperScriptEngine {
	private static JrubySuperScriptEngine jrEngine;

	synchronized public static JrubySuperScriptEngine getInstance() {
		if (jrEngine == null) {
			System.setProperty("org.jruby.embed.compilemode", "jit");
			jrEngine = new JrubySuperScriptEngine("jruby");
		}
		return jrEngine;
	}

	public JrubySuperScriptEngine(String name) {
		super(name);
	}
}

/**
 * 脚本引擎工厂类,负责实例化脚本引擎对象
 */
class SuperScriptEngineFactory {
	public final static String JRUBY_ENGINE_NAME = "JRUBY";
	
	synchronized public static SuperScriptEngine getInstance(String engineName) {
		SuperScriptEngine instance = null;
		if (engineName.toUpperCase().equals(JRUBY_ENGINE_NAME)) {
			instance = JrubySuperScriptEngine.getInstance();
		}
		return instance;
	}
}

/**
 * 脚本文件封装
 */
class ScriptFile {
	/** 脚本文件名称  */
	protected String name;
	/** 脚本的hash值  */
	protected int hash;
	/** 脚本的路径       */
	protected String path;
	/** 脚本的文件流  */
	protected InputStream in;	
	
	public ScriptFile(File file) throws FileNotFoundException {
    	in	 = new FileInputStream(file);
		name = file.getName();
		path = file.getPath();
		hash = file.hashCode();
	}
	
	public String getName() {
		return name;
	}	
	
	public String getPath() {
		return path;
	}

	public int getHash() {
		return hash;
	}
	
	public InputStream getInputStream() {
		return in;
	}	
}

/**
 * 脚本文件管理
 */
class LoadedScriptFile {
	public final static String DEFAULT_GET_INSTANCE = "getInstance";
	
	protected SuperScriptEngine engine;
	protected Class<?> impl;
	
	public LoadedScriptFile(String engineName) {
		this.engine = SuperScriptEngineFactory.getInstance(engineName);
	}	
		
	public SuperScriptEngine getEngine() {
		return engine;
	}
	
	public Object getInstance(ScriptFile scriptFile, Class<?> impl, String fun) {
		Object instance = null;
		instance = engine.getInterface(impl, 
				scriptFile.getInputStream(), fun);
		return instance;
	}
	
	public Object getInstance(ScriptFile scriptFile, Class<?> impl) {
		return getInstance(scriptFile, impl, "");
	}
}


2、工具类,用于查找脚本文件
import java.io.File;
import java.io.FileNotFoundException;

import java.net.URISyntaxException;
import java.net.URL;

import junit.framework.Assert;

/**
 * 
 * 读取脚本文件,适合各种不同后缀脚本
 */
public class ScriptFileHelper {
	private final static String SCRIPT_HOME = "SCRIPT_HOME";
	private final static String SEPARATOR = System.getProperty("file.separator");
	private final static String JRUBY_SUFFIX = ".rb";

	/**
	 * 根据文件名读入资源文件
	 * 查找范围及优先级:
	 *     1. classes目录下的fileName;
	 *     2. 环境变量SCRIPT_HOME下的filaName;
	 *     3. 当前工作空间下resources目录下的filaName;
	 */
	public static ScriptFile getScriptFileOnFileName(String fileName) {
		ScriptFile scriptFile = null;
		try {
			URL resource = ScriptFileHelper.class.getResource("/" + fileName);
			if (resource != null) {
				scriptFile = new ScriptFile(new File(resource.toURI()));
			}
			if (scriptFile == null) { 
				String[] paths = {
						System.getProperty(SCRIPT_HOME) + fileName,
						System.getProperty("user.dir") + SEPARATOR + "scriptfiles" + SEPARATOR + fileName};
				for (String path : paths) {
					System.out.println(path);
					if ((new File(path)).isFile()) {
						scriptFile = new ScriptFile(new File(path));
						break;
					}
				}
			}
		} catch (FileNotFoundException e) {
			System.out.println(e.getStackTrace());
		} catch (URISyntaxException e) {
			System.out.println(e.getStackTrace());
		}
		Assert.assertNotNull(scriptFile);
		return scriptFile;
	}
		
	/**
	 * 根据类名读取脚本文件
	 * 查找范围及优先级:
	 *     1. impl所在目录下同名的脚本;
	 *     2. classes目录下的fileName;
	 */	
	public static ScriptFile getScriptFileOnImpl(Class<?> impl, String suffix) {
		ScriptFile scriptFile = null;
		try {
			// 读取当前包下同名的文件
			String implName = impl.getSimpleName() + suffix;
			URL resource = impl.getResource(implName);	
			if (resource == null) {
				// 读取classes下同名的文件
				resource = impl.getResource("/" + implName);
			}
			if (resource != null) {
				scriptFile = new ScriptFile(new File(resource.toURI()));
			}
		} catch (URISyntaxException e) {
			System.out.println(e.getStackTrace());
		} catch (FileNotFoundException e) {
			System.out.println(e.getStackTrace());
		}
		Assert.assertNotNull(scriptFile);
		return scriptFile;	
	}	
	
	/**
	 * 1. 根据全路径加载脚本文件 
	 */
	public static ScriptFile getScriptFileOnFullPath(String fullPath) {
		ScriptFile scriptFile = null;
		try {
			if ((new File(fullPath)).isFile()) {
				scriptFile = new ScriptFile(new File(fullPath));		
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		Assert.assertNotNull(scriptFile);
		return scriptFile;
	}
	
	/**
	 * 根据类名,脚本引擎名,读取脚本文件
	 * 查找范围及优先级:
	 */	
	public static ScriptFile getJrubyScriptFile(Class<?> impl, String engineName) {
		ScriptFile reslut = null;
		if (engineName.toUpperCase().equals(SuperScriptEngineFactory.JRUBY_ENGINE_NAME)) {
			reslut = getScriptFileOnImpl(impl, JRUBY_SUFFIX);
		}
		return reslut;
	}
}


3、测试代码
接口定义
public interface Message {
	public String sayHello();
}


接口实现
require 'java'

class RubyMessage
  include_class 'test.wireless.auto.ruby.Message' 
  def sayHello
    return 'hello java'
  end
end
RubyMessage.new


测试代码
public class MessageTest {	
	@Test
	public void test_JrubyUtilTest() {
		JrubyUtil jruby = new JrubyUtil();
		Object result = jruby.getInstance(Message.class);	
		System.out.println(((Message)result).sayHello());
	}
}
分享到:
评论

相关推荐

    From Java to Ruby

    然而,Ruby鼓励使用异常来控制程序流程,而在Java中,过度使用异常会被视为不良实践。 在开发工具和生态系统方面,Java有成熟的IDE如Eclipse和IntelliJ IDEA,以及Maven和Gradle等构建工具。Ruby则有RubyMine作为...

    从 Java 到 Ruby_ 每一个管理者应该知道的事情

    标题 "从 Java 到 Ruby_ 每一个管理者应该知道的事情" 提示我们,这篇文章或书籍将探讨在 IT 管理领域从使用 Java 转向 Ruby 的关键点。Ruby 是一种动态类型、面向对象的编程语言,以其简洁、灵活的语法和强大的元...

    Java与Ruby在Web开发上谁更高效

    在实际的应用示例中,作者展示了如何使用Java的OpenXava框架实现与RoR类似的功能。通过简单的Java类定义(如Recipe.java),OpenXava可以自动生成Web界面和后台逻辑,实现了食谱列表展示、创建/编辑食谱以及分类的...

    深度剖析Ruby vs Java误区

    Halloway指出,编程本身就是一个挑战,无论使用Java还是Ruby,都需要一定的学习曲线。限制语言特性并不能真正降低编程的难度。 误区四讨论了Rails创新的复制性。虽然Rails的一些理念可以应用于其他语言,但有些特性...

    依赖结构矩阵_Java_Ruby_下载.zip

    在Java和Ruby这两种编程语言中,DSM同样适用,帮助开发者理解代码的复杂性,优化模块间的耦合度,提高软件的可维护性和可扩展性。本资源包含的"dtangler-master"可能是一个用于处理和分析依赖结构矩阵的项目,可能是...

    Java世界的Ruby

    #### 在Java中使用Ruby的最佳实践 为了充分利用Ruby和Java各自的优点,开发者可以采取以下几种策略: 1. **将Ruby用于脚本任务**:利用Ruby的灵活性快速编写原型代码或自动化脚本,同时使用Java进行核心业务逻辑的...

    ruby生成java文件的工具

    标题中的“ruby生成java文件的工具”指的是使用Ruby编程语言编写的一种工具,它能够自动生成Java源代码。这种工具通常用于提高开发效率,特别是在需要大量重复性代码的情况下,如数据访问对象(DAO)、控制器...

    Dijkstra最短路径算法在不同语言中的实现_Java_Ruby_下载.zip

    在这个压缩包文件"Dijkstra最短路径算法在不同语言中的实现_Java_Ruby_下载.zip"中,包含了一个名为"dijkstras-algorithm-master"的项目,很可能包含了Dijkstra算法在Java和Ruby两种编程语言下的实现。 首先,让...

    ltp哈工大NLP源码含(c# c++ ,java python ruby等)

    【标题】"ltp哈工大NLP源码含(c# c++ ,java python ruby等)" 提供的是哈尔滨工业大学自然语言处理(NLP)工具包(LTP:Language Technology Platform)的源代码,涵盖了多种编程语言实现,包括C#、C++、Java、...

    Redis 实战 源码(java python ruby node)(缺少第三节)

    Redis,全称Remote Dictionary Server,是一款高性能的键值存储系统,常被用于数据库、缓存和消息...无论你是Java、Python、Ruby还是Node.js开发者,都能从这本书中收获宝贵的经验,提升你在使用Redis时的技能和效率。

    Ruby-JRuby一个Ruby语言的Java实现

    在JRuby中,你可以直接调用Java类库,就像调用Ruby内置函数一样简单。这对于集成Java框架,如Spring或Hibernate,或者利用Java的并发和多线程能力,都是极大的便利。同样,Java开发者也可以轻松地调用Ruby代码,实现...

    ruby初学者教程(对初学者很有帮助)

    **2.3 使用irb(交互式Ruby解释器)** irb是一个命令行工具,可以让开发者直接在命令行中测试Ruby代码片段,非常适合学习和调试。 **2.4 使用ri(Ruby信息) ri是一个内置的帮助系统,可以帮助开发者查询Ruby文...

    java调用脚本语言笔记(jython,jruby,groovy)

    Java调用Jython、JRuby和Groovy提供了强大的动态编程能力,使得开发者可以在Java应用中充分利用这些脚本语言的优点。了解如何在Java中正确地调用和管理这些脚本,对于提升开发效率和应用功能都有很大帮助。在实际...

    jruby_windows_1_6_4安装文件

    - **Java调用Ruby**:通过JRUBY-CLASSPATH环境变量,Java程序可以加载并调用Ruby代码。 通过JRuby,Windows用户可以充分利用Ruby的简洁语法和Java的强大功能,实现两者的无缝结合,极大地扩展了开发者的工具箱。...

    ist的matlab代码-rails_lecture_lesson_java2ruby:练习的重点是Java和Ruby语法的比较。您应该认识到

    使用Ruby命名约定来做到这一点。 练习的重点是Java和Ruby语法的比较。 您应该认识到异同并习惯它们。 使用spec文件夹中的RSpec规范测试您的实现。 克隆练习存储库,解决问题,然后重新签回解决方案。 一个成功的呼叫...

    Ruby-rubyinstall安装RubyJRubyRubiniusMagLevorMRuby

    2. JRuby:JRuby是Ruby的一个Java实现,它可以在Java平台上运行,并且能够利用Java的性能和生态系统。JRuby的最大优点是与Java库的无缝集成,以及在多线程环境下的高效执行。 3. Rubinius:Rubinius是一个用Ruby...

    对Ruby VS Java误区的深度剖析

    Halloway反驳了这一观点,指出如果正确使用,Ruby的特性实际上可以提高代码的可维护性。虽然Java的IDE提供了优秀的代码导航,但Ruby的DRY(Don't Repeat Yourself)原则使代码更易读,更易于修改。 误区三:Ruby太...

    ruby2java:查尔斯·纳特(Charles Nutter)的JRuby项目的分支,该项目从Ruby源代码构建Java .class文件-java project source code

    6. **文档和示例**:为了帮助开发者理解和使用Ruby2Java,项目通常会提供详细的文档,包括安装指南、使用示例以及API参考。 通过这个项目,开发者可以在保持Ruby的灵活性和生产力的同时,利用Java平台的强大功能和...

    Java版的Ruby解释器 JRuby简介

    在这个例子中,`addOne`方法原本可能需要在Java中进行同步,但注释掉了`synchronize`块,这表明在JRuby中,开发者可以使用Ruby的并发控制机制,而不是Java的锁来管理线程安全。 JRuby的另一个重要特性是其与Java...

Global site tag (gtag.js) - Google Analytics