1. 程式人生 > 其它 >JAVA呼叫Sap的RFC

JAVA呼叫Sap的RFC

技術標籤:SAPSAP

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();
}