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 我放百度云链接:https://pan.baidu.com/s/1upV7J-JdkiKaH1SczFK6nA 提取码:t33y
其实只需要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();
}