# sap-connector **Repository Path**: itwangji/sap-connector ## Basic Information - **Project Name**: sap-connector - **Description**: SAP连接工具包 - **Primary Language**: Java - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 4 - **Created**: 2024-10-06 - **Last Updated**: 2024-10-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SAP请求工具 ## 2.0版本更新 1.0版本基于一些历史代码进行重构,并没有实际的去使用,从而导致写出来的代码具有一定的局限性。在实际使用后发现了代码中存在的一些问题,引起了更新2.0版本的欲望。 在1.0版本中,接口名在构建`SapTemplate`对象时就传入,在构造对象的时候就获取到对应的`JCoFunction` 。一开始是看之前的代码都是在方法体中创建连接,并且一次只调用一个接口,所以设计成这个样子。但在另外一个项目中发现,实际情况下还是有在一个方法中调用多个不同的接口的,但是这个时候共用同一个连接就好,没必要重新构建一个`SapTemplate` 对象。 第二个问题其实更为重要,就是框架很不易用,虽然代码使用起来很简洁,已经超过了我在其他项目中看到的调用代码太多了,但是实际使用起来我还是觉得不太好,因为框架使用者是一定要清楚我整个代码的调用逻辑的。例如你在执行`execute()` 之前,必须先调用`function(String)`方法获取接口对象`JCoFunction`。在这种情况下,如果使用者不清楚,没有调用`function(String)`方法就直接去调用传参方法,那这个时候就会直接报空指针异常了,因为function还没有初始化。 第三个问题就是创建连接的方式是固定的,我在代码里写的方式和实际项目中获取连接的方式并不一样(因为我没有引入lesso-core包),不可能让使用者直接去改代码。 基于以上原因,我想让这个工具变得更加易用,而且能够支持不同的创建连接方式。所以我对1.0代码进行了一个重构,优化了上述的这些问题,希望它能变得更好用。 ## 快速开始 **配置实体类** ```java public class SapWorkshopSection { @SapField("VBELN") // <1> private String vbeln; @SapField("KTEXT") private String ktext; public String getVbeln() { return vbeln; } public void setVbeln(String vbeln) { // <2> this.vbeln = vbeln; } public String getKtext() { return ktext; } public void setKtext(String ktext) { this.ktext = ktext; } } ``` 1. 配置SAP返回的字段名; 2. 默认会通过setXXX方法设置值,也可以自定义setter方法名。 **执行请求** ```java import com.lesso.curry.SapTemplate; public class SampleSync { public void sync() { SapTemplate.connect().function("function").execute(); } } ``` ## 自定义连接方式 不同的公司可能封装了自己的创建方式,可以兼容,也可以采用默认的创建方式,直接传入配置的文件名。 ```java import com.lesso.curry.SapTemplate; public class ConnectDemo { public static void main(String[] args) { // 配置文件名为default.jcoDestination SapTemplate.connect(); // 自定义配置文件名:prod.jcoDestination SapTemplate.connect("prod"); // 自定义对象创建方式:default.jcoDestination(默认) SapTemplate.connect(name -> SapUtil.create(name)); // 自定义对象创建方式:prod.jcoDestination(指定文件名) SapTemplate.connect("prod", name -> SapUtil.create(name)); } } ``` ## 数据转换 ### 日期类型转换 目前适配了Date、LocalDate、LocalTime、LocalDateTime。 ```java public class Demo { @SapField(value = "date", formatter = "yyyyMMdd") private LocalDate billDate; } ``` ### 自定义数据转换器 比如SAP返回的字段是字符串,Java端需要按照具体的值,映射成枚举类型,等等。 ```java import com.lesso.curry.SapField; public class Demo { @SapField(value = "status", converter = HttpStatusConverter.class) private HttpStatus httpStatus; } ``` ## 反射 默认框架是以setXXX作为设置值的方法,如果需要自定义,可以使用注解配置。 ```java public class Demo { @SapField(value = "number", setter = "number") private String number; private void number(String number) { this.number = number; } } ``` ## 和之前的方式比较 #### 现有调用 ```java public class Old { private SapSummaryList oldSapSummaryList() { Map param = new HashMap<>(); param.put("I_KUNNR", "0000102245"); param.put("I_VKORG", "1010"); param.put("I_ZBEDA", "20211105"); param.put("I_ZENDA", "20221206"); param.put("I_EXTWG", ""); param.put("I_TYPE", "0"); SapSummaryList sapSummaryList = new SapSummaryList(); SAPConnector sapConnector = new SAPConnector() { }; ServiceUtil.PagingResponse> sapFunc = sapConnector.sapFuncGetListTables(param, sapSummaryList); Map table = sapFunc.getT(); Map msg = sapFunc.getMsgMap(); if (msg.size() > 0) { sapSummaryList.seteZzje(msg.get("E_ZZJE").toString()); } List sapCarItems; List sapSingleItems; if (!table.isEmpty()) { for (Map.Entry entry : table.entrySet()) { String key = entry.getKey(); JCoTable jCoTable = entry.getValue(); if (key.equals("T_ZSSD012")) { sapCarItems = ServiceUtil.getObjectByJCOTable(jCoTable, SapCarItem.class, new SapCarItem().getPropertyMap()); sapSummaryList.setSapCarItems(sapCarItems); } else if (key.equals("T_ZSSD012A")) { sapSingleItems = ServiceUtil.getObjectByJCOTable(jCoTable, SapSingleItem.class, new SapSingleItem().getPropertyMap()); sapSummaryList.setSapCreditItems(sapSingleItems); } } } return sapSummaryList; } } ``` #### 使用本框架 ```java public class News { private SapSummaryList newSapSummaryList() { SapResponse response = SapTemplate.connect().function("ZSDFM041") .addImportantParam("I_KUNNR", "0000102245") .addImportantParam("I_VKORG", "1010") .addImportantParam("I_ZBEDA", "20211105") .addImportantParam("I_ZENDA", "20221206") .addImportantParam("I_EXTWG", "") .addImportantParam("I_TYPE", "0") .execute(); SapSummaryList sapSummaryList = new SapSummaryList(); sapSummaryList.seteZzje(response.output("E_ZZJE")); sapSummaryList.setSapCarItems(response.toList(SapCarItem.class, "T_ZSSD012")); sapSummaryList.setSapCreditItems(response.toList(SapSingleItem.class, "T_ZSSD012A")); return sapSummaryList; } } ``` #### 现有调用2 ```java public class Olds { private SapCreditLimit oldCustomerCredit() { Map param = new HashMap<>(); param.put("KNKLI", "0000102245"); param.put("VKORG", "1010"); param.put("ZORNUM1", ""); param.put("ZORNUM2", ""); param.put("PRICE", 0); SapCreditLimit sapCreditLimit = new SapCreditLimit(); SAPConnector sapConnector = new SAPConnector() { }; ServiceUtil.PagingResponse> sapFunc = sapConnector.sapFuncGetListTables(param, sapCreditLimit); SapCommonCredit sapCommonCredit; SapSzCredit sapSzCredit; Map msg = sapFunc.getMsgMap(); if (msg != null && msg.containsKey("ZCG")) { JCoStructure jCoStructure = (JCoStructure) msg.get("ZCG"); sapCommonCredit = ServiceUtil.getObjectByJCoStructure(jCoStructure, SapCommonCredit.class, new SapCommonCredit().getPropertyMap()); sapCreditLimit.setSapCommonCredits(sapCommonCredit); } if (msg != null && msg.containsKey("ZSZ")) { JCoStructure jCoStructure = (JCoStructure) msg.get("ZSZ"); sapSzCredit = ServiceUtil.getObjectByJCoStructure(jCoStructure, SapSzCredit.class, new SapSzCredit().getPropertyMap()); sapCreditLimit.setSapSzCredits(sapSzCredit); } return sapCreditLimit; } } ``` #### 使用本框架 ```java public class Demo { private SapCreditLimit newCustomerCredit() { return SapTemplate.connect().function("ZSD009") .addImportantParam("KNKLI", "0000102245") .addImportantParam("VKORG", "1010") .addImportantParam("ZORNUM1", "") .addImportantParam("ZORNUM2", "") .addImportantParam("PRICE", 0) .execute() .output(SapCreditLimit.class); } } ``` ## 注意⚠️ 需要注意的是,本框架没有SAP请求需要依赖的配置文件生成功能。