1. 程式人生 > 實用技巧 >在spring boot中使用sapjco3,並用docker部署到Linux伺服器

在spring boot中使用sapjco3,並用docker部署到Linux伺服器

一、在windows中的配置

二、linux的配置

三、spring boot專案構建

sapjco3包含很多個作業系統版本,不同的作業系統需要使用不同的配置檔案和配置方式,不過sapjco3.jar是可以通用的。

一、在windows中的配置

windows中需要的檔案主要包括:

sapjco3.dll

sapjco3.pdb

sapjco3.jar

1、sapjco3.dll檔案

32位系統

將 sapjco3.dll 加入到c:/windows/system32/目錄 或者 將 sapjco3.dll 加入到 JDK/bin 目錄下;

64位系統

將 sapjco3.dll 加入到c:/windows/SysWOW64/目錄 或者 將 sapjco3.dll 加入到 JDK/bin 目錄下;

64位機可以直接將sapjco3.dll放在"C:\Windows\System32"目錄下,這樣以後不必針對具體的應用來配置它;

上面的配置是為了將它放在系統環境變數path可以找到的地方,所以也可以直接把sapjco3.dll檔案所在的位置,配置到系統環境變數path下面;

2、sapjco3.pdb檔案

在springboot中使用sapjco3可以不用配置sapjco3.pdb,如果在kettle中需要呼叫sap的介面,則需要把sapjco3.pdb放在kettle的根目錄"${KETTLE_HOME}/"下面;

3、sapjco3.jar檔案

這個檔案就是java呼叫sap的主要api,包含許多方法,如連線sap、獲取介面引數、設定介面引數和獲取返回引數等;

這裡推薦將sapjco3.jar放在專案的lib目錄下面,然後在專案打包的時候,將本地依賴的jar包打包到專案jar中

也可以將sapjco3.jar放在${JAVA_HOME}/lib目錄下或者放在其他目錄並將該目錄下的sapjco3.jar新增到系統環境變數CLASSPATH下面;

也可以在pom.xml中引入sapjco3.jar依賴,這樣專案打包的時候會將sapjco3.0.14.jar打包到專案jar裡面,但是這樣sapjco3.jar檔案是帶有版本字尾的,在專案部署的時候,會啟動失敗,報It is not allowed to rename or repackage the original archive “sapjco3.jar”

需要手動進入jar包,將sapjco3.0.14.jar名稱修改為sapjco3.jar;

<!-- https://mvnrepository.com/artifact/com.sap.conn.jco/sapjco3 -->
<dependency>
        <groupId>com.sap.conn.jco</groupId>
        <artifactId>sapjco3</artifactId>
        <version>3.0.14</version>
        <scope>test</scope>
</dependency>

還有一種方式是使用maven的install命令將sapjco3.jar安裝到本地倉庫,然後在專案中引入依賴,但是切記jar包不能字尾版本號;


二、linux的配置

linux需要的檔案包括:

libsapjco3.so

sapjco3.jar

其中jar包sapjco3.jar與windows版的可以通用;重點是將libsapjco3.so檔案配置到linux的jre/lib執行時環境中或者專案可以載入到libsapjco3.so的其他位置;

1、Linux系統:

1)將壓縮檔案解壓到某個目錄下面,比如/home/appuser/sapjco3/ 下面:

tar -zxvfsapjco3-linuxx86_64-3.0.17.tgz -C /home/appuser/sapjco3

2)配置環境變數

vim /etc/profile

在配置檔案內加上下面的內容:

export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/appuser/sapjco3

export CLASSPATH=.:${JAVA_HOME}/lib:${LD_LIBRARY_PATH}/sapjco3.jar

或者

先將檔案libsapjco3.so複製到${JAVA_HOME}/jre/lib/amd64/server資料夾下

export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${JAVA_HOME}/jre/lib/amd63/server

export CLASSPATH=.:${JAVA_HOME}/lib:${LD_LIBRARY_PATH}/sapjco3.jar

上面配置的重點是libsapjco3.so的位置,對於sapjco3.jar,可以配置到環境變數${CLASSPATH}中,也可以打包在專案中;

官方的推薦如下:

2、docker:

在docker中可以使用 -v 宿主機目錄:容器目錄 的方式將libsapjco3.so和sapjco3.jar進行對映:

docker run -d \

--restart=always \

--name springboot-sapjco3 \

-v "$PWD/sapringboot-sapjco3":/usr/app \

-v /home/appuser/sapjco3/libsapjco3.so:/usr/lib/libsapjco3.so \

--workdir="/usr/app" \

-p 8080:8080 \

java:8u111 \

java -jar sprringboot-sapjco3.jar

這樣就將宿主機的libsapjco3.so對映到了容器的/usr/lib下面;

如果專案中沒有打包sapjco3.jar檔案,也可以在docker run 的 -v 命令中將該檔案對映到jdk的lib目錄下:

-v /hemo/appuser/sapjco3/sapjco3.jar:/usr/lib/jvm/java-8-openjdk-amd64/lib/sapjco3.jar

三、spring boot專案構建

1、專案結構與配置檔案

將sapjco3.jar放在專案resource/lib下面;

CONNECT_SAP_CONFIG.jcoDestination檔案是連線SAP的配置檔案,必需放在專案的根目錄下面,其內容如下:

#for tests only !
jco.client.lang=en
jco.client.client=710
jco.client.user=admin
jco.client.passwd=admin
jco.client.sysnr=00
jco.client.ashost=192.168.1.11

配置pom.xml,引入自定義jar包,並在專案打包時將自定義jar包打包進專案的jar:

<dependencies>
        <!--maven打包時,將resources/lib/sapjco3.jar一併打包-->
        <dependency>
            <groupId>com.sap</groupId>
            <artifactId>sapjco3</artifactId>
            <version>1.0</version>
            <scope>system</scope>
          <systemPath>${project.basedir}/src/main/resources/lib/sapjco3.jar</systemPath>
        </dependency>
        <!--其他依賴-->
        <dependency>
              ......
        </dependency>
<dependencies>
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>true</executable>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>springloaded</artifactId>
                        <version>1.2.5.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
</build>

2.獲取sap連線物件

public class JCoDestinationBuilder {
    public static JCoDestination destination = null;
    private static final Logger logger = LogUtils.getPlatformLogger();
    public static JCoDestination build() throws JCoException {
        if (null==destination) {
            synchronized (JCoDestinationBuilder.class) {
                try {
                    if (null == destination)
                        destination = JCoDestinationManager.getDestination("CONNECT_SAP_CONFIG");
                    destination.ping();
                    logger.info("Connect to SAP successfully......");
                } catch (JCoException e) {
                    e.printStackTrace();
                    logger.error("Connect to SAP failed, error msg: " + e.toString());
                }
            }
        }
        //logger.info(String.valueOf(destination.getAttributes()));
        return destination;
    }
}

3.呼叫sap介面函式

@Service
public class SappiMonitorServiceImpl implements SappiMonitorService {
    @Autowired
    Sm58EntityRepository sm58EntityRepository;
    @Autowired
    MessageService messageService;
    @Autowired
    private Environment environment;
    private static final Logger logger = LogUtils.getPlatformLogger();

    @Override
    public JSONObject monitorSm58(SappiSm58 sappiSm58) throws JCoException {
        if (sappiSm58==null) sappiSm58 = new SappiSm58();
        JCoDestination destination = JCoDestinationBuilder.build();
        JCoFunction function = destination.getRepository().getFunction("ZMONITOR_SM58");
        JCoParameterList importlist = function.getImportParameterList();
        JCoParameterList exportList = function.getExportParameterList();
        JCoParameterList tables = function.getTableParameterList();
importlist.setValue(
"I_BEGIN_DATE",sappiSm58.getI_begin_date()); importlist.setValue("I_END_DATE",sappiSm58.getI_end_date()); try { function.execute(destination); //logger.warn(function.toXML()); } catch (JCoException e) { e.printStackTrace(); logger.error("execute()failed......"); } JCoTable t_arfcistate = tables.getTable("T_ARFCISTATE"); for (int i=0;i<t_arfcistate.getNumRows();i++) { t_arfcistate.setRow(i); Sm58Entity sm58Entity = new Sm58Entity(); sm58Entity.setArfcipid(t_arfcistate.getString("ARFCIPID")); sm58Entity.setArfcpid(t_arfcistate.getString("ARFCPID")); sm58Entity.setArfctime(t_arfcistate.getString("ARFCTIME")); sm58Entity.setArfctidcnt(t_arfcistate.getString("ARFCTIDCNT")); sm58Entity.setArfcdest(t_arfcistate.getString("ARFCDEST")); sm58Entity.setArfcluwcnt(t_arfcistate.getString("ARFCLUWCNT")); sm58Entity.setArfcstate(t_arfcistate.getString("ARFCSTATE")); sm58Entity.setArfcfnam(t_arfcistate.getString("ARFCFNAM")); sm58Entity.setArfcreturn(t_arfcistate.getString("ARFCRETURN")); sm58Entity.setArfcuzeit(t_arfcistate.getString("ARFCUZEIT")); sm58Entity.setArfcdatum(t_arfcistate.getString("ARFCDATUM")); sm58Entity.setArfcuser(t_arfcistate.getString("ARFCUSER")); sm58Entity.setArfcretrys(t_arfcistate.getLong("ARFCRETRYS")); sm58Entity.setArfctcode(t_arfcistate.getString("ARFCTCODE")); sm58Entity.setArfcrhost(t_arfcistate.getString("ARFCRHOST")); sm58Entity.setArfcmsg(t_arfcistate.getString("ARFCMSG")); sm58Entity.setArfcreserv(t_arfcistate.getString("ARFCRESERV")); sm58Entity.setHash(t_arfcistate.getString("HASH")); sm58EntityRepository.save(sm58Entity); } String markdown = SappiMonitorServiceImpl.generateMarkdown("monitorSm58", exportList.getString("E_ERR_NUM").replaceAll(" ","")); //呼叫MessageService介面 MarkdownMessage markdownMessage = new MarkdownMessage(); markdownMessage.setUserid(environment.getProperty("sap.pi.monitor.sm58.touser")); markdownMessage.setMarkdown(markdown); JSONObject jsonObject = new JSONObject(); if ("E".equals(exportList.getString("E_STATUS"))) { jsonObject = messageService.sendMarkdown(markdownMessage); jsonObject.put("errCode","-1"); jsonObject.put("errMsg","系統執行出現" + exportList.getString("E_ERR_NUM") +"條錯誤"); } else { jsonObject.put("errCode","0"); jsonObject.put("errMsg","系統執行正常"); } return jsonObject; } }

上面程式碼中,粗體部分是獲取sap連線物件、介面引數賦值、介面呼叫和獲取返回結果的主要程式碼;

4.編寫相應的Controller程式碼

@Api(tags = "SAPPI執行狀態監控", description = "監控SAPPI執行狀態")
@Controller
@RequestMapping("/monitor/sappi")
public class SappiMonitorController {
    @Autowired
    SappiMonitorService sappiMonitorService;

    @ApiOperation(value = "事務程式碼:SXI_MONITOR", notes = "請求方式:POST")
    @PostMapping("/sxi_monitor")
    @ResponseBody
    public JSONObject monitorSxi_monitor(@RequestBody(required = false) SappiSxi_monitor sappiSxi_monitor) throws Exception {
        return sappiMonitorService.monitorSxi_monitor(sappiSxi_monitor);
    }

    @ApiOperation(value = "事務程式碼:SM58", notes = "請求方式:POST")
    @PostMapping("/sm58")
    @ResponseBody
    public JSONObject monitorSm58(@RequestBody(required = false) SappiSm58 sappiSm58) throws Exception {
        return sappiMonitorService.monitorSm58(sappiSm58);
    }
}

5.執行與測試

上面的程式碼中,只貼出了sapjco使用的主要部分,其中資料庫的持久化部分和將sap介面呼叫結果傳送到微信通知的部分都可以刪減掉;

測試時,請求方式改為GET方式即可:

@PostMapping("/sm58")改為 @GetMapping("/sm58")

然後在瀏覽器或者用postman直接呼叫介面:localhost:8080/monitor/sappi/sm58

將會看到如下返回結果:

{
  "invalidUser": "",
  "invalidTagList": [],
  "errCode": "-1",
  "errMsg": "系統執行出現1 條錯誤",
  "invalidPartyList": [],
  "invalidUserList": []
}

6、打包與部署

使用maven的package命令將專案打包成jar包,並上傳到linux伺服器/home/appuser/springboot-sapjco目錄下面;

使用上面的docker命令部署並執行專案;