• JAVA 调用 SAP RFC接口【函数】的方式实例【window 和Linux不同部署】


    原文:https://blog.csdn.net/qq_36907589/article/details/105435117

    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下

    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 查看一下 然后用三元运算符赋值为 空串。 

    看完打开支付宝扫一扫领个红包吧!


  • 相关阅读:
    路由控制
    NodeJS -Express 4.0 用include取代partial
    工程的结构文件
    Express 框架的安装
    iconfont阿里爸爸做的开源图库
    12.文件系统fs
    11.事件驱动events
    10.Node.js核心模块
    Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service
    Apache CXF实现Web Service(1)——不借助重量级Web容器和Spring实现一个纯的JAX-WS web service
  • 原文地址:https://www.cnblogs.com/shihaiming/p/15342868.html
Copyright © 2020-2023  润新知