社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
前言:为了提高SAP二次开发的效率,想用python写个简单的脚本工具,与SAP 中frc的接口自动对接。但是,国内的博客中有关此内容的博文很少,且时间久远。查了国外的文章,有一些文章有涉及此内容,不过在python这一块还是有一定的问题。python的 pysaprfc 模块的维护更新和文档都是较少的,有之前的博主分享过经验说用pysaprfc模块连接SAP传输的值是乱码,不知解决了吗。所以,积累前人的经验,以及结合python语言的跨平台性的不足的这些特点,我使用的是使用Java搭建中间件,综合python和Java语言的优势。
如图:Java作为中间层可以利用其强大的跨平台性与SAP系统连接;Java又与python具有良好的可连接性且非常简单;下面将主要从python和Java的代码层去分析
所需jar包:dom4j-1.6.1.jar,sapjoc3.jar,者两个jar包也是为自己写的连接类服务的,详细教程看两个jar包的文档。
自己写的连接类:
public class SAPConn {
private static final String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL";
static{
Properties connectProperties = new Properties();
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.18.12"); //SAP集团的ip
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "400"); //集团号
connectProperties.setProperty(DestinationDataProvider.JCO_USER, "username"); //登录的用户名
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "password"); //登录的密码
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "zh");
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);
}
/**
*
* @param name ABAP
* @param suffix
* @param properties
*/
private static void createDataFile(String name, String suffix, Properties properties){
File cfg = new File(name+"."+suffix);
if(cfg.exists()){
cfg.deleteOnExit();
}
try{
FileOutputStream fos = new FileOutputStream(cfg, false);
properties.store(fos, "for tests only !");
fos.close();
}catch (Exception e){
//log.error("Create Data file fault, error msg: " + e.toString());
System.out.println("Create Data file fault, error msg: " + e.toString());
throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
}
}
/**
*
* @return
*/
public static JCoDestination connect(){
JCoDestination destination =null;
try {
destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
} catch (JCoException e) {
//log.error("Connect SAP fault, error msg: " + e.toString());
System.out.println("Connect SAP fault, error msg: " + e.toString());
}
return destination;
}
}
class omjson{
String FIELDNM;
String FIELDTEXT;
public String getFIELDNM() {
return FIELDNM;
}
public void setFIELDNM(String fIELDNM) {
FIELDNM = fIELDNM;
}
public String getFIELDTEXT() {
return FIELDTEXT;
}
public void setFIELDTEXT(String fIELDTEXT) {
FIELDTEXT = fIELDTEXT;
}
@Override
public String toString() {
return FIELDNM+":"+FIELDTEXT;
}
}
public String rfcs(String name) {
JCoFunction function = null;
JCoDestination destination = SAPConn.connect();
List<omjson> list = new ArrayList<omjson>();
try {
//你的SAP frc 接口的名字
function = destination.getRepository().getFunction("Z_RFC_XML");
JCoParameterList input = function.getImportParameterList();
//输入你传入SAP rfc 接口的参数,如果没有就不用传了
input.setValue("TNAME", name);
function.execute(destination);
JCoParameterList tblexport = function.getTableParameterList();
String msg = tblexport.toXML();
Document document = DocumentHelper.parseText(msg);
Element employees = document.getRootElement();
for (Iterator i = employees.elementIterator(); i.hasNext(); ) {
Element employee = (Element) i.next();
for (Iterator j = employee.elementIterator(); j.hasNext(); ) {
Element node = (Element) j.next();
omjson om = new omjson();
//System.out.println(node.getName() + ":" + node.getText());
for (Iterator k = node.elementIterator(); k.hasNext(); ) {
HashMap<String, String> map = new HashMap<String, String>();
Element item = (Element) k.next();
if(item.getName().equals("FIELDNM")){
om.setFIELDNM(item.getText());
}else if(item.getName().equals("FIELDTEXT")){
om.setFIELDTEXT(item.getText());
}
}
list.add(om);
}
}
}catch (Exception e) {
e.printStackTrace();
}
return list.toString();
}
到这里我们连接类就写好了,不过我们并不是要用java作为脚本语言,所以将写的所有类打包成jar包,加上下载的两个jar包,一共四个jar包,我们会在python中调用。
python_sap.py:
import jpype
# """通过java的接口调用SAP接口,指定输出的表名""" #路径问题,可能不支持中文
jarpath4 = os.path.join(os.path.abspath('.'), "D:/script/RFCTest.jar")
jarpath3 = os.path.join(os.path.abspath('.'), "D:/script/SAPConn.jar")
jarpath2 = os.path.join(os.path.abspath('.'), "D:/script/dom4j-1.6.1.jar")
jarpath1 = os.path.join(os.path.abspath('.'), "D:/script/sapjco3.jar")
#加载多个Jar包
#注意这里的java的jdk安装默认的路径,如果不是默认的路径需要指定路径
#如 # startJVM("C:/Program Files/Java/jdk1.8.0_221/jre/bin/server/jvm.dll","-ea","-Djava.class.path=%s;%s;%s;%s;%s;%s" % (jarpath, #jarpath, jarpath1, jarpath2, jarpath3, jarpath4)
jpype.startJVM("-ea", "-Djava.class.path=%s;%s;%s;%s;%s;%s" % (jarpath, jarpath, jarpath1, jarpath2, jarpath3, jarpath4))
首先python需要加载jpype模块,用来调用java的程序。在python中只需要这么几行代码就调用了java刚才产生的jar包,然后就可以写逻辑代码,将从SAP传来的值进行分析。具体怎么用python调用java,可以看网上详细教程,很多例子。
注意:python的字符集需要调整,不然会乱码,中文可以用UTF-8,或者GB2313
最后一步,把sapjoc3.dll这个文件放到jdk的bin下,这个文件可能是SAP系统自带的,可以找找,没有就去网上下载一个也是可以的。
总结:其实这种方法是有一点复杂,起码还要懂点java的基础。我写这个博客并不是说这种方式多么厉害高深,我只是提供一种python 调用SAP rfc接口的一种思路,而且是成功的案例。python在数据分析,爬虫,脚本等有自己强大的地方,而java在跨平台等有其优势,扬长避短发挥各自优势,这也是这篇博客所想表达的。如果各位看客有新想法,也可以把自己的连接放到评论区,分享学习。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!