问题场景
按照前文rJava的安装与测试-不用每次设置VM参数‘-Djava.library.path’所述弄好了JRI,但是在项目里重复调用Rengine re = new Rengine(args, false, new TextConsole());这段代码时,项目会停止响应或者报错。
解决方式
既然重复调用不行那就让项目初始化时只调取一次Rengine实例就好了,采用单例模式即可。另外将你对应的jri.dll(我的在D:\programFile\R\R-3.4.1\library\rJava\jri\x64目录下)文件放入Tomcat的bin目录下。
调用方式:
/**
* 调用R脚本生成克隆进化图
* java与R互调思路见我的博客:http://blog.csdn.net/sand_clock/article/details/78031010
* @param filePath 作图的地址
* @param imagePath 保存图片的地址
* @param rPath R脚本的路径
* @return 作图是否成功
*/
public static boolean createClonePic(String filePath, String imagePath, String rPath) {
Rengine re = SingleRengine.getRegineInstance();
if (!re.waitForR()) {
System.out.println("Cannot load R");
return false;
}
System.out.println("开始执行脚本里的函数");
//调用R脚本,注意R路径里不要用'\\',要用'/'
re.assign("fn", rPath);
//用source命令将脚本中的函数加载到R环境中,后续可以直接调用
re.eval("source(fn)");
//调用有参函数
//在R里给变量赋值用于传参
re.assign("filePath", filePath);
re.assign("imagePath", imagePath);
REXP rex = re.eval("VolinPlot(filePath, imagePath)");
if (rex == null) {
return false;
}
RBool success = rex.asBool();
if (success.isTRUE()) {
return true;
}
return false;
}
单例类:
package rjava;
import org.rosuda.JRI.RMainLoopCallbacks;
import org.rosuda.JRI.Rengine;
import java.awt.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* Created on 2017/9/29
* Author: youxingyang.
*/
public class SingleRengine {
//私有的静态内部类 构造类时是原子操作
private static class SingleRengineIn {
private static final SingleRengine singleRengine = new Rengine(null, false, new TextConsole());
}
public static SingleRengine getInstance() {
return SingleRengineIn.singleRengine;
}
private SingleRengine() {}
private static class TextConsole implements RMainLoopCallbacks {
@Override
public void rWriteConsole(Rengine re, String text, int oType) {
System.out.print(text);
}
@Override
public void rBusy(Rengine re, int which) {
System.out.println("rBusy(" + which + ")");
}
@Override
public String rReadConsole(Rengine re, String prompt, int addToHistory) {
System.out.print(prompt);
try {
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
return (s == null || s.length() == 0) ? s : s +"\n";
}catch (Exception e) {
System.out.println("jriReadConsole exception: " + e.getMessage());
}
return null;
}
@Override
public void rShowMessage(Rengine re, String message) {
System.out.println("rShowMessage \"" + message + "\"");
}
@Override
public void rFlushConsole(Rengine re) {
}
@Override
public void rLoadHistory(Rengine re, String filename) {
}
@Override
public void rSaveHistory(Rengine re, String filename) {
}
@SuppressWarnings("deprecation")
@Override
public String rChooseFile(Rengine re, int newFile) {
FileDialog fd =new FileDialog(new Frame(), (newFile == 0) ?"Select a file" :"Select a new file",
(newFile ==0) ? FileDialog.LOAD : FileDialog.SAVE);
fd.show();
String res =null;
if (fd.getDirectory() != null)
res = fd.getDirectory();
if (fd.getFile() != null)
res = (res ==null) ? fd.getFile() : (res + fd.getFile());
return res;
}
}
}