java要調用 SAP RFC接口時,需要用到sapjco3.jar 架包;
網上說的亂八七糟的windows將sapjco3.dll 文件放到system32的目錄下.............我嫌棄麻煩沒用;
本人經歷親測可用的簡單粗暴的方式:
先說windows下還需要將文件sapjco3.dll 和 sapjco3.jar文件放到項目下WEB-INF/lib 下直接就可以用。
此時tomcat/bin下面會生成一個文件【*****.jcoDestination】如果測試-正式切換的時候,這個不會變,要手動更改。
【Java 調用sap 切換正式怎麼還是測試的問題】{ 後面會講解到!}
Linux別急下面再詳細說一下Linux的配置,坑的要死。。。(各種百度各種查)
下載鏈接:鏈接:https://pan.baidu.com/s/1dFKyvldScvXxIXP18nmtpA
提取碼:cvde
不樂意掙這個csdn幣 直接放百度雲,有用的話給個雙擊就行。
java項目下直接把sapjco3.jar 和sapjco3.dll 兩個文件da放到 項目lib下
直接上代碼:連接sap
package com.jeecg.sapjco;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;
import org.jeecgframework.core.annotation.JAuth;
import org.jeecgframework.core.enums.Permission;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;
@JAuth(auth= Permission.SKIP_AUTH) //跳過外部調用攔截
public class GetSapConn {
static String ABAP_AS_POOLED = "SAP-RFC"; //所屬異構系統 【找sap要】
private static void createDataFile() {
Properties properties = new Properties();
//測試
properties.setProperty(DestinationDataProvider.JCO_ASHOST, "**.**.**.***");//sap服務器地址
properties.setProperty(DestinationDataProvider.JCO_SYSNR, "02");//系統編號,找SAP覈對寫00就可以了
properties.setProperty(DestinationDataProvider.JCO_CLIENT, "6**");//集團號,不知道就問你們的sap basis
properties.setProperty(DestinationDataProvider.JCO_USER, "***");//帳號
properties.setProperty(DestinationDataProvider.JCO_PASSWD, "****");//密碼
properties.setProperty(DestinationDataProvider.JCO_LANG, "zh");//語言
String name = ABAP_AS_POOLED;
String suffix = "jcoDestination";
File cfg = new File(name + "." + suffix);
if (!cfg.exists()) {
try {
FileOutputStream fos = new FileOutputStream(cfg, false);
properties.store(fos, "for tests only !");
fos.close();
} catch (Exception e) {
throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
}
}
}
public static JCoDestination getJcoConnection() throws JCoException {
createDataFile();
return JCoDestinationManager.getDestination(ABAP_AS_POOLED);
}
}
測試案例【傳入參數調用sap函數返回結果】
package com.jeecg.sapjco;
import com.jeecg.roomRecord.entity.TAWorkroomRecordEntity;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterList;
import com.sap.conn.jco.JCoTable;
import org.jeecgframework.core.annotation.JAuth;
import org.jeecgframework.core.common.controller.BaseController;
import org.jeecgframework.core.common.model.json.AjaxJson;
import org.jeecgframework.core.constant.Globals;
import org.jeecgframework.core.enums.Permission;
import org.jeecgframework.minidao.annotation.Param;
import org.jeecgframework.web.cgform.exception.BusinessException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/SapTest")
@JAuth(auth= Permission.SKIP_AUTH)
public class SapTest extends BaseController {
/**
*
* @param request
* @return
*
* Sap 函數:ZFI_FM_009
*/
@RequestMapping(params = "test")
@ResponseBody
public AjaxJson test(HttpServletRequest request) {
String message = null;
AjaxJson j = new AjaxJson();
try {
JCoDestination jCoDestination = null;// 連接對象
JCoFunction function = null;// 調用rfc函數對象
try {
jCoDestination=GetSapConn.getJcoConnection();
//// 調用rfc-sap【ZFI_FM_009】函數對象--指的是調用sap 那邊的函數名
function = jCoDestination.getRepository().getFunctionTemplate("ZFI_FM_009").getFunction();
if (null == function) {
throw new RuntimeException("get function not found in sap");
} else {
JCoParameterList paramList = function.getImportParameterList();
//【sap系統傳入參數,有多個的話就寫多行 LV_BANKA sap定義的函數參數名 有多個的話就寫多行】
paramList.setValue("LV_BANKA","參數值");
paramList.setValue("LV_BANKL","參數值");
//如果傳如參數是內表的形式的話就以如下代碼傳入sap系統
// JCoTable table1 = function.getTableParameterList().getTable("I_EKPO");
// for (int i = 0; i < purchaseNo.size(); i++) {
// table1.setRow(i);
// table1.appendRow();
// table1.setValue("EBELN", purchaseNo.get(i)[0]);
// table1.setValue("EBELP", purchaseNo.get(i)[1]);
// }
function.execute(jCoDestination);//執行調用函數
JCoTable table2 = function.getTableParameterList().getTable("ES_DATA");//[ES_DATA 是SAP返回 數據的“表名字”]得到sap返回的參數,你就把他當作c語言的結構體理解就可以了
//有時候sap那邊只是返回一個輸出參數,sap比方說你這邊輸入一個物料號,想得到sap那邊的物料描述,這是sap方是不會返回一個內表給你的
//而是隻是返回一個輸出參數給你這時你就要用到下面的方法來得到輸出參數
//paramList = function.getExportParameterList();
//paramList.getString("rfc返回字段字段名稱");
for (int i = 0; i < table2.getNumRows(); i++) {
table2.setRow(i);
//這裏獲取sap函數傳出內表結構的字段 【傳入的字符串爲調用函數需要傳入的參數名,必須爲大寫】
String BANKL = table2.getString("BANKL");//【表結果裏面的字段】記住這裏BANKL一定是大寫的,不然得不到值
String BANKA = table2.getString("BANKA");//【表結果裏面的字段】記住這裏BANKA一定是大寫的,不然得不到值
System.out.println("BANKL:"+BANKL +"------"+ "BANKA"+BANKA);
//得到了sap數據,然後下面就是你java擅長的部分了,想封裝成什麼類型的都由你
}
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
jCoDestination = null;
}
} catch (Exception e) {
e.printStackTrace();
message = "失敗";
throw new org.jeecgframework.core.common.exception.BusinessException(e.getMessage());
}
j.setMsg(message);
return j;
}
}
執行結果:
如果是 普通參數(相當於java 方法傳入一個字符串 ) + 結構參數的話 說白了結構類型就相當於java傳入一個Map
/**
* IV_TYPE
* IV_IS_COMMIT
* IS_DATA [結構類型]
* OA存儲主數據存儲接口--結構類型
* ZSD_FM_CREATE_CUSTOMER
* chufangbo 2020-04-11
*/
@RequestMapping(params = "get***SAP***Function")
@ResponseBody
public AjaxJson getSapBackFunction(HttpServletRequest request) {
//TDingOaInfoEntity entity = JSONObject.parseObject(jsonObject, TDingOaInfoEntity.class);
String message = null;
AjaxJson j = new AjaxJson();
try {
JCoDestination destination = JCoDestinationManager
.getDestination(ABAP_AS);//所屬異構系統OA或者SAP提供
JCoFunction function = destination.getRepository().getFunction(
"ZSD_FM_*******");//從對象倉庫中獲取 RFM 函數
if (function == null)
throw new RuntimeException("RFC_SYSTEM_INFO not found in SAP.");
try {
function.execute(destination);
} catch (AbapException e) {
System.out.println(e.toString());
}
JCoParameterList is_data_sum = function.getImportParameterList();
is_data_sum.setValue("IV_TYPE","1");// 普通參數
is_data_sum.setValue("IV_IS_COMMIT","X");// 普通參數
//IS_DATA 是SAP 結構名稱 類是與JAVA Map當參數傳入Funtion的參數封裝
JCoStructure is_data = function.getImportParameterList().getStructure("IS_DATA");
is_data.setValue("KTOKD","***");// KTOKD 是結構中的名稱類似於java 傳入一個map,在此處通過key賦值value進行封裝
//.............繼續添加
is_data_sum.setValue("IS_DATA",is_data);
function.execute(destination);//執行調用函數
JCoTable table2 = function.getTableParameterList().getTable("MESSTAB");//[MESSTAB 是SAP返回 數據的“表名字”]得到sap返回的參數,你就把他當作c語言的結構體理解就可以了
//有時候sap那邊只是返回一個輸出參數,sap比方說你這邊輸入一個物料號,想得到sap那邊的物料描述,這是sap方是不會返回一個內表給你的
//而是隻是返回一個輸出參數給你這時你就要用到下面的方法來得到輸出參數
//獲取sap回執編號
JCoParameterList exportParameterList = function.getExportParameterList();
Object ev_kunnr = exportParameterList.getValue("EV_KUNNR");
System.out.println("獲取SAP回傳客戶編號: "+ev_kunnr);
for (int i = 0; i < table2.getNumRows(); i++) {
table2.setRow(i);
//這裏獲取sap函數傳出內表結構的字段 【傳入的字符串爲調用函數需要傳入的參數名,必須爲大寫】
String TYPE = table2.getString("TYPE");//[消息類型:S 成功 E 錯誤 W警告 I信息 A 中斷]記住這裏參數一定是大寫的,不然得不到值【如果報錯說明你參數傳的不對】
String MESSAGE = table2.getString("MESSAGE");//記住這裏一定是大寫的,不然得不到值
System.out.println("TYPE:"+TYPE +"MESSAGE:"+MESSAGE);
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
j.setMsg(message);
return j;
}
開始Linux :
首先不要依靠以上配置,和百度所說的去Linux去配置環境變量什麼的。。。都沒用。。。害我南轅北轍,ca踩了一個坑,跳出來又踩進去,又跳出來,又踩進去。。。。。
開始正文
找到Linux項目中的Tomcat /home/...../apache-tomcat-dd/webapps/項目名稱/WEB-INF/lib
第一步 把以下三個文件丟進去。sapjcorfc 這兩個文件,看網上說的天花亂墜的我是沒用到。
第二步:找到 /home/......./apache-tomcat-dd/bin
把這兩個文件丟進去,然後重新啓動項目
然後你會發現 在bin目錄下面生成一個 類是與 SAP-RFC.jcoDestination 。
註釋:SAP-RFC是我調用sap那邊定義的所屬異構系統的名字,不用管,你們可能生成的別的名字
另外【如果本地測試之後沒問題,或者到服務器上測試沒問題的話,切換到正式連接之後發現數據還是測試庫的,憋着急,此時請查看本地Tomcat 和服務器上tomcat/bin 目錄下的SAP-RFC.jcoDestination ,的地址配置的還是測試庫的,修改保存一下就OK了】
如果你們沒生成,等會我在文章最開始的百度雲放一個,你們模仿寫一下你們自己的配置。添加進去。這個東西很重要,如果沒有就會調用失敗。
大致就是:(你們可以自己寫一個方進去SAP-RFC是我調用sap那邊定義的 你們用你們自己的)
#for tests only !
#Mon Apr 20 11:03:50 CST 2020
jco.client.lang=zh
jco.client.client=***
jco.client.passwd=***
jco.client.user=*****
jco.client.sysnr=0*
jco.client.ashost=2*.2*.2*.2**
大功告成:
註釋:如果SAP那邊報錯
可能就是通過JAVA傳輸的時候 sap 那邊不支持 Null,此時你可以debug 查看一下 然後用三元運算符賦值爲 空串。