真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java中rpc請求代碼 java rpa

如何實(shí)現(xiàn)一個簡單的RPC框

0,服務(wù)接口定義---Echo.java

創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站建設(shè)、做網(wǎng)站與策劃設(shè)計,巧家網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:巧家等地區(qū)。巧家做網(wǎng)站價格咨詢:18982081108

/*

* 定義了服務(wù)器提供的服務(wù)類型 */public interface Echo { ? ?public String echo(String string);

}

一,客戶端代碼分析--實(shí)現(xiàn)類:MainClient.java

客戶端實(shí)現(xiàn)包括:獲得一個代理對象,并使用該代理對象調(diào)用服務(wù)器的服務(wù)。獲取代理對象時,需要指定被代理的類(相當(dāng)于服務(wù)器端提供的服務(wù)名),Server IP,Port,這樣客戶端就能找到服務(wù)端的服務(wù)了。

延伸:分布式環(huán)境下,Client如何打到Server的服務(wù)?---因為,在服務(wù)器中運(yùn)行的某些服務(wù)不像標(biāo)準(zhǔn)服務(wù)有著固定的端口,如HTTP的80端口。

一種解決方法是:在運(yùn)行服務(wù)的每臺機(jī)器上都運(yùn)行一個特殊的守護(hù)進(jìn)程,該守護(hù)進(jìn)程負(fù)責(zé)跟蹤位于該機(jī)器中每一項服務(wù)所使用的端口;此外,守護(hù)進(jìn)程還監(jiān)聽一個特定的已經(jīng)端口,Client通過這個端口與守護(hù)進(jìn)程聯(lián)系,請求得到指定服務(wù)的端口。

復(fù)雜的RPC實(shí)現(xiàn)框架中,比如可以把服務(wù)注冊到ZooKeeper中,Client也從ZooKeeper中查詢服務(wù)。參考:一個更復(fù)雜的RPC框架實(shí)現(xiàn)

Echo echo = RPC.getProxy(Echo.class, "127.0.0.1", 20382);

System.out.println(echo.echo("hello,hello"));//使用代理對象調(diào)用服務(wù)器的服務(wù).并將結(jié)果輸出

二,服務(wù)器端分析--實(shí)現(xiàn)類:MainServer.java

服務(wù)器實(shí)現(xiàn)包括:創(chuàng)建一個服務(wù)器對象,將它能提供的服務(wù)注冊,并啟動進(jìn)程監(jiān)聽客戶端的連接

Server server = new RPC.RPCServer(); ? ? ? ?/*

* server 啟動后,需要注冊server端能夠提供的服務(wù),這樣client使用 服務(wù)的名字、

* 服務(wù)器的IP、以及服務(wù)所運(yùn)行的端口 來調(diào)用 server 的服務(wù) ? ? ? ? */

server.register(Echo.class, RemoteEcho.class);//注冊服務(wù)的名字

server.register(AnOtherEchoService.class, AnOtherEchoServiceImpl.class);

server.start();//啟動server

三,服務(wù)器監(jiān)聽Client連接分析----實(shí)現(xiàn)類:Listener.java

當(dāng)server.start()后,它要創(chuàng)建一個Listener對象,這是一個線程類,該線程用來監(jiān)聽Client連接。

public void start() {

System.out.println("啟動服務(wù)器");

/*

* server 啟動時,需要Listener監(jiān)聽是否有client的請求連接

* listener 是一個線程,由它來監(jiān)聽連接 ? ? ? ? ? ? */

listener = new Listener(this); ? ? ? ? ? ?this.isRuning = true;

listener.start();//listener 是一個線程類,start()后會執(zhí)行線程的run方法

}

其實(shí),監(jiān)聽連接就是JAVA ServerSocket類和Socket類提供的相關(guān)功能而已。

/*

* accept()是一個阻塞方法,server_socket 一直等待client 是否有連接到來 */

Socket client = server_socket.accept();//建立一條TCP連接

四,動態(tài)代理對象 生成---RPC.java

客戶端只需要編寫生成代理對象,用代理對象去調(diào)用遠(yuǎn)程服務(wù)的代碼即可。但是,底層的功能如:建立連接,序列化(本例中也沒有考慮),跨語言調(diào)用(未考慮)...是由RPC框架完成的。

當(dāng)MainClient 語句:RPC.getProxy(Echo.class, "127.0.0.1", 20382);執(zhí)行時,會由

/*

* @param Class[]{} 該參數(shù)聲明了動態(tài)生成的代理對象實(shí)現(xiàn)了的接口,即 clazz 所代表的接口類型 .

* 這表明了生成的代理對象它是一個它所實(shí)現(xiàn)了的接口類型的對象

* 從而就可以用它來調(diào)用它所實(shí)現(xiàn)的接口中定義的方法

*

* @param handler 生成代理實(shí)例對象時需要傳遞一個handler參數(shù)

* 這樣當(dāng)該 代理實(shí)例對象調(diào)用接口中定義的方法時,將會委托給InvocationHandler 接口中聲明的invoke方法

* 此時,InvocationHandler 的invoke 方法將會被自動調(diào)用 ? ? ? ? */

T t = (T) Proxy.newProxyInstance(RPC.class.getClassLoader(), new Class[] {clazz}, handler); ? ? ? ?return t;

返回該代理對象,然后就會委托第三個參數(shù) handler 自動執(zhí)行 invoke(),invoke將客戶端調(diào)用的所有相關(guān)信息封裝到Invocation 對象中(后面分析)。然后執(zhí)行第16行代碼發(fā)起連接。

1 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 2 ? ? ? ? ? ? ? ? Invocation invo = new Invocation(); 3 ?? ? ? ? ? ? ? ?invo.setInterfaces(clazz); 4 ? ? ? ? ? ? ? ? ?5 ? ? ? ? ? ? ? ? //利用反射機(jī)制將java.lang.reflect.Method 所代表的方法名,參數(shù) 封裝到 Invocation invo對象中 6 ? ? ? ? ? ? ? ? invo.setMethod(new org.jy.rpc.protocal.Method(method.getName(),method.getParameterTypes())); 7 ?? ? ? ? ? ? ? ?invo.setParams(args); 8 ? ? ? ? ? ? ? ? ?9 ? ? ? ? ? ? ? ? /*10 ?? ? ? ? ? ? ? ? * 當(dāng)把需要調(diào)用的遠(yuǎn)程server端的方法名和參數(shù)封裝到invo之后,Client 對象 就可以把 invo 作為參數(shù) 傳遞給服務(wù)器了.11 ?? ? ? ? ? ? ? ? * 為什么需要這樣做呢?InvocationHandler 的invoke方法是自動執(zhí)行的,在該方法里面,它根據(jù)生成的代理對象 proxy (第一個參數(shù))12 ?? ? ? ? ? ? ? ? * 所實(shí)現(xiàn)的接口(由 Proxy.newProxyInstance()的第二個參數(shù)指定) 就可以知道這個接口中定義了哪些方法13 ?? ? ? ? ? ? ? ? * InvocationHandler 的 invoke 方法的第二個參數(shù)Method method 就可以解析出接口中的方法名和參數(shù)了14 ?? ? ? ? ? ? ? ? * 把它們封裝進(jìn)Invocation invo對象中,再將 invo 作為 client.invoke(invo)的參數(shù) 發(fā)送到服務(wù)器方15 ? ? ? ? ? ? ? ? ?*/16 ? ? ? ? ? ? ? ? client.invoke(invo);//invoke 先調(diào)用init發(fā)起一個Socket連接,再將invo 發(fā)送至輸出流中17 ? ? ? ? ? ? ? ? return invo.getResult();18 ? ? ? ? ? ? }

五,“客戶端存根”--Client.java

最重要的是它的 invoke方法(注意與InvocationHandler的invoke()區(qū)分)。它負(fù)責(zé)建立連接,打開輸入、輸出流,向服務(wù)器發(fā)送字節(jié)數(shù)據(jù)。

1 ? ? public void invoke(Invocation invo) throws UnknownHostException, IOException, ClassNotFoundException {2 ?? ? ? ?init();3 ? ? ? ? System.out.println("寫入數(shù)據(jù)");4 ? ? ? ? oos.writeObject(invo);//將Client 需要調(diào)用的Server的 接口、方法、參數(shù) 封裝起來 發(fā)給服務(wù)器5 ?? ? ? ?oos.flush();6 ? ? ? ? ois = new ObjectInputStream(socket.getInputStream());//用來接收從 server 返回 回來的執(zhí)行結(jié)果 的輸入流7 ? ? ? ? Invocation result = (Invocation) ois.readObject();8 ? ? ? ? invo.setResult(result.getResult());//將結(jié)果 保存到 Invocation result對象中9 ? ? }

六,“服務(wù)器存根“---實(shí)現(xiàn)類:RPCServer.java

上面提到,服務(wù)器通過Listener監(jiān)聽客戶端連接,當(dāng)建立客戶端連接后,Socket client = server_socket.accept(); 不再阻塞,服務(wù)器調(diào)用它的call()方法完成客戶端請求的功能。也即,客戶端請求的結(jié)果實(shí)際上是在服務(wù)器執(zhí)行生成的。返回的結(jié)果是在Client.java 的 invoke() 方法里被讀取出來 。call()再一次用到了JAVA反射(第11行) 參考:JAVA動態(tài)代理

1 public void call(Invocation invo) { 2 ?? ? ? ? ? ?System.out.println(invo.getClass().getName()); 3 ? ? ? ? ? ? Object obj = serviceEngine.get(invo.getInterfaces().getName()); 4 ? ? ? ? ? ? if(obj!=null) { 5 ? ? ? ? ? ? ? ? try { 6 ? ? ? ? ? ? ? ? ? ? Method m = obj.getClass().getMethod(invo.getMethod().getMethodName(), invo.getMethod().getParams()); 7 ? ? ? ? ? ? ? ? ? ? /* 8 ?? ? ? ? ? ? ? ? ? ? * 利用JAVA反射機(jī)制來執(zhí)行java.lang.reflect.Method 所代表的方法 9 ?? ? ? ? ? ? ? ? ? ? * @param result : 執(zhí)行實(shí)際方法后 得到的 服務(wù)的執(zhí)行結(jié)果10 ? ? ? ? ? ? ? ? ? ? ?*/11 ? ? ? ? ? ? ? ? ? ? Object result = m.invoke(obj, invo.getParams());12 ? ? ? ? ? ? ? ? ? ? invo.setResult(result);//將服務(wù)的執(zhí)行結(jié)果封裝到invo對象中。在后面的代碼中,將該對象寫入到輸出流中13 ? ? ? ? ? ? ? ? } catch (Throwable th) {14 ?? ? ? ? ? ? ? ? ? ?th.printStackTrace();15 ?? ? ? ? ? ? ? ?}16 ? ? ? ? ? ? } else {17 ? ? ? ? ? ? ? ? throw new IllegalArgumentException("has no these class");18 ?? ? ? ? ? ?}19 ? ? ? ? }

七,”RPC 編碼、解碼,協(xié)議的定義“---Invocation.java?? Method.java

其實(shí),這里并不是那種實(shí)用的開源RPC框架如Thrift中所指的編碼、IDL……上面兩個類只是RPC實(shí)現(xiàn)過程中輔助完成Java動態(tài)代理的實(shí)現(xiàn),說白了就是封裝客戶端需要調(diào)用的方法,然后指定生成的代理對象需要實(shí)現(xiàn)的接口(服務(wù)).

八,總結(jié):

先運(yùn)行MainServer.java啟動服務(wù)器,然后,再運(yùn)行MainClient.java 啟動一個客戶端連接服務(wù)器就可以看到執(zhí)行結(jié)果。

當(dāng)需要添加新的服務(wù)時:按以下步驟即可:①定義服務(wù)接口及其實(shí)現(xiàn)類,如:AnOtherEchoService.java? ②:在MainServer.java中注冊新添加的服務(wù)。

③:在MainClient.java中編寫獲得新服務(wù)的代理對象的代碼,并用該代理對象調(diào)用新服務(wù)接口中聲明的方法。

這樣,在客戶端就能夠遠(yuǎn)程地調(diào)用服務(wù)器上的一個新服務(wù)了。

jsonrpc java怎么運(yùn)行

JSON-RPC-Java 由兩個對用戶可視化的組件構(gòu)成,它們是JSONRPCBridge和JSONRPCServlet,二者的協(xié)調(diào)實(shí)現(xiàn)了JSON服務(wù)器端對請求對象的處理,并響應(yīng)給用戶。

JSONRPCBridge是一個擁有服務(wù)器端導(dǎo)出給特定客戶端的對象的引用的session對象,它接收服務(wù)器(也就是JSONRPCServlet)傳來的JSON-RPC請求,然后其把JSON對象解碼(unmarshalling)為Java對象,再扮演方法調(diào)用的角色,還要把方法調(diào)用返回的Java對象結(jié)果組碼(marshall)為JSON對象傳給客戶端處理。而具體的從Java對象到Javascript對象的類型轉(zhuǎn)換由負(fù)責(zé)串行化的串行化類Serializer處理。

JSONRPCBridge必須放置在HttpSession對象中,并且注冊屬性名為“JSONRPCBridge”,以使JSONRPCServlet能夠定位負(fù)責(zé)調(diào)用導(dǎo)出到客戶端的Java對象的橋。為此,為了導(dǎo)出一個對象的所有實(shí)例和靜態(tài)方法到客戶端,應(yīng)該有如下的代碼: JSONRPCBridge.registerObject("myObject", myObject);

為了導(dǎo)出一個類的所有的靜態(tài)方法,應(yīng)該:JSONRPCBridge.registerClass(("myObject", myObject);

如果registerObject和registerClass被多次調(diào)用為有相同鍵值的對象使用,那么其將被最新賦值的對象所更新。

在JSON中,還可以使用單例模式的globalBridge來為所有的HTTP客戶端導(dǎo)出所有的實(shí)例方法。其可以用來注冊工廠類,但使用時要注意認(rèn)證與安全問題。使用時如下標(biāo)識:JSONRPCBridge.getGlobalBridge().registerObject("myObject",myObject); 同上其還可以導(dǎo)出所有的靜態(tài)方法。

該協(xié)議中最重要的一部分還有就是Servlet了,現(xiàn)在就來簡單的介紹一下:

在該協(xié)議中,JSONRPCServlet充當(dāng)傳送器,處理通過HTTP傳輸過來的JSON

java protobuf 定義rpc服務(wù)怎么調(diào)用

1.,選擇其中的win版本下載,我選擇的是protoc-2.4.1-win32.zip

2.下載一個protobuf-java-2.4.1.jar文件(注意,要與你剛才下的proto.exe版本相同)

然后就開始開發(fā)了。

步驟:

1.用記事本編寫一個.proto文件:

}如:編寫的是test.proto

package protobuf;

option java_package = "com.sq.protobuf";

option java_outer_classname = "FirstProtobuf";

message testBuf {

required int32 ID = 1;

required string Url = 2;

}

將其放在與剛解壓的protoc.exe同級目錄中。

2.在cmd中,到protoc-2.4.1-win32文件夾下,

執(zhí)行

E:\protoc-2.4.1-win32 protoc.exe --java_out=./ test.proto

則可以找到的一個生成的FirstProtobuf.java文件。

3.在MyEclipse中新建一個java project,建立包c(diǎn)om.sq.protobuf,然后將剛才生成的FirstProtobuf.java文件放在其下面。

此時會報錯,因為沒有引入jar包,在package視圖下,將protobuf-java-2.4.1.jar引入,即可解決問題。


當(dāng)前題目:java中rpc請求代碼 java rpa
分享路徑:http://weahome.cn/article/ddgedgs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部