Java連接SAP RFC實(shí)現(xiàn)數(shù)據(jù)抽取的示例詳解
包管理
首先要連接SAP需要兩個(gè)包,分別為sapjco3.jar和sapjco3.dll,切記這兩個(gè)包需要放在同一目錄;否則會(huì)報(bào)錯(cuò)。
我先嘗試將這兩個(gè)包發(fā)到私服上,再在pom.xml文件中引入,發(fā)現(xiàn).dll文件下載不了;于是就將這兩個(gè)包放在根目錄sap下,dockerfile構(gòu)建鏡像時(shí)將這兩個(gè)包c(diǎn)opy到j(luò)dk/lib目錄下。
COPY sap/sapjco3.dll /usr/local/jdk-17.0.5/lib/ COPY sap/sapjco3.jar /usr/local/jdk-17.0.5/bin/
功能介紹
- 連接SAP
- 入?yún)@取
- 出參獲取
- 函數(shù)列表獲取
- 表名獲取
- 函數(shù)執(zhí)行
- 執(zhí)行結(jié)果獲取
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");// 服務(wù)器 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "xx"); // 系統(tǒng)編號(hào) connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "xxx"); // SAP集團(tuán) connectProperties.setProperty(DestinationDataProvider.JCO_USER, "xxx"); // SAP?戶名 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "xxx"); // 密碼 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH"); // 登錄語(yǔ)?:ZH EN connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3"); // 最?連接數(shù) connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10"); // 最?連接線程 // 注冊(cè)連接參數(shù) destDataProvider.addDestination(ABAP_AS_POOLED, connectProperties); Environment.registerDestinationDataProvider(destDataProvider); // 創(chuàng)建一個(gè)與SAP系統(tǒng)的連接 JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED); // 調(diào)用函數(shù) function = destination.getRepository().getFunction("funcationName"); if(null == function) { throw new RuntimeException("無(wú)此函數(shù)"); } // 輸入字段 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); } // 獲取所有函數(shù) function = destination.getRepository().getFunction("RFC_FUNCTION_SEARCH"); if(null == function) { throw new RuntimeException("無(wú)此函數(shù)"); } 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("函數(shù)名:"+functionName); } //獲取所有表名 JCoParameterList tableParameterList = function.getTableParameterList(); if(tableParameterList!=null){ for (JCoField jCoField : tableParameterList) { System.out.println("表:" + jCoField.getName()); } } // 輸?參數(shù)修改 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");//以表作為請(qǐng)求參數(shù) // it_matnr.appendRow(); // it_matnr.setValue("age",18);//設(shè)置表值 //方法執(zhí)行 function.execute(destination); // 函數(shù)執(zhí)行結(jié)果 JCoTable jcoTable = function.getTableParameterList().getTable("tableName"); int numRows = jcoTable.getNumRows();//行數(shù)為0可以直接return for (int i = 0; i < numRows; i++) { jcoTable.setRow(i);//設(shè)置索引 獲取返回表里的數(shù)據(jù) String fieldValue= jcoTable.getString("fieldName");//解析表字段值 System.out.println(fieldValue); } } catch (Exception e) { e.printStackTrace(); } finally { // 取消環(huán)境注冊(cè) Environment.unregisterDestinationDataProvider(destDataProvider); } } }
/** * 實(shí)現(xiàn)DestinationDataProvider接口,用于注冊(cè)連接參數(shù) */ 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; } }
當(dāng)然也可以通過創(chuàng)建文件的方式保存連接屬性
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");// 服務(wù)器 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "xx"); // 系統(tǒng)編號(hào) connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "xxx"); // SAP集團(tuán) connectProperties.setProperty(DestinationDataProvider.JCO_USER, "xxx"); // SAP?戶名 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "xxx"); // 密碼 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH"); // 登錄語(yǔ)?:ZH EN connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3"); // 最?連接數(shù) connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10"); // 最?連接線程 createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties); } /** * 創(chuàng)建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; } }
在使用場(chǎng)景中,我遇到了這樣一種情況:
SpringBoot服務(wù)已啟動(dòng),sap函數(shù)入?yún)蓚€(gè),上面代碼獲取sap函數(shù)入?yún)蓚€(gè); 我將sap函數(shù)入?yún)⒏臑槿齻€(gè)后,上面代碼獲取還是兩個(gè),重啟服務(wù)后獲取就是正確的三個(gè)了。
經(jīng)過研究發(fā)現(xiàn),JCoDestinationManager.getDestination(ABAP_AS_POOLED);
會(huì)緩存destination
連接,每次都是先從緩存中取
RfcDestination destination = (RfcDestination)this.destinations.get(destinationName);
查看destination.getRepository()
會(huì)發(fā)現(xiàn)storage字段緩存了function等信息;解決辦法是:
// 清除緩存 destination.getRepository().clear();
清除緩存后,每次會(huì)獲取新的內(nèi)容。
到此這篇關(guān)于Java連接SAP RFC實(shí)現(xiàn)數(shù)據(jù)抽取的示例詳解的文章就介紹到這了,更多相關(guān)Java數(shù)據(jù)抽取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問題示例
這篇文章主要介紹了java實(shí)現(xiàn)拉鉤網(wǎng)上的FizzBuzzWhizz問題示例,需要的朋友可以參考下2014-05-05java實(shí)現(xiàn)浮點(diǎn)數(shù)轉(zhuǎn)人民幣的小例子
java實(shí)現(xiàn)浮點(diǎn)數(shù)轉(zhuǎn)人民幣的小例子,需要的朋友可以參考一下2013-03-03Spring配置文件解析之BeanDefinitionReader詳解
這篇文章主要介紹了Spring配置文件解析之BeanDefinitionReader詳解,ApplicationContext.xml配置文件解析成Document對(duì)象,真正對(duì)xml中元素解析的類是在BeanDefinitionDocumentReader的實(shí)現(xiàn)類中來完成的,需要的朋友可以參考下2024-02-02如何使用Comparator比較接口實(shí)現(xiàn)ArrayList集合排序
這篇文章主要介紹了如何使用Comparator比較接口實(shí)現(xiàn)ArrayList集合排序問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12java如何執(zhí)行bat腳本,并監(jiān)控執(zhí)行結(jié)果
這篇文章主要介紹了java如何執(zhí)行bat腳本,并監(jiān)控執(zhí)行結(jié)果問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Java滾動(dòng)數(shù)組計(jì)算編輯距離操作示例
這篇文章主要介紹了Java滾動(dòng)數(shù)組計(jì)算編輯距離操作,涉及java字符串與數(shù)組的遍歷、計(jì)算、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2019-12-12Mybatis resultType返回結(jié)果為null的問題排查方式
這篇文章主要介紹了Mybatis resultType返回結(jié)果為null的問題排查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03