历史版本2 :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供应商都会提供,不过缺点在于需要写类文件来获取数据,报表多的时候比较麻烦,如果要达到一些图表联动等效果,需要在类里面写参数,修改起来不是很方便,需要技术人员进行报表制作,业务人员比较困难。