通過接口實現JAVA和.NET互調用-JNInterface
使用C#編程多年,也十分感激微軟在語言架構、語法糖、編輯器等方面給自己帶來的便利。但因為最近工作中有接觸到JAVA,漸漸地發現的確像大家說的那樣,JAVA的生態很好,要找點什么幾乎都有現成的,於是自然就想到了能不能用.NET來調用JAVA。
具了解,有個JNBridge的軟件,可以"Bridge any Java with any .NET, anywhere",也許很好用,但是付費的,不喜歡。
又了解了一下其他的方法,都不怎么通用,支持不健全。
當然,通過WebService肯定是可以的,但是一直不喜歡webservice的臃腫。
於是就自己寫了一個輕量級的小組件,java和.net各一個本版,都包含一個客戶端和服務端,兩個本版的客戶端都可以與兩個本版的服務端通信。
一句話概括來說就是:服務端監聽客戶端的請求,收到請求后會找到事先注冊好的處理程序,處理后再返回客戶端。(如果這個過程不了解,那么說明尊駕對HTTP也不了解,這段時間總有web開發者對我說http是有狀態的,這一部分人應該也不理解...)
流程是很簡單的,第一步就是定義消息體了,可以理解為HTTP協議定義的消息體,HTTP里有請求和應答,這里自然也有兩個相似的東西,和實際生活中好多例子一樣,比如有人問你"你吃飯了嗎?",出於禮貌,不管你吃了沒吃,當時心情如何,都應該回復人家。
這里我定義JNInvokeMessage和JNReturnMessage兩個消息類(為了看起來清晰,貼出C#簡化代碼,java的基本是一樣的)
JNInvokeMessage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public
class
JNInvokeMessage
{
public
string
targetName {
get
;
set
; }
public
Dictionary<
string
,
object
> parameters;
public
JNInvokeMessage(
string
targetName)
{
this
.targetName = targetName;
}
public
JNInvokeMessage setParam(
string
key,
object
value)
{
lock
(
this
)
{
if
(parameters ==
null
) parameters =
new
Dictionary<
string
,
object
>();
}
parameters[key] = value;
return
this
;
}
public
object
getParam(
string
key)
{
if
(parameters ==
null
)
return
null
;
object
obj;
if
(parameters.TryGetValue(key,
out
obj))
{
return
obj;
}
return
null
;
}
}
|
JNReturnMessage.cs
1
2
3
4
5
6
7
8
|
public
class
JNReturnMessage
{
public
bool
ok {
get
;
set
; }
public
string
error {
get
;
set
; }
public
object
value {
get
;
set
; }
}
|
下一步就是定義一個接口契約了,在C#里,可以定義一個委托:
1
|
public
delegate
JNReturnMessage IJNInterface(JNInvokeMessage invokeMessage);
|
java里,沒有委托,所以我們定義一個接口:
1
2
3
|
public
interface
IJNInterface {
JNReturnMessage invoke(JNInvokeMessage invokeMessage);
}
|
都是大同小異的東西,.NET委托其實是類。
接下來就是實現Client和Server了,基本都是一些通信邏輯,老套路了網上都有,就不帖代碼了,主要就是Server里有個interfaces,來保存接口處理程序,處理程序相等於MVC的Controller里的Action。在.net里用Dictionary,java里用map:
1
|
private
Dictionary<
string
, IJNInterface> interfaces =
new
Dictionary<
string
, IJNInterface>();
|
1
|
private
Map<String, IJNInterface> interfaces =
new
HashMap<String, IJNInterface>();
|
字典的key就相當於url,唯一確定要調用的處理程序。
兩邊開啟服務和客戶端調用寫法基本都是一樣的,下面展示java開啟服務,在.net客戶端調用:
java service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static
void
startServer()
throws
IOException {
JNServer server =
new
JNServer();
server.addInterface(
"test"
, invokeMessage -> {
System.out.println(invokeMessage.toJson());
JNReturnMessage returnMessage =
new
JNReturnMessage(
true
,
"hello .net"
);
return
returnMessage;
});
server.addInterface(
"home/index"
,
new
IJNInterface() {
@Override
public
JNReturnMessage invoke(JNInvokeMessage invokeMessage) {
System.out.println(invokeMessage.toJson());
JNReturnMessage returnMessage =
new
JNReturnMessage(
true
,
new
int
[]{
1
,
2
,
3
,
4
,
5
});
return
returnMessage;
}
});
server.start();
}
|
.net Client:
1
2
3
4
5
6
7
8
9
10
11
12
|
static
void
Main(
string
[] args)
{
//new Thread(new ThreadStart(startServer)).Start();
//Thread.Sleep(1000);
JNClient client =
new
JNClient();
JNInvokeMessage msg =
new
JNInvokeMessage(
"test"
);
var
ret = client.Invoke(msg);
Console.WriteLine(ret.toJson());
}
|
.net控制台顯示,說明我們調用成功:
如果調用失敗,ok為false,error是錯誤的描述。
把java程序或.net程序注冊為服務,在windows上建議使用srvany.exe,簡單好用,這里是SrvanyUI_1.0下載,下面是我測試用的java服務設置:
程序路徑就是 java.exe,啟動參數就是 -jar "服務jar包的路徑"
注意:
消息格式是JSON,java里用了fastjson,.net里用了Newtonsoft.Json,所以如果在返回值或參數里用了復雜的對象或集合數組類的,反序列化處理應該是fastjson里的JSONObject和JSONArray,Newtonsoft.Json里的JObject和JArray。
下載:
源碼:
http://git.oschina.net/loogn/Loogn.JNInterface.JAVA
http://git.oschina.net/loogn/Loogn.JNInterface.NET