RPC:遠(yuǎn)程過(guò)程調(diào)用
主要內(nèi)容
1.項(xiàng)目結(jié)構(gòu)變化
2.RPC簡(jiǎn)介
3.RMI實(shí)現(xiàn)RPC
4.HttpClient實(shí)現(xiàn)RPC
5.Zookeeper安裝
6.Zookeeper客戶端常用命令
7.向Zookeeper中注冊(cè)內(nèi)容
8.從Zookeeper中發(fā)現(xiàn)內(nèi)容
9.手寫(xiě)RPC框架
一.今天學(xué)什么?為什么講?
Dubbo是RPC的一個(gè)框架.
二.項(xiàng)目架構(gòu)變化
1.單體架構(gòu)
1.1架構(gòu)圖
單體架構(gòu)就是一個(gè)項(xiàng)目里面包含這個(gè)項(xiàng)目中全部代碼.一個(gè)應(yīng)用搞定全部功能.
DNS服務(wù)器可以是單映射,也可以配置多個(gè)映射.
1.2軟阿基代碼結(jié)構(gòu)
在單體架構(gòu)項(xiàng)目中,團(tuán)隊(duì)都是通過(guò)包(package)進(jìn)行區(qū)分每個(gè)模塊
總體包結(jié)構(gòu):com.bjsxt.*.分層包
項(xiàng)目名:
? ? --com
? ? ? ? --bjsxt
? ? ? ? ? ? --common
? ? ? ? ? ? --utils
? ? ? ? --user
? ? ? ? ? ? --controller
? ? ? ? ? ? --service
? ? ? ? ? ? --mapper
? ? ????--sys
? ? ? ? ? ? --controller
? ? ? ? ? ? --service
? ? ? ? ? ? --mapper
1.3優(yōu)缺點(diǎn)
1.3.1優(yōu)點(diǎn)
部署簡(jiǎn)單,維護(hù)方便,開(kāi)發(fā)成本低
1.3.2缺點(diǎn)
當(dāng)項(xiàng)目規(guī)模大,用戶訪問(wèn)頻率高,并發(fā)量大,數(shù)據(jù)量大時(shí),會(huì)大大降低程序執(zhí)行效率,甚至出現(xiàn)服務(wù)器宕機(jī)等情況
1.4適用項(xiàng)目
傳統(tǒng)管理項(xiàng)目,小型互聯(lián)網(wǎng)項(xiàng)目
2.分布式架構(gòu)
2.1架構(gòu)圖(簡(jiǎn)易版)
分布式架構(gòu)會(huì)把一個(gè)項(xiàng)目按照特定要求(多按照模塊或功能)拆分成多個(gè)項(xiàng)目,每個(gè)項(xiàng)目分別部署到不同的服務(wù)器上.
2.2軟件代碼結(jié)構(gòu)
項(xiàng)目1:
? ? --com.bjsxt.xxx
? ? ? ? --controller
? ? ? ? --service
? ? ? ? --mapper
項(xiàng)目2:
? ? --com.bjsxt.mmm
? ? ? ? --controller
? ? ? ? --service
? ? ? ? --mapper
2.3優(yōu)缺點(diǎn)
2.3.1優(yōu)點(diǎn)
增大了系統(tǒng)可用性.減少單點(diǎn)故障,導(dǎo)致整個(gè)應(yīng)用不可用
增加重用性.因?yàn)槟K化,所以重用性更高.高內(nèi)聚,低耦合
增加可擴(kuò)展性.有新的模塊增加新的項(xiàng)目即可
增加每個(gè)模塊的負(fù)載能力.因?yàn)槊總€(gè)模塊都是一個(gè)項(xiàng)目,所以每個(gè)模塊的負(fù)載能力更強(qiáng)
2.3.2缺點(diǎn)
成本更高.因?yàn)榧夹g(shù)多,難,所以開(kāi)大成本,時(shí)間成本,維護(hù)成本都在變高
架構(gòu)更加復(fù)雜
整體響應(yīng)之間變長(zhǎng),一些業(yè)務(wù)需要多項(xiàng)目通信后給出結(jié)果
通吐量更大.吞吐量=請(qǐng)求數(shù)/秒
2.4適用項(xiàng)目
中,大型互聯(lián)網(wǎng)項(xiàng)目.客戶多,數(shù)據(jù)多,訪問(wèn)并發(fā)高,壓力大,吞吐量高
2.5待解決問(wèn)題
分布式架構(gòu)中各個(gè)模塊如何進(jìn)行通信?
可以使用Http協(xié)議,也可以石紅RPC協(xié)議通信,也可以使用其他的通信方式.我們本階段使用的是RPC協(xié)議,因?yàn)樗菻TTP更適合項(xiàng)目?jī)?nèi)部通信
三.RPC簡(jiǎn)介
1.RFC
RFC(Request For Comments)是由互聯(lián)網(wǎng)工程任務(wù)組(IEIF)發(fā)布的文件集.文件集中每個(gè)文件都有自己唯一編號(hào).例如:rfc1831.目前RFC文件由互聯(lián)網(wǎng)協(xié)會(huì)(Internet Society,ISOC)贊助發(fā)行
? ? RPC就收集在RFC1831中.可以通過(guò)下面網(wǎng)址查看:
https://datatracker.ietf.org/doc/rfc1831/
2.RPC
RPC在rgc1831中收錄,RPC(Remote Procedure Call)遠(yuǎn)程過(guò)程調(diào)用協(xié)議
RPC協(xié)議規(guī)定允許互聯(lián)網(wǎng)中一臺(tái)主機(jī)程序調(diào)動(dòng)另一臺(tái)主機(jī)程序,而程序員無(wú)需對(duì)這個(gè)交互過(guò)程進(jìn)行編程.在RPC協(xié)議中強(qiáng)調(diào)當(dāng)A程序調(diào)用B程序中功能或方法時(shí),A是不知道B中方法具體實(shí)現(xiàn)的
RPC是上層協(xié)議,底層可以基于TCP協(xié)議,也可以基于HTTP協(xié)議.一般我們說(shuō)RPC都是基于RPC的具體實(shí)現(xiàn),如:Dubbo框架.從廣義上講只要是滿足網(wǎng)絡(luò)中進(jìn)行通信調(diào)用都統(tǒng)稱為RPC,甚至HTTP協(xié)議都可以說(shuō)是RPC的具體實(shí)現(xiàn),但是具體分析看來(lái)RPC協(xié)議要比HTTP協(xié)議更加高效,基于RPC的框架功能更多
RPC協(xié)議是基于分布式架構(gòu)而出現(xiàn)的,所以RPC在分布式項(xiàng)目中有著得天獨(dú)厚的優(yōu)勢(shì)
3.RPC和HTTP對(duì)比
3.1具體實(shí)現(xiàn)
RPC:可以基于TCP協(xié)議,也可以基于HTTP協(xié)議
HTTP:基于HTTP協(xié)議
3.2效率
RPC:自定義具體實(shí)現(xiàn)可以減少很多無(wú)用的報(bào)文內(nèi)容,使得報(bào)文體積更小
HTTP:如果是HTTP1.1報(bào)文中很多內(nèi)容都是無(wú)用的.如果是HTTP2.0以后和RPC相差不大,比RPC少的可能就是一些服務(wù)治理等功能
3.3連接方式
RPC:長(zhǎng)鏈接支持
HTTP:每次連接都是3次握手(斷開(kāi)連接為4次揮手)
3.4性能
RPC可以基于很多序列化方式.如:thrift
HTTP主要是通過(guò)JSON,序列化和方序列化效率更低
3.5注冊(cè)中心
RPC:一般RPC框架都帶有注冊(cè)中心
HTTP:都是直連
3.6負(fù)載均衡
RPC:絕大多數(shù)RPC框架都帶有負(fù)載均衡測(cè)量
HTTP:一般都需要借助第三方工具.如:nginx
3.7綜合結(jié)論
RPC框架一般都帶有豐富的服務(wù)治理等功能,更適合企業(yè)內(nèi)部接口調(diào)用.而HTTP更適合多平臺(tái)之間相互調(diào)用
四.HttpClient實(shí)現(xiàn)RPC
1.HttpClient簡(jiǎn)介
在JDK中java.net包下提供了用戶HTTP訪問(wèn)的基本功能,但是它缺少靈活性或許多應(yīng)用所需要的功能
HttpClient起初是Apache Jackarta Common的子項(xiàng)目.用來(lái)提供高效的,最新的,功能豐富的支持HTTP協(xié)議的客戶端編程工具包,并且他支持HTTP協(xié)議最新的版本.2007年成為頂級(jí)項(xiàng)目
通俗解釋:HttpClient可以實(shí)現(xiàn)Java代碼完成標(biāo)準(zhǔn)HTTP請(qǐng)求及響應(yīng)
2.代碼實(shí)現(xiàn)
2.1服務(wù)端
新建項(xiàng)目HttpClientServer
2.1.1新建控制器
com.bjsxt.controller.DemoController
@Controller
public class DemoController{
? ? @RequestMapping("/demo")
? ? @ResponseBody
? ? public String demo(String param){
? ? ? ? return "demo"+param;
????}
}
2.1.2新建啟動(dòng)器
com.bjsxt.HttpClientServerApplication
@SpringBootApplication
public class HttpClientServerApplication{
? ? public static void main(String[] args){
? ? ? ? SpringApplication.run(HttpClientServerApplication.class,args);
????}
}
2.2客戶端
新建HttpClientDemo項(xiàng)目
2.2.1添加依賴
<dependencies>
? ? <dependency>
? ? ? ? <groupId>org.apache.httpcomponents</groupId>
? ? ? ? <artifactId>httpclient</artifactId>
? ? ? ? <version>4.5.10</version>
????</dependency>
</dependencies>
2.2.2新建類
新建com.bsjxt.HttpClientDemo,編寫(xiě)主方法
2.2.2.1使用POST方法訪問(wèn)
public class HttpClientDemo{
? ? public static void main(String[] args){
? ? ? ? try{
? ? ? ? ? ? CloseableHttpClient httpClient = HttpClients.createDefault();
? ? ? ? ? ? HttpPost post = new HttpPost("http://localhost:8080/demo");
? ? ? ? ? ? HttpEntity httpEntity = null;
? ? ? ? ? ? List<NameValuePair>params = new ArrayList<>();
? ? ? ? ? ? params.add(new BasicNameValuePair("param","123"));
? ? ? ? ? ? StringEntity entity = new UrlEncodedFormEntity(params,"utf-8");
? ? ? ? ? ? post.setEntity(entity);
? ? ? ? ? ? CloseableHttpResponse response = httpClient.execute(post);
? ? ? ? ? ? String result = EntityUtils.toString(response.getEntity());
? ? ? ? ? ? System.out.println(result);
? ? ? ? ? ? response.close();
? ? ? ? ? ? httpClient.close();
????????}catcha(IOException e){
? ? ? ? ? ? e.printStackTrace();
????????}
????}
}
2.2.2.2使用GET方式訪問(wèn)
public static void main(String[] args){
? ? try{
? ? ? ? CloseableHttpClient httpClient = HttpClients.createDefault();
? ? ? ? URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/demo");
? ? ? ? uriBuilder.addParameter("param","get123");
? ? ? ? HttpGet get = new HttpGet(uriBuilder.build());
? ? ? ? CloseableHttpResponse response = httpClient.execute(get);
? ? ? ? String result = EntityUtils.toString(response.getEntity(),"utf-8");
? ? ? ? System.out.println(result);
? ? ? ? response.close();
? ? ? ? httpClient.close();
????}catch(URISyntaxException e){
? ? ? ? e.printStackTrace();
????}catch(IOException e){
? ? ? ? e.printlnStackTrace();
????}
}
3.HttpClient請(qǐng)求包含JSON
3.1java代理實(shí)現(xiàn)
public class HttpClientDemo{
? ? public static void main(Stirng[] args){
? ? ? ? try{
? ? ? ? ? ? CloseableHttpClient httpClient = HttpClients.createDefault();
? ? ? ? ? ? HttpPost post = new HttpPost("http://localhost:8080/demo");
? ? ? ? ? ? HttpEntity httpEntity = null;
? ? ? ? ? ? String json = "{}";
? ? ? ? ? ? StringEntity entity = new StringEntity(json,ContentType.APPLICATION_JSON);
? ? ? ? ? ? post.setEntity(entity);
? ? ? ? ? ? CloseableHttpResponse response = httpClient.execute(post);
? ? ? ? ? ? String result - EntityUtils.toString(response.getEntity());
? ? ? ? ? ? System.out.println(result);
? ? ? ? ? ? response.close();
? ? ? ? ? ? httpClient.close();
????????}catch(IOException e){
? ? ? ? ? ? e.printStackTrace();
????????}
????}
}
4.服務(wù)端控制器接口參數(shù)
@RequestBody把請(qǐng)求體中六數(shù)據(jù)轉(zhuǎn)換為指定的對(duì)象.多用在請(qǐng)求體參數(shù)是json數(shù)據(jù)且請(qǐng)求的Content-Type="application/json"
@RequestMapping("/demo4")
@ResponseBody
public String demo4(@RequestBody List<People>list){
? ? System.out.println(list);
? ? return list.toString();
}
5.Jackson用法
5.1把對(duì)象轉(zhuǎn)換為json字符串
ObjectMapper objectMapper = new ObjectMapper();
People peo = new People();
String jsonStr = objectMapper.writeValueAsString(peo);
5.2把json字符串轉(zhuǎn)換為對(duì)象
ObjectMapper objectMapper= new ObjectMapper();
People peo = objectMapper.readValue(jsonStr,People.class);
5.3把json字符串轉(zhuǎn)換為L(zhǎng)ist集合
ObjectMapper objectMapper = new ObjectMapper();
JavaType javaType = objectMapper.getTypeFactory().constructParametericType(List.class,People.class);
List<People> list = objectMapper.readValue(jsonStr,javaType);
6.Ajax發(fā)送json參數(shù)寫(xiě)法
var json = '[{"id":123,"name":"bjsxt"},{"id":123,"name:"bjsxt"}]';
$.ajax({
? ? url:'/demo5',
? ? success:function(data}{
? ? ? ? alert(data);
? ? ? ? for(var i=0; i<data.length; i++){
????????????alert(data[i].id+"? "+data[i].name);
????????}
????},
? ? contentType:'application/json',//請(qǐng)求體中參數(shù)類型
? ? dataType:'json',//響應(yīng)內(nèi)容類型
? ? data:json
});
7.跨域
跨域:協(xié)議,端口,ip中只要有一個(gè)不同就是跨域請(qǐng)求
同源策略:瀏覽器默認(rèn)只允許ajax訪問(wèn)同源(協(xié)議,ip,端口都相同)內(nèi)容
解決同源策略:
在控制器接口上天啊及@CrossOrigin.表示允許跨域.本質(zhì)在響應(yīng)頭中添加
Access-Control-Allow-Origin:*
@RequestMapping("/demo5")
@ResponseBody
@CrossOrigin
public List<People>demo5(@RequestBody List<People>list){
? ? System.put.println(list);
? ? return list;
}
五.RMI實(shí)現(xiàn)RPC
1.RMI簡(jiǎn)介
RMI(Remote Method Invocation)遠(yuǎn)程方法調(diào)用
RMI是從JDK1.2推出的功能,它可以實(shí)現(xiàn)在一個(gè)java應(yīng)用中可以像調(diào)用本地方法一樣調(diào)用另一個(gè)服務(wù)器中java應(yīng)用(JVM)中的內(nèi)容
RMI是java語(yǔ)言的遠(yuǎn)程調(diào)用,無(wú)法實(shí)現(xiàn)跨語(yǔ)言
2.執(zhí)行流程
Registry(注冊(cè)表)是防止所有服務(wù)器對(duì)象的命名空間.每次服務(wù)端創(chuàng)建一個(gè)對(duì)象時(shí),它都會(huì)使用bind()或rebind()方法注冊(cè)該對(duì)象.這些是使用稱為名稱的唯一名稱注冊(cè)的.
要調(diào)用遠(yuǎn)程對(duì)象,客戶端需要該對(duì)象的引用.即通過(guò)服務(wù)端綁定的名稱從注冊(cè)表中獲取對(duì)象(lookup()方法)
3.API介紹
3.1Remote
java.rmi.Remote定義了此接口為遠(yuǎn)程調(diào)用接口.如果接口被外部調(diào)用,需要繼承次接口
3.2RemoteException
java.rmi.RemoteException
繼承了Remote接口,如果方法是允許被遠(yuǎn)程調(diào)用的,需要拋出此異常
3.3UnicastRemoteObject
java.rmi.server.UnicastRemoteObject
此類實(shí)現(xiàn)了Remote接口和Serializable接口
自定義接口實(shí)現(xiàn)類除了實(shí)現(xiàn)自定義接口還需要繼承此類
3.4LocateRegistry
java.rmi.registry.LocateRegistry
可以通過(guò)LocateRegistry子本機(jī)上創(chuàng)建Registry,通過(guò)特定的端口就可以訪問(wèn)這個(gè)Registry
3.5Naming
java.rmi.Naming
Naming定義了發(fā)布內(nèi)容可訪問(wèn)RMI名稱.也是通過(guò)Naming獲取到指定的遠(yuǎn)程方法
4.代碼實(shí)現(xiàn)
4.1服務(wù)端創(chuàng)建
創(chuàng)建RmiServer項(xiàng)目
4.1.1編寫(xiě)接口
com.bjsxt.service.DemoService編寫(xiě)
public interface DemoService extends Remote{
? ? String demo(String demo)throws RemoteException;
}
4.1.2.編寫(xiě)實(shí)現(xiàn)類
com.bsjxt.service.impl.DemoServiceImpl編寫(xiě)
注意:
? ? 構(gòu)造方法是public的.默認(rèn)生成protected
public class DemoServiceImpl extends UnicastRemoteObject implements DemoService{
? ? public DemoServiceImpl() throws RemoteException{}
? ? @Override
? ? public String demo(String demo)throws RemoteException{
? ? ? ? return demo+"123";
????}
}
4.1.3編寫(xiě)主方法
編寫(xiě)com.bjsxt.DemoService類,生成主方法
public class DemoServer{
? ? public static void main(String[] args){
? ? ? ? try{
? ? ? ? ? ? DemoService demoService = new DemoServiceImpl();
? ? ? ? ? ? LocateRegistry.createRegistry(8888);
? ? ? ? ? ? Naming.bind("rmi://localhsot:8888/demoService",demoService);
????????}catch(RemoteException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(AlreadyBoundException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(malformedURLException){
? ? ? ? ? ? e.printStackTrace();
????????}
????}
}
4.1.4運(yùn)行項(xiàng)目
運(yùn)行項(xiàng)目后,項(xiàng)目一直處于啟動(dòng)狀態(tài),表示可以遠(yuǎn)程訪問(wèn)此項(xiàng)目中的遠(yuǎn)程方法
4.2創(chuàng)建客戶端代碼
創(chuàng)建項(xiàng)目RmiClient
4.2.1復(fù)制服務(wù)端接口
把服務(wù)端com.bjsxt.service.DemoService粘貼到項(xiàng)目中
注意:復(fù)制代碼僅為快速完成案例,學(xué)習(xí)技術(shù),在商業(yè)開(kāi)發(fā)中,DemoService接口應(yīng)該使用獨(dú)立的工程定義,并在服務(wù)端和客戶端工程中通過(guò)依賴的方式引入
4.2.2創(chuàng)建主方法類
新建com.bjsxt.DemoClient
public class DemoClient{
? ? public static void main(String[] args){
? ? ? ? try{
? ? ? ? ? ? DemoService demoService = (DemoService)Naming.lookup("rmi://localhost:8888/demoService");
? ? ? ? ? ? String result = demoService.demo("demo34");
? ? ? ? ? ? System.out.println(result);
????????}catch(NotBoundException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(MalformedURLException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(RemoteException e){
? ? ? ? ? ? e.printStackTrace();
????????}
????}
}
六.Zookeeper安裝
略
七.常用命令
略
八.向Zookeeper中注冊(cè)內(nèi)容
先進(jìn)項(xiàng)目ZookeeperClient
1.創(chuàng)建/demo節(jié)點(diǎn)
使用zookeeper的客戶端命令工具創(chuàng)建/demo
./zkCli.sh
create /demo
2.添加依賴
<dependencies>
? ? <dependency>
? ? ? ? <groupId>org.apache.zookeeper</groupId>
? ? ? ? <artifactId>zookeeper</artifactId>
? ? ? ? <version>3.5.5</version>
????</dependency>
</dependencies>
3.編寫(xiě)代碼
創(chuàng)建類com.bjsxt.MyApp
ZooDefs.Ids.OPEN-ACL_UNSAFE表示權(quán)限
CreateMode.PERSISTENT_SEQUENTIAL永久存儲(chǔ),文件內(nèi)容編寫(xiě)遞增
public static void main(String[] args){
? ? try{
? ? ? ? Zookeeper zookeeper = new Zookeeper("192.168.232.132:2181",60000,new Watcher(){;
? ??????????@Override
? ? ? ? ????public void process(WatcherEvent watchedEvent){
????????????????System.out.println("獲取連接");
????????????}
? ? });
? ? String content = zookeeper.create("/demo/nn","content".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT_SEQUENTIAL);
? ? System.out.println("content"+content);
????}catch(IOException e){
? ? ? ? e.printStackTrace();
????}catch(KeeperException e){
? ? ? ? e.printStackTrace();
????}catch(InterruptedException e){
? ? ? ? e.printStackTrace();
????}
}
4.查看上傳數(shù)據(jù)
ls -R /? ? 查看列表
get /demo/nn000000002? ? ?查看內(nèi)容
九.從zookeeper中發(fā)現(xiàn)內(nèi)容
在原有項(xiàng)目中新建一個(gè)類,類中編寫(xiě)主方法
public static void main(String[] args){
? ? try{
? ? ? ? Zookeeper zookeeper = new Zookeeper("192.168.232.132:2181",60000,new Watcher(){
? ? ? ? ? ? @Override
? ? ? ? ? ? public void process(WatchedEvent watchedEvent){
? ? ? ? ? ? ? ? System.out.println("獲取連接");
????????????}
????????});
? ? ? ? //獲取列表
? ? ? ? List<String>list = zookeeper.getChildren("/demo",false);
? ? ? ? for(String child:list){
? ? ? ? ? ? byte[] result = zookeeper.getData("/demo/"+child,false,null);
? ? ? ? ? ? Ssytem.out.println(new String(result));
????????}
????}catch(IOException e){
? ? ? ? e.printStackTrace();
????}catch(KeeperException e){
? ? ? ? e.printStackTrace();
????}catch(InterruptedException e){
? ? ? ? e.printStackTrace();
????}
}
十.手寫(xiě)RPC框架
使用Zookeeper作為注冊(cè)中心,RMI作為連接技術(shù),手寫(xiě)RPC框架
1.創(chuàng)建父項(xiàng)目ParentDemo
包含3個(gè)集合子項(xiàng)目
? ? service:包含被serviceImpl和consumer依賴的接口
? ? serviceImpl:provider提供的服務(wù)內(nèi)容
? ? consumer:消費(fèi)者,調(diào)用服務(wù)內(nèi)容
2.在父項(xiàng)目中添加依賴
<parent>
? ? <groupId>org.springframework.boot<groupId>
? ? <artifactId>spring-boot-starter-parent</artifactId>
? ? <version>2.1.10.RELEASE</version>
</parent>
<dependencies>
? ? <dependency>
? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? <artifactId>spring-boot-starter-web</artifactId>
????</dependency>
? ? <dependency>
? ? ? ? <groupId>org.apache.zookeeper</groupId>
? ? ? ? <aritfactId>zookeeper</artifactId>
? ? ? ? <version>3.5.5</version>
????</dependency>
</dependencies>
3.創(chuàng)建service項(xiàng)目
項(xiàng)目結(jié)構(gòu)如下:此項(xiàng)目中重點(diǎn)編寫(xiě)需要被兩個(gè)項(xiàng)目依賴的接口
4.創(chuàng)建DemoService接口
創(chuàng)建com.bjsxt.DemoService,具體內(nèi)容如下
public interface DemoService extends Remote{
? ? String demo(String param)throws RemoteException;
}
5.創(chuàng)建serviceImpl項(xiàng)目
此項(xiàng)目編寫(xiě)接口具體實(shí)現(xiàn),RMI服務(wù)發(fā)布和把信息發(fā)送到Zookeeper中
項(xiàng)目結(jié)構(gòu)如下:
在pom.xml中添加對(duì)service項(xiàng)目的依賴
<dependencies>
? ? <dependency>
? ? ? ? <artifactId>service</artifactId>
? ? ? ? <groupId>com.bjsxt</groupId>
? ? ? ? <version>1.0-SNAPSHOT</version>
????</dependency>
</dependencies>
6.創(chuàng)建DemoServiceImpl
創(chuàng)建com.bjsxt.service.impl.DemoServiceImpl
public class DemoServiceImpl extends UnicastRemoteObject implements DemoService{
? ? public DemoServiceImpl()throws RemoteException{
????}
? ? @Override
? ? public String demo(String param)throws RemoteException{
? ? ? ? return param+"123";
? ? }
}
7.創(chuàng)建RmiRun
創(chuàng)建com.bsjxt.RmiRun.實(shí)現(xiàn)RMI服務(wù)的發(fā)布和Zookeeper消息的發(fā)布
public class RmiRun{
? ? public static void main(String[] args){
? ? ? ? try{
? ? ? ? ? ? DemoService demoService = new DemoServiceImpl();
? ? ? ? ? ? LocateRegistry.createRegistry(8888);
? ? ? ? ? ? String url = "rmi://localhsot:8888/demoService";
? ? ? ? ? ? Naming.bind(url,demoService);
? ? ? ? ? ? Zookeeper zookeeper = new Zookeeper("192.168.232.132:2181",60000,new Watcher(){
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void process(WatcherEvent watchedEvent){
? ? ? ? ? ? ? ? ? ? Ssytem.out.println("獲取連接");
????????????????}
????????????});
? ? ? ? ? ? String content = zookeeper.create("/demo/demoService",url.getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
? ? ? ? ? ? System.out.println("服務(wù)發(fā)布成功...");
????????}catch(AlreadyBoundException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(IOException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(KeeperException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(InterruptedException e){
? ? ? ? ? ? e.printStackTrace();
????????}
????}
}
8.創(chuàng)建Consumer項(xiàng)目
新建consumer項(xiàng)目,此項(xiàng)目需要從zookeeper中獲取rmi信息,并調(diào)用rmi服務(wù)
在pom.xml中添加對(duì)service項(xiàng)目的依賴
<dependencies>
? ? <dependency>
? ? ? ? <artifactId>service</artifactId>
? ? ? ? <groupId>com.bjsxt</groupId>
? ? ? ? <version>1.0-SNAPSHOT</version>
????</dependency>
</dependencies>
9.創(chuàng)建接口和實(shí)現(xiàn)類
創(chuàng)建com.bjsxt.service.ConsumerService接口
創(chuàng)建com.bjsxt.servioce.impl.ConsumerServiceImpl實(shí)現(xiàn)類
public interface ConsumerService{
? ? String consumerService(String param);
}
@Service
public class ConsumerServiceImpl implements ConsumerService{
? ? @Override
? ? public String consumerService(String param){
? ? ? ? try{
? ? ? ? ? ? Zookeeper zookeeper = new Zookeeper("192.168.232.132:2181",60000,new Watcher(){
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void process(WatchedEvent watchedEvent){
? ? ? ? ? ? ? ? ? ? System.out.println("獲取連接");
????????????????}
????????????});
? ? ? ? ? ? byte[] urlByte = zookeeper.getData("/demo/demoService",false,null);
? ? ? ? ? ? DemoService demoService = (DemoService)Naming.lookup(new String(urlByte));
? ? ? ? ? ? String result = demoService.demo(param);
? ? ? ? ? ? System.out.println(result);
? ? ? ? ? ? return result;
????????}catch(IOException e){
? ? ? ? ? ? e.printStackTrace();
????????}catch(InteruptedException e){
? ? ? ? ? ? e.printlnStackTrace();
????????}catch(NotBoundException e){
? ? ? ? ? ? e.printStackTrace();
????????}
? ? ? ? return null;
? ? }
}
10.創(chuàng)建控制器
創(chuàng)建com.bjsxt.controller.DemoController控制器
@Controller
public class DemoController{
? ? @Autowired
? ? private ConsumerService consumerService;
? ? @RequestMapping("/demo")
? ? @ResponseBody
? ? public String demo(String param){
? ? ? ? return consumerService.consumerService(param);
????}
}
11.創(chuàng)建啟動(dòng)器
創(chuàng)建com.bjsxt.ConsumerApplication
@SpringBootApplication
public class ConsumerApplication{
? ? public static void main(String[] args){
? ? ? ? SpringApplication.run(ConsumerApplication.class,args);
????}
}
12.測(cè)試
在瀏覽器輸入:http://localhost:8080/demo?param=demo
觀察結(jié)果是否是:demo123