历史版本9 :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; } }
2.2 程序数据集调用

1)定义程序数据集
数据库连接上之后,定义程序数据集,通过我们的程序数据源接口将数据转换成虚拟表,类文件具体代码如下:
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; } }
2)配置程序数据集
详细配置步骤请查看:简单程序数据集

3. 总结编辑

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