工具类
package com.phfund.report.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.phfund.common.util.SysPropertiesConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import java.io.*;
import java.net.Socket;
import java.util.*;
public class RandPyUtils {
private static Logger logger = LogManager.getLogger(RandPyUtils.class);
private static String IP= SysPropertiesConfig.PY_R_IP;
private static String R_PORT=SysPropertiesConfig.R_PORT;
private static int PY_PORT=StringUtils.isEmpty(SysPropertiesConfig.PY_PORT)?0:Integer.parseInt(SysPropertiesConfig.PY_PORT);
/**
* 本地python环境
* list 脚本路径以及脚本参数
*/
public static Object PythonCall(List<String> list) {
String[] arr = list.toArray(new String[list.size()]);
Process pr;
List<Object> result = new ArrayList<>();
try {
pr = Runtime.getRuntime().exec(arr);
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream(), "GB2312"));
String line;
while ((line = in.readLine()) != null) {
result.add(line);
}
in.close();
} catch (IOException e) {
logger.error("python脚本执行出错:" + e.getMessage());
}
return result;
}
/**
* func 脚本函数
* path脚本路径
*/
public static String RCall(String func,String path, Map<String,String> map) {
String ports = StringUtils.isEmpty(R_PORT)?null: R_PORT;
int PORT=0;
if(ports==null){
//
}else{
String[] split = ports.split(",");
if(split!=null){
int i = (int) (Math.random() * split.length);
PORT =Integer.parseInt(split[i]);
}
}
logger.info("R IP PORT :"+IP+":"+PORT);
logger.info("R远程调用开始");
String result = null;
RConnection rcon=null;
try {
rcon = new RConnection(IP, PORT);
//加载脚本资源
rcon.assign("path", path);
rcon.eval("source(path)");
func = func.replaceAll("\\?","");
String parm=func.substring(func.indexOf("(")+1,func.lastIndexOf(")"));
//获取参数
List<String> parms=new ArrayList<>();
if(!StringUtils.isEmpty(parm)){
String[] split = parm.split(",");
parms = Arrays.asList(split);
}
RConnection finalRcon = rcon;
parms.forEach(x->{
String value = map.get(x);
if(value==null){
value="";
}
try {
String val="";
try {
val= new String(value.getBytes("utf-8"), "utf-8");
} catch (UnsupportedEncodingException e) {
logger.error("参数转utf-8异常");
return;
}
finalRcon.assign(x, val);
} catch (RserveException e) {
logger.error("R函数参数异常...");
return;
}
});
//执行脚本函数
REXP eval = rcon.eval(func);
//统一String返回
result = eval.asString();
logger.info("R远程调用结束");
} catch (Exception e) {
logger.error("R脚本执行出错:" + e.getMessage());
return null;
}finally {
if(rcon!=null){
rcon.close();
}
}
return result;
}
/**
* 解析R脚本结果类型
*/
// private static Object getResult(REXP eval) throws REXPMismatchException {
// List<Object> result = null;
// if (eval.isNumeric()) {
// double[] doubles = eval.asDoubles();
// if(doubles.length>0){
// result=Arrays.stream(doubles).boxed().collect(Collectors.toList());
// }
//
// } else if (eval.isInteger()) {
// int[] ints = eval.asIntegers();
// if(ints.length>0){
// result=Arrays.stream(ints).boxed().collect(Collectors.toList());
// }
//
// } else if (eval.isString()) {
// String[] strings = eval.asStrings();
// if(strings.length>0){
// result=Arrays.asList(strings);
// }
//
// } else if (eval.isList()) {
// result = eval.asList();
//
// } else {
// logger.info("R返回未知数据类型.......");
// }
// return result;
// }
/**
* 远程socket的方式调用python
*/
public static String remotePyCall(String PyScript) throws JsonProcessingException {
// 访问服务进程的套接字
Socket socket = null;
logger.info("R IP PORT :"+IP+":"+PY_PORT);
logger.info("python远程接口调用开始");
try {
// 初始化套接字,设置访问服务的主机和进程端口号,HOST是访问python进程的主机名称,可以是IP地址或者域名,PORT是python进程绑定的端口号
socket = new Socket(IP,PY_PORT);
// 获取输出流对象
OutputStream os = socket.getOutputStream();
PrintStream out = new PrintStream(os,true,"utf-8");
// 发送内容
out.print(PyScript);
// 告诉服务进程,内容发送完毕,可以开始处理
out.print("&over");
// 获取服务进程的输入流
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
String tmp = null;
StringBuilder sb = new StringBuilder();
// 读取内容
while((tmp=br.readLine())!=null)
sb.append(tmp).append('\n');
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {if(socket!=null) socket.close();} catch (IOException e) {
logger.error("socket客户端关闭异常.");
}
logger.info("python远程接口调用结束.");
}
return null;
}
//获取文件夹下所有文件路径
public static List<String> getFiles(String path) {
List<String> files = new ArrayList<String>();
File file = new File(path);
File[] tempList = file.listFiles();
for (int i = 0; i < tempList.length; i++) {
if (tempList[i].isFile()) {
files.add(tempList[i].toString());
}
}
return files;
}
public static void main(String[] args) throws Exception {
//getFiles("D:/other");
Map<String,String> map=new HashMap<>();
map.put("parm1","zlc");
map.put("parm2","27");
map.put("parm3","88");
String path="D:/other/ceshi/R/test.R";
String func="myAdd(?parm1?,?parm2?,?parm3?)";
func = func.replaceAll("\\?","");
String prm=func.substring(func.indexOf("(")+1,func.lastIndexOf(")"));
List<String> strings=new ArrayList<>();
if(!StringUtils.isEmpty(prm)){
String[] split = prm.split(",");
strings = Arrays.asList(split);
}
ObjectMapper mapper = new ObjectMapper();
//R部分
String s1 = RCall(func, path, map);
List list0 = mapper.readValue(s1, List.class);
System.out.println(list0);
//python部分
String pyscript="python D:/other/ceshi/Python/test.py ?parm1? ?parm2? ?parm3?";
pyscript=replaceParam(pyscript,map);
String s = remotePyCall(pyscript);
//
// List list = mapper.readValue(s, List.class);
// List<LinkedHashMap> ff=list;
// System.out.println(ff);
// String pyscriptee="python D:/other/ceshi/Python/test1.py ?parm1? ?parm2?";
// pyscriptee=replaceParam(pyscriptee,map);
// System.out.println(remotePyCall(pyscriptee));
int i = (int) (Math.random() * 3);
System.out.println(i);
}
}
调用R语言需要的jar包
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>REngine</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.rosuda.REngine</groupId>
<artifactId>Rserve</artifactId>
<version>1.8.1</version>
</dependency>
通过scoket的方式调用python,python scoket服务端代码如下:
# -*- coding: utf-8 -*-
import socket
import sys
import threading
import json
import os
import platform
import imp
imp.reload(sys)#解决中文参数乱码问题
def main():
# 创建服务器套接字
serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 获取本地主机名称
host = "172.22.16.253"
# 设置一个端口
port = 12345
# 将套接字与本地主机和端口绑定
serversocket.bind((host,port))
# 设置监听最大连接数
serversocket.listen(5)
# 获取本地服务器的连接信息
myaddr = serversocket.getsockname()
print("服务器地址:%s"%str(myaddr))
# 循环等待接受客户端信息
Flag=True
while Flag:
# 获取一个客户端连接
clientsocket,addr = serversocket.accept()
print("连接地址:%s" % str(addr))
try:
t = ServerThreading(clientsocket)#为每一个请求开启一个处理线程
t.start()
pass
except Exception as identifier:
print(identifier)
pass
pass
serversocket.shutdown(2)
serversocket.close()
pass
class ServerThreading(threading.Thread):
def __init__(self,clientsocket,recvsize=1024*1024,encoding="utf-8"):
threading.Thread.__init__(self)
self._socket = clientsocket
self._recvsize = recvsize
self._encoding = encoding
pass
def run(self):
print("开启线程.....")
try:
#接受数据
args = ''
while True:
# 读取recvsize个字节
rec = self._socket.recv(self._recvsize)
# 解码
args += rec.decode("utf-8")
# 文本接受是否完毕,因为python socket不能自己判断接收数据是否完毕,
# 所以需要自定义协议标志数据接受完毕
if args.strip().endswith('&over'):
args=args[:-5]
break
#执行指定脚本arg为python D:/other/ceshi/Python/test.py parm1 parm2 parm3的形式
out=os.popen(args)
#获取结果
result=out.read()
# 发送数据
self._socket.send(("%s" % result).encode("utf-8"))
pass
except Exception as identifier:
self._socket.send("500".encode(self._encoding))
print(identifier)
pass
finally:
self._socket.close()
print("线程结束.....")
pass
if __name__ == "__main__":
main()