JAVA呼叫Sap的RFC
阿新 • • 發佈:2021-01-21
SAP目前是世界上最大的也是使用最多的ERP系統,很多大型系統都將自己的業務資料放到了SAP系統來進行管理,那麼當別的系統需要這些資料時,就需要從SAP中獲取這些資料。SAP中有各種不同型別的介面,RFC,PI等等。下面記錄的是java如何呼叫RFC的介面。網上可以找到很多類似的文章,程式碼也是以前的老手寫的,也比較易懂,這裡再記下來主要是為了以後找起來方便。
java呼叫RFC介面需要用到sapjco3.jar,windows下還需要將檔案sapjco3.dll檔案放到system32的目錄下,linux下同樣需要把sapjco3.so放入專案的執行目錄下。
需要的sapjco3.dll、sapjco3.so、sapjco3.jar
其實只需要sapjco3.dll(windows)、sapjco3.so(linux)
有兩種方式:
1.sapjco3.jar 放在專案路徑下 打包注意一下 具體不詳細介紹了。
2.Maven的方式引入:
<properties> <sapjco3.version>3.0.11</sapjco3.version> </properties> <dependency> <groupId>com.github.easonjim</groupId> <artifactId>com.sap.conn.jco.sapjco3</artifactId> <version>${sapjco3.version}</version> </dependency>
程式碼如下:
RfcManager.java:
package com.thescm.console.jco; import com.sap.conn.jco.JCoDestination; import com.sap.conn.jco.JCoDestinationManager; import com.sap.conn.jco.JCoException; import com.sap.conn.jco.JCoFunction; import com.sap.conn.jco.ext.DestinationDataProvider; import com.sap.conn.jco.ext.Environment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; /** * RFC 配置中心 * * @author SJ * @date 2021-1-4 16:32:01 */ public final class RfcManager { private final static Logger logger = LoggerFactory.getLogger(RfcManager.class); private static final String ABAP_AS_POOLED = "ABAP_AS_POOL"; private static JcoProvider provider; private static JCoDestination destination; static { Properties properties = loadProperties(); // catch IllegalStateException if an instance is already registered try { provider = new JcoProvider(); Environment.registerDestinationDataProvider(provider); provider.changePropertiesForABAP_AS(ABAP_AS_POOLED, properties); } catch (Exception e) { logger.error("RfcManager registerDestinationDataProvider error:"+e.getMessage(), e); } } public static Properties loadProperties() { Properties connectProperties = new Properties(); // SAP伺服器 connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.xx.xx"); // SAP埠 connectProperties.setProperty(DestinationDataProvider.JCO_MSSERV, ""); // SAP系統編號 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "xx"); // SAP集團 connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "xxx"); // SAP使用者名稱 connectProperties.setProperty(DestinationDataProvider.JCO_USER, "xxxxx"); // SAP密碼 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "xxxxx"); // SAP登入語言 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "zh"); // 最大連線數 connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "xx"); // 最大連線執行緒 connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "xx"); // 連線路由 connectProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, "/x/xxxxx"); return connectProperties; } public static JCoDestination getDestination() throws JCoException { if (destination == null) { destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED); } return destination; } public static void execute(JCoFunction function) { logger.info("SAP Function Name : " + function.getName()); try { function.execute(getDestination()); } catch (JCoException e) { logger.error("RfcManager execute error:", e); } } public static JCoFunction getFunction(String functionName) { JCoFunction function = null; try { function = getDestination().getRepository().getFunctionTemplate(functionName).getFunction(); } catch (JCoException e) { logger.error("RfcManager getFunction JCoException error:", e); } catch (NullPointerException e) { logger.error("RfcManager getFunction NullPointerException error:", e); } return function; } }
RfcSessionReference.java
package com.thescm.console.jco;
import com.sap.conn.jco.ext.JCoSessionReference;
import java.util.concurrent.atomic.AtomicInteger;
/**
* RFC SESSION 管理中心
*
* @author SJ
* @date 2021-1-4 16:32:21
*/
public class RfcSessionReference implements JCoSessionReference {
static AtomicInteger atomicInt = new AtomicInteger(0);
private String id = "session-" + String.valueOf(atomicInt.addAndGet(1));
@Override
public void contextFinished() {
}
@Override
public void contextStarted() {
}
@Override
public String getID() {
return id;
}
}
JcoProvider.java
package com.thescm.console.jco;
import com.sap.conn.jco.ext.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Properties;
/**
* JCO 提供方
*
* @author SJ
* @date 2021-1-4 16:33:02
*/
public class JcoProvider implements DestinationDataProvider, SessionReferenceProvider {
private final static Logger logger = LoggerFactory.getLogger(JcoProvider.class);
private HashMap<String, Properties> secureDBStorage = new HashMap<>();
private DestinationDataEventListener eL;
@Override
public Properties getDestinationProperties(String destinationName) {
try {
//read the destination from DB
Properties p = secureDBStorage.get(destinationName);
if (p != null) {
//check if all is correct, for example
if (p.isEmpty()) {
logger.info("destination configuration is incorrect!");
}
return p;
}
logger.info("properties is null ...");
return null;
} catch (RuntimeException re) {
logger.error("internal error!");
return null;
}
}
@Override
public void setDestinationDataEventListener(
DestinationDataEventListener eventListener) {
this.eL = eventListener;
logger.info("eventListener assigned ! ");
}
@Override
public boolean supportsEvents() {
return true;
}
/**
* implementation that saves the properties in a very secure way
*/
public void changePropertiesForABAP_AS(String destName, Properties properties) {
synchronized (secureDBStorage) {
if (properties == null) {
if (secureDBStorage.remove(destName) != null) {
eL.deleted(destName);
}
} else {
secureDBStorage.put(destName, properties);
// create or updated
eL.updated(destName);
}
}
}
@Override
public JCoSessionReference getCurrentSessionReference(String scopeType) {
RfcSessionReference sesRef = JcoMutiThread.localSessionReference.get();
if (sesRef != null) {
return sesRef;
}
throw new RuntimeException("Unknown thread:" + Thread.currentThread().getId());
}
@Override
public boolean isSessionAlive(String sessionId) {
return false;
}
@Override
public void jcoServerSessionContinued(String sessionID)
throws SessionException {
}
@Override
public void jcoServerSessionFinished(String sessionID) {
}
@Override
public void jcoServerSessionPassivated(String sessionID)
throws SessionException {
}
@Override
public JCoSessionReference jcoServerSessionStarted() throws SessionException {
return null;
}
}
JcoMutiThread.java
package com.thescm.console.jco;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Hashtable;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* JCO執行緒操作
*
* @author SJ
* @date 2021-1-4 15:34:35
*/
public class JcoMutiThread extends Thread {
private final static Logger logger = LoggerFactory.getLogger(JcoMutiThread.class);
public static Hashtable<IMultiStepJob, RfcSessionReference> sessions = new Hashtable<>();
public static ThreadLocal<RfcSessionReference> localSessionReference = new ThreadLocal<>();
private BlockingQueue<IMultiStepJob> queue;
private CountDownLatch doneSignal;
private boolean isSapBusy = false;
public JcoMutiThread(CountDownLatch doneSignal, BlockingQueue<IMultiStepJob> queue) {
this.doneSignal = doneSignal;
this.queue = queue;
}
@Override
public void run() {
try {
for (; ; ) {
IMultiStepJob job = queue.poll(10, TimeUnit.SECONDS);
// stop if nothing to do
if (job == null) {
break;
}
if (isSapBusy) {
Thread.sleep(5000);
}
RfcSessionReference sesRef = sessions.get(job);
if (sesRef == null) {
sesRef = new RfcSessionReference();
sessions.put(job, sesRef);
}
localSessionReference.set(sesRef);
try {
isSapBusy = job.runNextStep();
} catch (Throwable th) {
logger.error("JcoMutiThread runNextStep", th);
}
if (isSapBusy) {
queue.add(job);
} else {
sessions.remove(job);
job.cleanUp();
}
localSessionReference.set(null);
}
} catch (InterruptedException e) {
logger.error("JcoMutiThread run", e);
} finally {
doneSignal.countDown();
}
}
}
IMultiStepJob.java
package com.thescm.console.jco;
/**
* 多步驟任務
*
* @author SJ
* @date 2021-1-4 10:10:16
*/
public interface IMultiStepJob {
boolean runNextStep();
String getName();
void cleanUp();
}