java對(duì)接??禂z像頭的完整步驟記錄
現(xiàn)在制造業(yè)很多都是用的??档臄z像頭,作為程序員有時(shí)候需要對(duì)接??禂z像頭,實(shí)現(xiàn)門(mén)禁訪問(wèn)控制,監(jiān)控預(yù)覽,錄像文件下載等功能。
一、開(kāi)發(fā)環(huán)境準(zhǔn)備
在??倒倬W(wǎng)下載SDK開(kāi)發(fā)文檔及庫(kù)文件:
https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10
根據(jù)軟件部署的平臺(tái)選擇對(duì)應(yīng)的版本,這里以win64版本為例。
將下載好的庫(kù)文件復(fù)制粘貼加入到j(luò)ava項(xiàng)目中,并改名為lib文件夾。
注意:demo里的examples.jar和jna.jar也需要放在lib文件下,以方便調(diào)試。
然后在project structure中加入lib庫(kù)文件中。
將下載下來(lái)的demo中的文件復(fù)制粘貼到項(xiàng)目文件中,填入對(duì)應(yīng)的攝像頭的賬號(hào)密碼。執(zhí)行程序,若顯示登錄成功,則表示調(diào)試成功。
二、實(shí)現(xiàn)java調(diào)用設(shè)備接口
打開(kāi)下載的《設(shè)備網(wǎng)絡(luò)SDK使用手冊(cè).chm》作為參考,在該手冊(cè)中java如何對(duì)接??禂z像頭有詳細(xì)說(shuō)明。
由于設(shè)備網(wǎng)絡(luò)SDK是封裝的動(dòng)態(tài)鏈接庫(kù)(Windows的dll或者Linux的so),各種開(kāi)發(fā)語(yǔ)言對(duì)接SDK,都是通過(guò)加載動(dòng)態(tài)庫(kù)鏈接,調(diào)用動(dòng)態(tài)庫(kù)中的接口實(shí)現(xiàn)功能模塊對(duì)接,因此,設(shè)備網(wǎng)絡(luò)SDK的對(duì)接不區(qū)分開(kāi)發(fā)語(yǔ)言,而且對(duì)接的流程和對(duì)應(yīng)的接口都是通用的,各種語(yǔ)言調(diào)用動(dòng)態(tài)庫(kù)的方式有所不同。
java語(yǔ)言是通過(guò)JNA的方式調(diào)用動(dòng)態(tài)鏈接庫(kù)中的接口,實(shí)現(xiàn)在java語(yǔ)言中調(diào)用C/C++語(yǔ)言封裝的接口。
因此,java的類(lèi)文件不需要編寫(xiě)任何業(yè)務(wù)代碼實(shí)現(xiàn)某接口來(lái)調(diào)用設(shè)備,而是聲明一個(gè)接口就能調(diào)用設(shè)備的功能了。
這只需要在一個(gè)java接口中描述目標(biāo)native library的函數(shù)與結(jié)構(gòu),JNA將自動(dòng)實(shí)現(xiàn)Java接口到native function的映射,而不需要編寫(xiě)任何Native/JNI代碼,大大降低了Java調(diào)用動(dòng)態(tài)鏈接庫(kù)的開(kāi)發(fā)難度。
JNA調(diào)用C/C++的過(guò)程大致如下:
(一)加載動(dòng)態(tài)鏈接庫(kù)
通過(guò)java調(diào)用海康官方提供的設(shè)備功能,首先需要自定義一個(gè)接口加載dll文件,比如demo中是聲明HCNetSDK
的接口,該接口繼承Library 或 StdCallLibrary。
默認(rèn)的是繼承Library ,如果動(dòng)態(tài)鏈接庫(kù)里的函數(shù)是以stdcall方式輸出的,那么就繼承StdCallLibrary。接口內(nèi)部需要一個(gè)公共靜態(tài)常量:INSTANCE,通過(guò)這個(gè)常量,就可以獲得這個(gè)接口的實(shí)例,從而使用接口的方法,也就是調(diào)用外部dll/so的函數(shù)。
INSTANCE常量通過(guò) Native.loadLibrary() API函數(shù)獲得,(新版本的jna中,常量是通過(guò)Native.load()函數(shù)獲取的)該函數(shù)有2個(gè)參數(shù):
// SDK接口說(shuō)明,HCNetSDK.dll public interface HCNetSDK extends StdCallLibrary { HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary("E:\\DEMO_TEST\\JAVA_Demo\\JNA_TEST\\lib\\HCNetSDK.dll", HCNetSDK.class); // 動(dòng)態(tài)庫(kù)中結(jié)構(gòu)體、接口描述 }
這里是采用的是絕對(duì)路徑,為防止項(xiàng)目工程路徑的變化,可以改為獲取動(dòng)態(tài)路徑。
public class XXDemo { static HCNetSDK hCNetSDK = null; //動(dòng)態(tài)庫(kù)加載,根據(jù)軟件所屬操作系統(tǒng)的工程文件目錄動(dòng)態(tài)獲取庫(kù)文件路徑 private static boolean createSDKInstance() { if (hCNetSDK == null) { synchronized (HCNetSDK.class) { String strDllPath = ""; try { if (osSelect.isWindows()) //win系統(tǒng)加載庫(kù)路徑 strDllPath = System.getProperty("user.dir") + "\\lib\\HCNetSDK.dll"; else if (osSelect.isLinux()) //Linux系統(tǒng)加載庫(kù)路徑 strDllPath = System.getProperty("user.dir") + "/lib/libhcnetsdk.so"; hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class); } catch (Exception ex) { System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage()); return false; } } } return true; } public static void main(String[] args) throws InterruptedException { //調(diào)用函數(shù)之前先加載動(dòng)態(tài)鏈接庫(kù) if (hCNetSDK == null) { if (!createSDKInstance()) { System.out.println("Load SDK fail"); return; } } } }
類(lèi)似的,別的dll庫(kù)文件的接口也是如此進(jìn)行聲明。
// 播放庫(kù)函數(shù)聲明,PlayCtrl.dll public interface PlayCtrl extends StdCallLibrary{ PlayCtrl INSTANCE = (PlayCtrl) Native.loadLibrary("E:\\DEMO_TEST\\JAVA_Demo\\JNA_TEST\\lib\\PlayCtrl.dll", PlayCtrl.class); // 播放庫(kù)中結(jié)構(gòu)體,接口描述 }
(二)結(jié)構(gòu)體、接口重定義
dll和so是C/C++語(yǔ)言函數(shù)的集合和容器,與Java中的接口概念吻合,所以JNA把dll文件和so文件看成一個(gè)個(gè)接口。
在JNA中定義一個(gè)接口就是相當(dāng)于了定義一個(gè)DLL/SO文件的描述文件,該接口代表了動(dòng)態(tài)鏈接庫(kù)中發(fā)布的所有函數(shù),對(duì)于程序不需要的函數(shù),可以不在接口中聲明。
例如,官方demo中的HCNetSDK的java接口聲明了HCNetSDK.dll/so文件很多的接口。在實(shí)際開(kāi)發(fā)中可以不需要聲明這么多接口,只取某些需要的接口重新進(jìn)行分組。
若在《設(shè)備網(wǎng)絡(luò)SDK使用手冊(cè)》查找功能時(shí)發(fā)現(xiàn)某些接口在demo中沒(méi)有,則可以在HCNetSDK.h
頭文件搜索對(duì)應(yīng)的接口,然后在java中聲明該接口的定義。
1.類(lèi)型映射
接口中使用的函數(shù)必須與鏈接庫(kù)中的函數(shù)原型保持一致,因?yàn)镃/C++的類(lèi)型與Java的類(lèi)型是不一樣的,動(dòng)態(tài)庫(kù)中的C/C++的數(shù)據(jù)類(lèi)型必須轉(zhuǎn)換成java對(duì)應(yīng)類(lèi)型,這就是類(lèi)型映射(Type Mappings)。
默認(rèn)的類(lèi)型映射可以參考JNA官網(wǎng)的類(lèi)型映射表。(國(guó)內(nèi)鏡像鏈接 https://gitee.com/mirrors/jna/)
2.結(jié)構(gòu)體和類(lèi)的轉(zhuǎn)換
Java中沒(méi)有結(jié)構(gòu)體(struct)這種數(shù)據(jù)類(lèi)型,JNA為我們提供了Structure這個(gè)類(lèi),只要繼承該類(lèi),就可實(shí)現(xiàn)java結(jié)構(gòu)體,相當(dāng)于轉(zhuǎn)換成java中的類(lèi)。
例如,NET_DVR_USER_LOGIN_INFO結(jié)構(gòu)體需要在HCNetSDK接口中進(jìn)行重定義,轉(zhuǎn)換方式如下:
//C++中NET_DVR_USER_LOGIN_INFO結(jié)構(gòu)體定義 typedef struct{ char sDeviceAddress[NET_DVR_DEV_ADDRESS_MAX_LEN]; BYTE byUseTransport; // 是否啟用能力集透?jìng)鳎?--不啟用透?jìng)?,默認(rèn),1--啟用透?jìng)? WORD wPort; char sUserName[NET_DVR_LOGIN_USERNAME_MAX_LEN]; char sPassword[NET_DVR_LOGIN_PASSWD_MAX_LEN]; fLoginResultCallBack cbLoginResult; void *pUser; BOOL bUseAsynLogin; BYTE byProxyType; // 0:不使用代理,1:使用標(biāo)準(zhǔn)代理,2:使用EHome代理 BYTE byUseUTCTime; // 0-不進(jìn)行轉(zhuǎn)換,默認(rèn),1-接口上輸入輸出全部使用UTC時(shí)間,SDK完成UTC時(shí)間與設(shè)備時(shí)區(qū)的轉(zhuǎn)換,2-接口上輸入輸出全部使用平臺(tái)本地時(shí)間,SDK完成平臺(tái)本地時(shí)間與設(shè)備時(shí)區(qū)的轉(zhuǎn)換 BYTE byLoginMode; // 0-Private 1-ISAPI 2-自適應(yīng) BYTE byHttps; // 0-不適用tls,1-使用tls 2-自適應(yīng) LONG iProxyID; // 代理服務(wù)器序號(hào),添加代理服務(wù)器信息時(shí),相對(duì)應(yīng)的服務(wù)器數(shù)組下表值 BYTE byVerifyMode; // 認(rèn)證方式,0-不認(rèn)證,1-雙向認(rèn)證,2-單向認(rèn)證;認(rèn)證僅在使用TLS的時(shí)候生效; BYTE byRes3[119]; }NET_DVR_USER_LOGIN_INFO,*LPNET_DVR_USER_LOGIN_INFO; // 宏定義 #define NET_DVR_DEV_ADDRESS_MAX_LEN 129 #define NET_DVR_LOGIN_USERNAME_MAX_LEN 64 #define NET_DVR_LOGIN_PASSWD_MAX_LEN 64
注意轉(zhuǎn)換之后,java類(lèi)中的屬性都為public,這意味著可以直接進(jìn)行屬性的修改和讀取,而不需要進(jìn)行g(shù)et和set方法的聲明和操作。
// SDK接口說(shuō)明,HCNetSDK.dll public interface HCNetSDK extends StdCallLibrary { HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary("E:\\DEMO_TEST\\JAVA_Demo\\JNA_TEST\\lib\\HCNetSDK.dll", HCNetSDK.class); // 動(dòng)態(tài)庫(kù)中結(jié)構(gòu)體、接口描述 public static class NET_DVR_USER_LOGIN_INFO extends Structure{ public byte[] sDeviceAddress = new byte[NET_DVR_DEV_ADDRESS_MAX_LEN]; public byte byUseTransport; public short wPort; public byte[] sUserName = new byte[NET_DVR_LOGIN_USERNAME_MAX_LEN]; public byte[] sPassword = new byte[NET_DVR_LOGIN_PASSWD_MAX_LEN]; public FLoginResultCallback cbLoginResult; public Pointer pUser; public boolean bUseAsynLogin; public byte byProxyType; // 0:不使用代理,1:使用標(biāo)準(zhǔn)代理,2:使用EHome代理 public byte byUseUTCTime; // 0-不進(jìn)行轉(zhuǎn)換,默認(rèn),1-接口上輸入輸出全部使用UTC時(shí)間,SDK完成UTC時(shí)間與設(shè)備時(shí)區(qū)的轉(zhuǎn)換,2-接口上輸入輸出全部使用平臺(tái)本地時(shí)間,SDK完成平臺(tái)本地時(shí)間與設(shè)備時(shí)區(qū)的轉(zhuǎn)換 public byte byLoginMode; // 0-Private 1-ISAPI 2-自適應(yīng) public byte byHttps; // 0-不適用tls,1-使用tls 2-自適應(yīng) public int iProxyID; // 代理服務(wù)器序號(hào),添加代理服務(wù)器信息時(shí),相對(duì)應(yīng)的服務(wù)器數(shù)組下表值 public byte byVerifyMode; // 認(rèn)證方式,0-不認(rèn)證,1-雙向認(rèn)證,2-單向認(rèn)證;認(rèn)證僅在使用TLS的時(shí)候生效; public byte[] byRes2 = new byte[119]; // 結(jié)構(gòu)體中重寫(xiě)getFieldOrder方法,F(xiàn)ieldOrder順序要和結(jié)構(gòu)體中定義的順序保持一致 @Override protected List getFieldOrder(){ return Arrays.asList("sDeviceAddress","byUseTransport","wPort","sUserName","sPassword", "cbLoginResult","pUser","bUseAsynLogin","byProxyType","byUseUTCTime", "byLoginMode","byHttps","iProxyID","byVerifyMode","byRes2"); } } // 常量(宏)定義 public static final int NET_DVR_DEV_ADDRESS_MAX_LEN = 129; public static final int NET_DVR_LOGIN_USERNAME_MAX_LEN = 64; public static final int NET_DVR_LOGIN_PASSWD_MAX_LEN = 64; }
3.接口轉(zhuǎn)換
在HCNetSDK接口中聲明的方法要和開(kāi)發(fā)包中HCNetSDK.h的頭文件中聲明的函數(shù)對(duì)應(yīng)上,其中方法名、參數(shù)列表、返回值都要和HCNetSDK.h中的函數(shù)對(duì)應(yīng),HCNetSDK.h頭文件的函數(shù)轉(zhuǎn)換到j(luò)ava中聲明,轉(zhuǎn)換方式如下所示:
/******************************** SDK接口函數(shù)聲明 *********************************/ // 初始化SDK,調(diào)用其他SDK函數(shù)的前提 NET_DVR_API BOOL __stdcall NET_DVR_Init(); // 啟用日志文件寫(xiě)入接口 NET_DVR_API BOOL __stdcall NET_DVR_SetLogToFile(DWORD nLogLevel ,char* strLogDir, BOOL bAutoDel); // 返回最后操作的錯(cuò)誤碼 NET_DVR_API DWORD __stdcall NET_DVR_GetLastError(); // 釋放SDK資源,在程序結(jié)束之前調(diào)用 NET_DVR_API BOOL __stdcall NET_DVR_Cleanup(); // 登錄接口 NET_DVR_API LONG __stdcall NET_DVR_Login_V40( LPNET_DVR_USER_LOGIN_INFO pLoginInfo, LPNET_DVR_DEVICEINFO_V40 lpDeviceInfo ); // 用戶(hù)注銷(xiāo) NET_DVR_API BOOL __stdcall NET_DVR_Logout(LONG lUserID); // 回調(diào)函數(shù)聲明,登錄狀態(tài)回調(diào)函數(shù) typedef void (CALLBACK *fLoginResultCallBack) ( LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo , void* pUser );
轉(zhuǎn)換到j(luò)ava中時(shí),注意類(lèi)型轉(zhuǎn)換
// SDK接口說(shuō)明,HCNetSDK.dll public interface HCNetSDK extends StdCallLibrary { HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary("E:\\DEMO_TEST\\JAVA_Demo\\JNA_TEST\\lib\\HCNetSDK.dll", HCNetSDK.class); /*** API函數(shù)聲明 ***/ // 初始化SDK,調(diào)用其他SDK函數(shù)的前提 boolean NET_DVR_Init(); // 啟用日志文件寫(xiě)入接口 boolean NET_DVR_SetLogToFile(int bLogEnable , String strLogDir, boolean bAutoDel); // 返回最后操作的錯(cuò)誤碼 int NET_DVR_GetLastError(); // 釋放SDK資源,在程序結(jié)束之前調(diào)用 boolean NET_DVR_Cleanup(); // 登錄接口 int NET_DVR_Login_V40(NET_DVR_USER_LOGIN_INFO pLoginInfo, NET_DVR_DEVICEINFO_V40 lpDeviceInfo); // 用戶(hù)注銷(xiāo) boolean NET_DVR_Logout(int lUserID); // 回調(diào)函數(shù)申明 public static interface FLoginResultCallback extends StdCallCallback{ // 登錄狀態(tài)回調(diào)函數(shù) public int invoke(int lUserID,int dwResult,NET_DVR_DEVICEINFO_V30 lpDeviceinfo,Pointer pUser); } }
4.方法調(diào)用
經(jīng)過(guò)上述的操作,JNA工程已經(jīng)創(chuàng)建完成,結(jié)構(gòu)體和函數(shù)也在HCNetSDK
接口類(lèi)中進(jìn)行了轉(zhuǎn)換,后續(xù)就可以在主類(lèi)中實(shí)現(xiàn)調(diào)用。
以下為官方demo中的示例,以實(shí)現(xiàn)用戶(hù)注冊(cè)功能模塊為例,解釋了接口調(diào)用的流程。
public class jna_test { // 接口的實(shí)例,通過(guò)接口實(shí)例調(diào)用外部dll/so的函數(shù) static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE; // 用戶(hù)登錄返回句柄 static int lUserID; int iErr = 0; public static void main(String[] args) throws InterruptedException { jna_test test01 = new jna_test(); // 初始化 boolean initSuc = hCNetSDK.NET_DVR_Init(); if (initSuc != true) { System.out.println("初始化失敗"); } // 打印SDK日志 hCNetSDK.NET_DVR_SetLogToFile(3, ".\\SDKLog\\", false); // 用戶(hù)登陸操作 test01.Login_V40("192.168.1.64",(short)8000,"admin","test12345"); /* *實(shí)現(xiàn)SDK中其余功能模快 */ Thread.sleep(5000); //用戶(hù)注銷(xiāo),釋放SDK test01.Logout(); } /** * * @param m_sDeviceIP 設(shè)備ip地址 * @param wPort 端口號(hào),設(shè)備網(wǎng)絡(luò)SDK登錄默認(rèn)端口8000 * @param m_sUsername 用戶(hù)名 * @param m_sPassword 密碼 */ public void Login_V40(String m_sDeviceIP,short wPort,String m_sUsername,String m_sPassword) { /* 注冊(cè) */ // 設(shè)備登錄信息 HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO(); // 設(shè)備信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN]; System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length()); m_strLoginInfo.wPort =wPort ; m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN]; System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length()); m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]; System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length()); // 是否異步登錄:false- 否,true- 是 m_strLoginInfo.bUseAsynLogin = false; // write()調(diào)用后數(shù)據(jù)才寫(xiě)入到內(nèi)存中 m_strLoginInfo.write(); lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo); if (lUserID == -1) { System.out.println("登錄失敗,錯(cuò)誤碼為" + hCNetSDK.NET_DVR_GetLastError()); return; } else { System.out.println("登錄成功!"); // read()后,結(jié)構(gòu)體中才有對(duì)應(yīng)的數(shù)據(jù) m_strDeviceInfo.read(); return; } } //設(shè)備注銷(xiāo) SDK釋放 public void Logout() { if (lUserID>=0) { if (hCNetSDK.NET_DVR_Logout(lUserID) == false) { System.out.println("注銷(xiāo)失敗,錯(cuò)誤碼為" + hCNetSDK.NET_DVR_GetLastError()); } System.out.println("注銷(xiāo)成功"); hCNetSDK.NET_DVR_Cleanup(); return; } else{ System.out.println("設(shè)備未登錄"); hCNetSDK.NET_DVR_Cleanup(); return; } } }
我自己也寫(xiě)了個(gè)DEMO,放在gitee倉(cāng)庫(kù)了??梢蕴峁﹨⒖迹篽ttps://gitee.com/ZachLong/java-hik-camera
總結(jié)
到此這篇關(guān)于java對(duì)接??禂z像頭的文章就介紹到這了,更多相關(guān)java對(duì)接??禂z像頭內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決maven build 無(wú)反應(yīng),直接terminated的問(wèn)題
下面小編就為大家?guī)?lái)一篇解決maven build 無(wú)反應(yīng),直接terminated的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06Java使用釘釘創(chuàng)建企業(yè)內(nèi)部機(jī)器人的實(shí)現(xiàn)
釘釘?shù)某霈F(xiàn)為企業(yè)節(jié)約了大量人力成本,其中也開(kāi)放了大量的外部api接口方便企業(yè)使用。本文主要介紹了Java使用釘釘創(chuàng)建企業(yè)內(nèi)部機(jī)器人的實(shí)現(xiàn),感興趣的可以了解一下2021-11-11Java異常處理UncaughtExceptionHandler使用實(shí)例代碼詳解
當(dāng)一個(gè)線程由于未捕獲異常即將終止時(shí),Java虛擬機(jī)將使用thread . getuncaughtexceptionhandler()查詢(xún)線程的uncaughtException處理程序,并調(diào)用處理程序的uncaughtException方法,將線程和異常作為參數(shù)傳遞2023-03-03使用注解@Recover優(yōu)化丑陋的循環(huán)詳解
我們知道在實(shí)現(xiàn)一個(gè)功能的時(shí)候是可以使用不同的代碼來(lái)實(shí)現(xiàn)的,那么相應(yīng)的不同實(shí)現(xiàn)方法的性能肯定也是有差別的,下面這篇文章主要給大家介紹了關(guān)于使用注解@Recover優(yōu)化丑陋的循環(huán)的相關(guān)資料,需要的朋友可以參考下2022-04-04Java自定義一個(gè)變長(zhǎng)數(shù)組的思路與代碼
有時(shí)我們希望將把數(shù)據(jù)保存在單個(gè)連續(xù)的數(shù)組中,以便快速、便捷地訪問(wèn)數(shù)據(jù),但這需要調(diào)整數(shù)組大小或者對(duì)其擴(kuò)展,下面這篇文章主要給大家介紹了關(guān)于Java自定義一個(gè)變長(zhǎng)數(shù)組的思路與代碼,需要的朋友可以參考下2022-12-12Struts2實(shí)現(xiàn)CRUD(增 刪 改 查)功能實(shí)例代碼
CRUD是Create(創(chuàng)建)、Read(讀取)、Update(更新)和Delete(刪除)的縮寫(xiě),它是普通應(yīng)用程序的縮影。接下來(lái)通過(guò)本文給大家介紹Struts2實(shí)現(xiàn)CRUD(增 刪 改 查)功能實(shí)例代碼,感興趣的朋友一起看看吧2016-06-06SpringCloud Finchley Gateway 緩存請(qǐng)求Body和Form表單的實(shí)現(xiàn)
在接入Spring-Cloud-Gateway時(shí),可能有需求進(jìn)行緩存Json-Body數(shù)據(jù)或者Form-Urlencoded數(shù)據(jù)的情況。這篇文章主要介紹了SpringCloud Finchley Gateway 緩存請(qǐng)求Body和Form表單的實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2019-01-01