`
xiang37
  • 浏览: 429481 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

使用JCo远程调用SAP系统函数

阅读更多

要用Java程序远程调用ABAP函数可以使用SAP提供的RFC针对Java程序的API——JCo。

 

0.JCo的安装
很不幸,虽然JCo是用Java语言编写的但却是平台相关的。(具体来说,JCo的Java包sapjco.jar确实是平台无关的,但是运行JCo需要RFC库支持,而RFC库是平台相关的)
目前为止我还只有在Windows系统中安装的版本,因为JCo不是一个开源组件,甚至在SAP官方下载它是需要SAP Service MarketPlace的用户帐号的。目前我手上的是JCo2.1.6Windows版本。
除了API文档和一些DEMO程序,你需要用到的有3个文件:librfc32.dll,sapjcorfc.dll,sapjco.jar。

 

安装配置步骤如下:
(1).将sapjco.jar导入到你的项目库路径中。SAP官方的指导是要你配置CLASSPATH,这种方法在我看来不值得提倡,因为eclipse或netBeans这样的IDE可以帮你轻松导入jar库而无需摆弄系统环境变量。
(2).将sapjcorfc.dll文件拷贝至sapjco.jar所在的文件夹中。注意,这两个文件必须放在同一个文件夹里,它们俩必须像热恋中的情人一样一直黏在一起才能使JCo正常工作。
(3).将librfc32.dll文件拷贝至C:\WINDOWS\system32中。如果系统中已安装过SAP客户端,那么可能本来就已经有一个librfc32.dll在那里了,SAP官方要求你覆盖那个文件,这是一种很不负责的方法。当你覆盖这个文件后很可能你的SAPLogon就无法工作了。正确的做法是备份原来的文件,然后尝试覆盖后使用SAPLogon,如果出问题了,把原来那个文件找回来。我在安装了710 Final Release版本的SAPLogon机器上使用原来的librfc32.dll运行JCo目前还没有发生什么异常。

 

好了,到现在为止,JCo算是安装好了,我们可以开始编写程序了。

 

1.使用JCo调用远程ABAP函数 
使用Java程序远程调用ABAP函数的大致流程是这样地:先要有SAP系统所在服务器的IP地址、要登录的SAP系统的客户端号、系统编号、用户名、用户密码,有了这些后,就可以建立一个到该SAP系统的连接,然后在这个连接上调用允许远程调用的函数,得到调用后的结果,关闭连接。
这其中牵涉到一些细节,我们先看程序:

 

package jcousage;

 

import com.sap.mw.jco.IFunctionTemplate;
import com.sap.mw.jco.JCO;
import java.util.Properties;

 

public class TestJCo {

    public static void main(String[] args) {
/*获得一个到SAP系统的连接  START  */
        Properties logonProperties = new Properties();
        logonProperties.put("jco.client.ashost","192.168.1.123"); //系统的IP地址
        logonProperties.put("jco.client.client","800");           //要登录的客户端
        logonProperties.put("jco.client.sysnr","00");             //系统编号
        logonProperties.put("jco.client.user","young98");         //登录用户名
        logonProperties.put("jco.client.passwd","password");      //用户登录口令
        //用上述条件创建一个连接对象
        JCO.Client myConnection = JCO.createClient( logonProperties );
/*获得一个到SAP系统的连接  END    */
        myConnection.connect();       //进行实际连接
        //如果连接不为null并且处于活动状态
        if (myConnection != null && myConnection.isAlive()) {
            //从连接获得一个逻辑意义上的“仓库”对象(Repository)
            JCO.Repository myRepository = 
                new JCO.Repository("Repository",  //只是一个名字
                                   myConnection); //活动的连接
            //要调用的SAP函数名称
            String strFunc = "BAPI_FLIGHT_GETLIST";
            //从“仓库”中获得一个指定函数名的函数模板
            IFunctionTemplate ft = myRepository.getFunctionTemplate(strFunc.toUpperCase());
            //从这个函数模板获得该SAP函数的对象
            JCO.Function function = ft.getFunction();
            //获得函数的import参数列表
            JCO.ParameterList input = function.getImportParameterList();

 

            //设定一个import参数的值。参数名为“MAX_ROWS”,设定值为10
            input.setValue(10, "MAX_ROWS");

 

/*设定结构参数  START  */
            //如果参数是一个结构,用参数名获得一个对应类型的结构对象
            JCO.Structure sFrom = input.getStructure("DESTINATION_FROM");
            //设定结构中的变量。变量名为“CITY”,设定值为“NEW YORK”
            sFrom.setValue("NEW YORK", "CITY");
            //将处理好的结构赋给该参数
            input.setValue(sFrom, "DESTINATION_FROM");
/*设定结构参数  END    */
/*设定table参数  START  */
            //用参数名获得一个对应类型的内部表对象
            JCO.Table tDateRange = function.getTableParameterList().getTable("DATE_RANGE");

 

            //接下来基本属于体力活了......
            //新增一条空行
            tDateRange.appendRow();
            //定位到第0行
            tDateRange.setRow(0);
            //设定该行对应变量
            tDateRange.setValue("I", "SIGN");
            tDateRange.setValue("EQ", "OPTION");
            tDateRange.setValue("20040330", "LOW");

            //新增一条空行
            tDateRange.appendRow();
            //定位到第1行
            tDateRange.setRow(1);
            //设定该行对应变量
            tDateRange.setValue("I", "SIGN");
            tDateRange.setValue("EQ", "OPTION");
            tDateRange.setValue("20040427", "LOW");
            //......
/*设定table参数  END    */
            //执行函数
            myConnection.execute(function);

 

            //在执行函数后可用相同方式获得输出结果
            JCO.Table flights = function.getTableParameterList().getTable("FLIGHT_LIST");
            //JCO.Table对象可以直接输出到html文件
            flights.writeHTML("C:/function.html");
            //也可以如下单独获得表中个别变量
            System.out.println("Airline" + "\t\t"
                               + "from city" + "\t"
                               + "to city" + "\t\t"
                               + "departure time" + "\t\t"
                               + "price" + "\t"
                               + "CURR");
            for (int i = 0; i < flights.getNumRows(); i++) {
                flights.setRow(i);
                System.out.println(flights.getString("AIRLINE") + "\t"
                                 + flights.getString("CITYFROM") + "\t"
                                 + flights.getString("CITYTO") + "\t"
                                 + flights.getDate("FLIGHTDATE") + "\t"
                                 + flights.getDouble("PRICE") + "\t"
                                 + flights.getString("CURR"));
            }
            //断开连接
            myConnection.disconnect();
        } else {
            System.out.println(false);
        }

    }
}//:~

 

首先,将连接需要的信息放到一个Properties里,对应的键值都是固定的。需要注意的是给定的用户名必须有足够的权限进行远程调用。
JCO.Client myConnection = JCO.createClient( logonProperties );
这样就创建了一个到SAP系统的连接对象了。接着只要在这个对象上调用connect()方法就能激活连接。为了保证这个连接确实可用,加上这一句:
if (myConnection != null && myConnection.isAlive())
接下来比较麻烦,先要从这个活动的连接上拿到一个“仓库”,然后从这个“仓库”里拿到函数模板,再从函数模板里拿到对应函数对象。
JCO.Repository myRepository = 
                new JCO.Repository("Repository",  //只是一个名字
                                        myConnection); //活动的连接
String strFunc = "BAPI_FLIGHT_GETLIST";
IFunctionTemplate ft = myRepository.getFunctionTemplate(strFunc.toUpperCase());
JCO.Function function = ft.getFunction();
整个过程很唬人,其实也就那么回事。这里我们调用的是一个叫“BAPI_FLIGHT_GETLIST”函数,这个函数在SAP系统中被声明为Remote-Enabled Module,能够被远程调用的函数都必须声明为Remote-Enabled Module。
好了,我们现在有函数对象了。我们知道,SAP函数主要就是有5个输入输出接口:Import、Export、Changing、Tables、Exceptions。其中除了Changing在远程调用中是不被允许的外,其他都是可用的属性:
Import:通过在函数对象上调用getImportParameterList()方法获得Import变量列表。
JCO.ParameterList input = function.getImportParameterList();
Export:在函数被执行后通过在函数对象上调用getExportParameterList()方法获得Export变量列表。
JCO.ParameterList output = function.getExportParameterList();
Changing:不支持。
Tables:通过在函数对象上调用getTableParameterList()方法获得Tables变量列表。
JCO.ParameterList tables = function.getTableParameterList();
Exceptions:可通过在函数对象上调用getExceptionList()方法获得Exceptions变量数组,也可调用getException(java.lang.String key)获得单个异常对象。
JCO.AbapException[] abapExceptions = function.getExceptionList();
JCO.AbapException abapException = function.getException( "1" );
Import、Export、Tables所获得的都是JCO.ParameterList对象。

 

如果参数是基本类型,则可直接设定:
input.setValue(10, "MAX_ROWS");
Object object = output.getValue("MAX_ROWS");
当然你这样getValue得到的只能是一个Object对象,如果你知道你会得到什么类型(一般情况下你应该知道),你可以直接get这个类型。比如,我们知道"MAX_ROWS"是个int值,所以:
int maxRows = output.getInt("MAX_ROWS");

 

如果参数是一个结构(如果你是个面向对象的程序员,请回忆一下C语言中的结构变量,谢谢),那么你得先得到一个对应此参数的结构对象,然后对结构中的变量成员get或者set:
JCO.Structure sFrom = input.getStructure("DESTINATION_FROM");
sFrom.setValue("NEW YORK", "CITY");
当然如果是Import的话最后别忘了把这个结构放回列表中:
input.setValue(sFrom, "DESTINATION_FROM");

 

在对Tables的参数进行操作时,也得先得到一个与该参数内部表对应的内部表对象:

JCO.Table tDateRange = tables.getTable("DATE_RANGE");
现在这个内部表对象还是空的,所以要先加一行数据,然后将一个逻辑指针指向该行,再进行各个元素的赋值或取值:
tDateRange.appendRow();
tDateRange.setRow(0);
tDateRange.setValue("I", "SIGN");
tDateRange.setValue("EQ", "OPTION");
tDateRange.setValue("20040330", "LOW");
内部表对象支持直接将表内容发送到HTML文件:
JCO.Table flights = function.getTableParameterList().getTable("FLIGHT_LIST");
flights.writeHTML("C:/function.html");
想知道内部表中有几条数据,可以调用getNumRows()方法:
int rows = flights.getNumRows();

 

结束调用时要记得断开连接:
myConnection.disconnect();

 

2.使用连接池
很多时候我们需要进行大量连接,SAP系统本来就脆弱,连接再一多那真的是老牛拉车了。所以我们要用连接池进行连接。下面是一个使用连接池的例子:

package jcousage;

 

import com.sap.mw.jco.JCO;
import java.util.Properties;

 

public class UsageForPool {
    public static void createConnectionPool( String poolName,
                                                int maxConnection,
                                                Properties logonProperties) {
        JCO.Pool pool = JCO.getClientPoolManager().getPool(poolName);
        if(pool == null) {
            JCO.addClientPool( poolName,            // 连接池名
                               maxConnection,       // 最大连接数
                               logonProperties );   // logon设定参数
        }
    }
    public static JCO.Client getConnectionInPool( String poolName ) {
        JCO.Client connection = null;
        JCO.Pool pool = JCO.getClientPoolManager().getPool(poolName);
        if(pool != null) {
            connection = JCO.getClient(poolName);
        }
        return connection;
    }
    public static void releaseConnection( JCO.Client connection ) {
        JCO.releaseClient( connection );
    }
    public static void removeConnectionPool(String poolName) {
        JCO.removeClientPool(poolName);
    }

 

    public static void main(String[] args) {
        Properties logonProperties = new Properties();
        logonProperties.put("jco.client.ashost","192.168.1.123");
        logonProperties.put("jco.client.client","800");
        logonProperties.put("jco.client.sysnr","00");
        logonProperties.put("jco.client.user","young98");
        logonProperties.put("jco.client.passwd","password");

        String poolName = "ThePool";
        createConnectionPool(poolName, 6, logonProperties);
        JCO.Client connection = getConnectionInPool(poolName);
        connection.connect();
        if (connection != null && connection.isAlive()) {
            System.out.println("Connection is alive!");
            releaseConnection(connection);
            removeConnectionPool(poolName);
        } else {
            System.out.println("Connection FALSE!");
        }
    }
}

 

首先,我们仍然需要一个Properties对象用来建立连接,不过这次是建立的连接是一个连接池:
JCO.addClientPool( poolName, maxConnection, logonProperties );
这个方法同时还需要池的名字以及最大连接数一起作为参数。当然在新建一个连接池之前,检查一下有没有相同名字的池已经存在是一个好习惯。
有了池我们就可以在连接池里获得连接啦:
JCO.Client connection = JCO.getClient(poolName);
然后在这个连接对象上激活连接就可以啦:
connection.connect();
接下来就跟上面说的一样用啦,简单吧。
用完别忘了释放连接:
JCO.releaseClient( connection );
如果连接池也不用了就删了它:
JCO.removeClientPool(poolName);

分享到:
评论
1 楼 Sky_257 2012-06-26  
请问  能用abap查询sap服务器的配置、会话、队列、spool等信息么?

相关推荐

    SAPjar包(eclipse中Java使用JCO调用SAP中的RFC函数).zip

    总结,SAP jar包在Eclipse中Java使用JCO调用SAP中的RFC函数涉及到的知识点包括:SAP JCO接口、Eclipse项目配置、SAP系统连接、RFC函数调用、参数传递以及错误处理。通过这种方式,开发者可以利用Java的强大功能与SAP...

    java连接RFC综合例子,java调用sap例子,泛微E8,E9调用SAP RFC例子

    RFC是SAP系统提供的一种接口技术,它允许外部系统与SAP系统交互,调用SAP的函数模块执行特定任务。在Java中,通过使用JCo(Java Connector)库,我们可以实现与SAP系统的RFC连接。 1. **JCo库的介绍**: - JCo是...

    JCO调用SAP 包

    要使用JCO调用SAP,首先需要配置JCO连接参数,包括RFC(Remote Function Call)目的地、用户认证信息、系统ID、主机名、端口号等。这些信息通常在JCO的连接配置文件(如jcoclient.properties)中设置。 3. 创建JCO...

    sapjco3最新版

    1. **远程函数调用(RFC)**:JCo3允许Java应用通过RFC协议调用SAP系统中的ABAP函数模块。RFC是一种标准化的接口技术,使得外部系统可以像调用本地函数一样调用SAP的功能。 2. **BAPI调用**:BAPI(Business ...

    java使用jco连接SAP

    JCo库提供了可以直接在Java程序中使用的API。该API通过JNI调用部署在客户端的SAP的RFC库。...相互独立发布JCo组件的架构,配置,基本使用方法以及调试,如何对RFC方式调用的ABAP函数进行远程调试。

    sapjco30/sapjco3.dll/sapjco3.jar SAP官网2017/7/18更新版本

    开发者可以通过这些API创建JCo连接,定义目的地(destination)信息,如系统ID、用户、密码和端口,然后通过这些目的地调用SAP的功能模块。 "2017/7/18"是这个版本的发布日期,这表明这是SAP在2017年7月18日提供的...

    sapjco3OPlinux下调用sap函数使用的包

    标题中的“sapjco3OPlinux下调用sap函数使用的包”指的是在Linux操作系统中,使用SAP JCo(Java Connector)3版本的库来调用SAP系统中的功能。SAP JCo是一种用于集成SAP系统和其他应用程序的Java API,它允许开发者...

    Java rfc调用 sap 接口 sapjco.jar sapjco.dll 文件

    本话题主要关注如何使用Java通过RFC调用SAP系统,并涉及到关键库文件`sapjco.jar`和`sapjco.dll`。 首先,`sapjco.jar`是SAP Java Connector (JCo)的Java库文件,它为Java应用程序提供了一种与SAP NetWeaver系统...

    Java 调用 SAP RFC 案例

    在Java中调用SAP RFC,通常需要使用JCo(Java Connector)库,这是SAP官方提供的Java API。JCo允许Java应用程序创建与SAP系统之间的连接,通过RFC接口进行交互。要使用JCo,你需要先在SAP系统中配置RFC目的地,然后...

    jco接口调用方式

    它基于Remote Function Call (RFC)协议,允许Java应用程序调用SAP ABAP函数模块,实现数据的实时交换。JCO不仅支持Java到ABAP的Inbound调用,也支持ABAP到Java的Outbound调用。 JCO接口调用方式主要分为以下几个...

    在 Message Broker中使用 SAP JCO 连接 SAP 系统

    JCO 使用远程方法调用(Remote Function Module, RFM)来调用 SAP 系统中的函数模块,实现业务逻辑的执行。在 Message Broker 中集成 SAP JCO,可以构建一个强大的集成环境,使不同系统的数据交换变得简单且高效。 ...

    sapjco3压缩包下载

    4. **JCo Function**: 这是调用SAP ABAP函数模块的主要接口。开发者可以通过创建JCo Function实例,然后设置参数,最后执行函数来实现与SAP的通信。 5. **JCo Structure and Fields**: 这些是数据结构和字段的Java...

    SAP Java JCo 3.1.6 Windows 平台 64bit.zip

    4. **调用RFC** - RFC(Remote Function Call)是SAP提供的远程调用机制,通过JCo可以调用SAP系统中的RFC函数模块执行业务逻辑。 5. **处理结果** - 调用完成后,获取并处理返回的结果数据。 6. **断开连接** - 不再...

    JAVA 调用SAP端接口的相关包(sapjco3.jar,sapjco3.dll,sapjcorfc.dll)

    以上就是使用JCo调用SAP端接口的基本流程。需要注意的是,为了确保兼容性和安全性,开发者需要根据SAP系统版本和操作系统选择正确的JCo版本。此外,SAP官方提供了详细的API文档和示例代码,可以帮助开发者更好地理解...

    sapjco2.3(sapjco2.3.dll和sapjco2.3.jar)

    这个 DLL 文件提供了本地接口,使得 Java 应用程序能够调用 SAP 的 RFC(远程功能调用)函数。RFC 是 SAP 系统中的一种标准接口技术,允许外部系统与 SAP 进行数据交换。通过 sapjco2.3.dll,Java 开发者可以创建 ...

    sapjco zip JAVA调用SAP 所需要的资料

    "sapjco zip JAVA调用SAP 所需要的资料"这个主题,涉及到的是使用Java通过JCO(Java Connector)来连接和通信SAP系统的核心组件。让我们详细探讨这些关键文件的作用以及如何使用它们。 首先,`sapjco3.dll`是SAP ...

    sapjco3.0.14

    开发者需要在Java代码中导入SAP JCo库,然后创建连接、建立会话,并通过JCo提供的API调用SAP系统的RFC函数。这包括注册RFC目的地、创建并执行RFC调用、处理返回结果等步骤。 4. 示例代码: ```java ...

    sapjco.jar sapjco.dll 可扩展文件

    这个文件是 Java 应用程序调用 SAP 功能的基础,它提供了连接、执行 RFC(远程功能调用)以及处理结果等功能。开发者通过导入这个 JAR 文件,可以在他们的 Java 代码中使用 SAP JCo API 来创建 SAP 连接,执行 ABAP ...

    SAP官网最新版本 sapjco3.jar

    SAP是一种全球领先的业务软件,用于企业...总的来说,SAP JCo3是Java开发者与SAP系统集成的重要工具,提供了高效且灵活的API来调用SAP的功能。通过理解其工作原理和最佳实践,你可以更有效地构建与SAP集成的应用程序。

Global site tag (gtag.js) - Google Analytics