Java连接SAP RFC实现数据抽取的示例详解
包管理
首先要连接SAP需要两个包,分别为sapjco3.jar和sapjco3.dll,切记这两个包需要放在同一目录;否则会报错。
我先尝试将这两个包发到私服上,再在pom.xml文件中引入,发现.dll文件下载不了;于是就将这两个包放在根目录sap下,dockerfile构建镜像时将这两个包copy到jdk/lib目录下。
COPY sap/sapjco3.dll /usr/local/jdk-17.0.5/lib/ COPY sap/sapjco3.jar /usr/local/jdk-17.0.5/bin/
功能介绍
- 连接SAP
- 入参获取
- 出参获取
- 函数列表获取
- 表名获取
- 函数执行
- 执行结果获取
Java连接SAP RFC
public class CheckSnFromSAP { private static final String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL"; public static void main(String[] args) { JCoFunction function = null; MyDestinationDataProvider destDataProvider = new MyDestinationDataProvider(); try { Properties connectProperties = new Properties(); connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "xxx");// 服务器 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "xx"); // 系统编号 connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "xxx"); // SAP集团 connectProperties.setProperty(DestinationDataProvider.JCO_USER, "xxx"); // SAP⽤户名 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "xxx"); // 密码 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH"); // 登录语⾔:ZH EN connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3"); // 最⼤连接数 connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10"); // 最⼤连接线程 // 注册连接参数 destDataProvider.addDestination(ABAP_AS_POOLED, connectProperties); Environment.registerDestinationDataProvider(destDataProvider); // 创建一个与SAP系统的连接 JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED); // 调用函数 function = destination.getRepository().getFunction("funcationName"); if(null == function) { throw new RuntimeException("无此函数"); } // 输入字段 JCoListMetaData listMetaData = function.getImportParameterList().getListMetaData(); List<Map<String, String>> inputFields = new ArrayList<>(); for (int i=0; i< listMetaData.getFieldCount(); i++) { Map<String, String> row = new HashMap<>(); String name = listMetaData.getName(i); String type = listMetaData.getTypeAsString(i); String sapType = listMetaData.getRecordTypeName(i); String description = listMetaData.getDescription(i); row.put("name", name); row.put("type", type); row.put("sapType", sapType); row.put("description", description); inputFields.add(row); } // 输出字段 JCoTable output = function.getTableParameterList().getTable("XXX"); JCoRecordMetaData recordMetaData = output.getRecordMetaData(); List<Map<String, String>> outputFields = new ArrayList<>(); for (int i=0; i< recordMetaData.getFieldCount(); i++) { Map<String, String> row = new HashMap<>(); String name = recordMetaData.getName(i); String type = recordMetaData.getTypeAsString(i); String sapType = recordMetaData.getRecordTypeName(i); String description = recordMetaData.getDescription(i); row.put("name", name); row.put("type", type); row.put("sapType", sapType); row.put("description", description); outputFields.add(row); } // 获取所有函数 function = destination.getRepository().getFunction("RFC_FUNCTION_SEARCH"); if(null == function) { throw new RuntimeException("无此函数"); } JCoParameterList importParams = function.getImportParameterList(); importParams.setValue("FUNCNAME", "*"); // Search for all functions function.execute(destination); JCoTable functionTable = function.getTableParameterList().getTable("FUNCTIONS"); int max = Math.min(functionTable.getNumRows(),500); for (int i = 0; i <max; i++) { functionTable.setRow(i); String functionName = functionTable.getString("FUNCNAME"); System.out.println("函数名:"+functionName); } //获取所有表名 JCoParameterList tableParameterList = function.getTableParameterList(); if(tableParameterList!=null){ for (JCoField jCoField : tableParameterList) { System.out.println("表:" + jCoField.getName()); } } // 输⼊参数修改 JCoParameterList input = function.getImportParameterList(); input.setValue("I_END", "2017-05-01"); input.setValue("I_START", "2017-01-01"); // JCoTable it_matnr = function.getTableParameterList().getTable("XXX");//以表作为请求参数 // it_matnr.appendRow(); // it_matnr.setValue("age",18);//设置表值 //方法执行 function.execute(destination); // 函数执行结果 JCoTable jcoTable = function.getTableParameterList().getTable("tableName"); int numRows = jcoTable.getNumRows();//行数为0可以直接return for (int i = 0; i < numRows; i++) { jcoTable.setRow(i);//设置索引 获取返回表里的数据 String fieldValue= jcoTable.getString("fieldName");//解析表字段值 System.out.println(fieldValue); } } catch (Exception e) { e.printStackTrace(); } finally { // 取消环境注册 Environment.unregisterDestinationDataProvider(destDataProvider); } } }
/** * 实现DestinationDataProvider接口,用于注册连接参数 */ class MyDestinationDataProvider implements DestinationDataProvider { private DestinationDataEventListener eventListener; private Map<String, Properties> destinationProperties; public MyDestinationDataProvider() { destinationProperties = new HashMap<>(); } public void addDestination(String destinationName, Properties properties) { destinationProperties.put(destinationName, properties); } @Override public Properties getDestinationProperties(String destinationName) { if (destinationProperties.containsKey(destinationName)) { return destinationProperties.get(destinationName); } return null; } @Override public void setDestinationDataEventListener(DestinationDataEventListener eventListener) { this.eventListener = eventListener; } @Override public boolean supportsEvents() { return true; } }
当然也可以通过创建文件的方式保存连接属性
public class SapConnection { private static final String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL"; static { Properties connectProperties = new Properties(); connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "xxx");// 服务器 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "xx"); // 系统编号 connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "xxx"); // SAP集团 connectProperties.setProperty(DestinationDataProvider.JCO_USER, "xxx"); // SAP⽤户名 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "xxx"); // 密码 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH"); // 登录语⾔:ZH EN connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3"); // 最⼤连接数 connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10"); // 最⼤连接线程 createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties); } /** * 创建sap接口属性文件 * @param name * @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) { System.out.println("Create Data file fault, error msg: " + e.toString()); throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e); } } /** * 获取sap连接 * @return */ public static JCoDestination connect() { JCoDestination destination = null; try { destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED); } catch (JCoException e) { System.out.println("Connect SAP fault, error msg: " + e.toString()); } return destination; } }
在使用场景中,我遇到了这样一种情况:
SpringBoot服务已启动,sap函数入参两个,上面代码获取sap函数入参两个; 我将sap函数入参改为三个后,上面代码获取还是两个,重启服务后获取就是正确的三个了。
经过研究发现,JCoDestinationManager.getDestination(ABAP_AS_POOLED);
会缓存destination
连接,每次都是先从缓存中取
RfcDestination destination = (RfcDestination)this.destinations.get(destinationName);
查看destination.getRepository()
会发现storage字段缓存了function等信息;解决办法是:
// 清除缓存 destination.getRepository().clear();
清除缓存后,每次会获取新的内容。
到此这篇关于Java连接SAP RFC实现数据抽取的示例详解的文章就介绍到这了,更多相关Java数据抽取内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Elasticsearch常见字段映射类型之scaled_float解读
这篇文章主要介绍了Elasticsearch常见字段映射类型之scaled_float解读。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-11-11Java集合之Comparable和Comparator接口详解
Java提供了Comparable接口与Comparator接口,它们为数组或集合中的元素提供了排序逻辑,实现此接口的对象数组或集合可以通过Arrays.sort或Collections.sort进行自动排序。本文将通过示例讲讲它们的使用,需要的可以参考一下2022-12-12Android、iOS和Java通用的AES128加密解密示例代码
现在很多App在与服务器接口的请求和响应过程中,为了安全都会涉及到加密和解密的问题,如果不加的话就会是明文的,即使加了GZIP也可以被直接解压成明文。如果同时有Android和IOS的App的话、必须要保证加密和解密的算法一致、不然后台没法处理,下面通过这篇文章学习下。2016-11-11
最新评论