历史版本7 :SAP的RFC接口调用 返回文档
编辑时间: 内容长度:图片数:目录数: 修改原因:

SAP作为独立的系统,与其它系统进行交互的时候,主要是两种方式:1:底层数据库直接交互;2:通过SAP专门的RFC接口进行数据调用。

SAP现在主要的数据库平台有两种关系型数据库,Oracle和DB2,第一种方式FineReport通过JDBC的方式直连SAP数据库来解决,详细请查看数据库连接,但是使用这种方式,制作人员需要对SAP数据库了解比较深,并且数据库可以对其他软件开放。下面主要介绍第二种方式。

1. 设计思路编辑

首先通过java类文件建立和SAP的连接,然后通过程序数据集接口,将RFC调出来的数据进行虚拟二维表封装,调用虚拟二维表,进行报表的制作。

2. 实现步骤编辑

2.1 建立连接
通过ConnectSAPServer类实现与SAP的连接,类文件的代码如下:
package com.fr.function;      import java.io.File;   import java.io.FileOutputStream;   import java.util.Properties;      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;      public class ConnectSAPServer {       static String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL";       static {           Properties connectProperties = new Properties();           connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST,                   "SAP服务器IP地址");           connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "系统编号");           connectProperties                   .setProperty(DestinationDataProvider.JCO_CLIENT, "客户端编号(SAP中的,和客户端没关系)");           connectProperties.setProperty(DestinationDataProvider.JCO_USER,                   "用户名");           connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,                   "密码");           connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");           connectProperties.setProperty(                   DestinationDataProvider.JCO_POOL_CAPACITY, "10");           connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,                   "10");           createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);       }          static void createDataFile(String name, String suffix, Properties properties) {           File cfg = new File(name + "." + suffix);           if (!cfg.exists()) {               try {                   FileOutputStream fos = new FileOutputStream(cfg, false);                   properties.store(fos, "SAP连接配置文件");                   fos.close();               } catch (Exception e) {                   throw new RuntimeException(                           "Unable to create the destination file "                                   + cfg.getName(), e);               }           }       }          public static JCoDestination Connect() {           JCoDestination destination = null;           try {               destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);           } catch (JCoException e) {               e.getCause();           }           return destination;       }   }  
注:最新的代码链接fine-help
2.2 程序数据集调用
  • 定义程序数据集
数据库连接上之后,定义程序数据集,通过我们的程序数据源接口将数据转换成虚拟表,类文件具体代码如下:
package com.fr.data;      import com.fr.base.FRContext;   import com.fr.base.Parameter;   import com.fr.data.AbstractTableData;   import com.sap.conn.jco.JCoDestination;   import com.sap.conn.jco.JCoException;   import com.sap.conn.jco.JCoFunction;   import com.sap.conn.jco.JCoTable;   public class ParamSAPDataTest extends AbstractTableData   {     private String[] columnNames = null;        private int columnNum = 3;           private String[][] rowData;     private static JCoDestination jCoDestination;        public ParamSAPDataTest()     {       this.parameters = new Parameter[] { new Parameter("LIFNR"),          new Parameter("NAME1") };          this.columnNames = new String[this.columnNum];       this.columnNames[0] = "供应商编码";       this.columnNames[1] = "供应商名称";       this.columnNames[2] = "供应商地址";     }        public int getColumnCount() {       return this.columnNum;     }        public String getColumnName(int columnIndex) {       return this.columnNames[columnIndex];     }        public int getRowCount() {       try {         init();       }       catch (JCoException e) {         FRContext.getLogger().info("失败");       }       return this.rowData.length;     }        public Object getValueAt(int rowIndex, int columnIndex) {       try {         init();       }       catch (JCoException e) {         FRContext.getLogger().info("失败");       }       if (columnIndex >= this.columnNum) {         return null;       }       return this.rowData[rowIndex][columnIndex];     }        public void init() throws JCoException {       if (this.rowData != null) {         return;       }       try       {       jCoDestination = ConnectSAPServer.Connect();       }catch (Exception e) {           FRContext.getLogger().info("失败");         }       JCoFunction function = jCoDestination.getRepository().getFunction("Z_LFA3_QUERY");       if (function == null)         throw new RuntimeException(           "Function not found in SAP.");       function.getImportParameterList().setValue("LIFNR", "%"+this.parameters[0].getValue().toString().toUpperCase().trim()+"%");       function.getImportParameterList().setValue("NAME1", "%"+this.parameters[1].getValue().toString().toUpperCase().trim()+"%");       function.execute(jCoDestination);       JCoTable returnTable = function.getTableParameterList().getTable(         "ZLFA1S3");       rowData=new String[20][3];       if (returnTable.getNumRows() > 0) {         returnTable.firstRow();         for (int i = 0; i < 20; )         {           String[] objArray = new String[this.columnNum];           objArray[0] = returnTable.getString("LIFNR");           objArray[1] = returnTable.getString("NAME1");           objArray[2] = returnTable.getString("STRAS");           this.rowData[i]=objArray;              i++; returnTable             .nextRow();         }            FRContext.getLogger().info(           "Query SQL of ParamSAPDataTest: \n" + this.rowData.length +            " rows selected");       }     }        public void release() throws Exception {       super.release();       this.rowData = null;     }   }  
注:最新的代码链接fine-help
  • 配置程序数据集
详细配置步骤请查看:简单程序数据集

3. 总结编辑

通过RFC接口这种方式避免了直连数据库的问题,而这些RFC参数和调用表结构网上或者SAP供应商都会提供,不过缺点在于需要写类文件来获取数据,报表多的时候比较麻烦,如果要达到一些图表联动等效果,需要在类里面写参数,修改起来不是很方便,需要技术人员进行报表制作,业务人员比较困难。