rpc(遠(yuǎn)程過(guò)程調(diào)用)饮寞,目的是調(diào)用遠(yuǎn)程計(jì)算機(jī)上的服務(wù)彩郊,首先呈队,我們先把服務(wù)完成
創(chuàng)建服務(wù)接口
public interfaceHello {
public void hello(Stringname, inti);
public voidworld();
}
創(chuàng)建接口實(shí)現(xiàn)類(lèi)
public class HelloImp limplements Hello {
public void hello(Stringname, inti) {
System.out.println("hello "+name+" "+i);
}
public void world() {
System.out.println("hello world");
}
}
到此惭每,我們已經(jīng)完成了服務(wù)的開(kāi)發(fā)熙宇,接下來(lái)坐昙,是把開(kāi)發(fā)好的服務(wù)提供出去給其他應(yīng)用調(diào)用绳匀,這里需要引入注冊(cè)中心的概念,我們開(kāi)發(fā)的服務(wù)炸客,需要注冊(cè)到注冊(cè)中心疾棵,客戶(hù)端則通過(guò)訂閱注冊(cè)中心的數(shù)據(jù),來(lái)決定調(diào)用的服務(wù)痹仙。這里也使用了廣大人民群眾熟知的zookeeper做為注冊(cè)中心是尔。
接下來(lái)重點(diǎn)介紹啟動(dòng)服務(wù)發(fā)布到注冊(cè)中心過(guò)程
自定義命名空間
因?yàn)榇蛟斓氖菍儆谧约旱目蚣埽?dāng)然需要有一個(gè)屬于自己的命名空間(這里L(fēng)Z所創(chuàng)命名空間為fly)开仰,這里需要根據(jù)spring的一些規(guī)范來(lái)拓展拟枚,在META-INF目錄下分別創(chuàng)建fly.xsd,spring.handles,spring.schemas,然后再創(chuàng)建相應(yīng)的bean解析類(lèi)和命名空間處理類(lèi)众弓,相關(guān)的用法有興趣的朋友可以查看相關(guān)資料恩溅,這里提供一個(gè)鏈接http://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html?,這樣做的目的就是谓娃,當(dāng)應(yīng)用啟動(dòng)暴匠,掃描spring文件加載bean時(shí),spring容器能讀取到你自定義命名空間下的配置并且執(zhí)行你所寫(xiě)的解析類(lèi)解析配置傻粘,如下每窖,服務(wù)端配置文件:
啟動(dòng)服務(wù)
服務(wù)注冊(cè)到注冊(cè)中心
啟動(dòng)netty服務(wù)端綁定IP和端口
至此,服務(wù)發(fā)布過(guò)程完成弦悉!
PS:下面說(shuō)一下服務(wù)發(fā)布綜合管理類(lèi)ServiceBean窒典,當(dāng)spring容器讀取到標(biāo)簽是會(huì)加載解析并加載,該類(lèi)實(shí)現(xiàn)了spring框架下的ApplicationListener接口稽莉,當(dāng)spring容器加載完成時(shí)瀑志,會(huì)調(diào)用onApplicationEvent()方法,我們把服務(wù)發(fā)布的 細(xì)節(jié)放在其方法中,當(dāng)spring容器加載完畢 產(chǎn)生ContextRefreshedEvent事件時(shí)劈猪,服務(wù)便會(huì)隨著容器的啟動(dòng)而發(fā)布出來(lái)
public?class ServiceBean?implements ApplicationListener?{
//接口服務(wù)名
private String interfaceClass;
//接口服務(wù)實(shí)現(xiàn)類(lèi)
private T ref;
public?static?final Map?exporterMap=new ConcurrentHashMap();
public?void export()throwsIllegalAccessException,InstantiationException,UnknownHostException,InterruptedException{
System.out.println("do?export.....");
try{
Class clz?=Class.forName(interfaceClass);
Method[]?methods?=?clz.getDeclaredMethods();
ArrayList?methodNames?=newArrayList();
for(Methodm:methods){
methodNames.add(m.getName());
}
String[]?methodArray?=? methodNames.toArray(newString[1]);
URL url?=new URL(NetUtil.getHostAddress(),interfaceClass,methodArray,2018);
Object proxy?=ProxyFactory.getProxy(ref.getClass());//創(chuàng)建實(shí)現(xiàn)類(lèi)代理
String key?=URL.urlEncoder(url.toString());
exporterMap.put(key,proxy);
//get注冊(cè)中心
ZookeeperRegister register?=ZookeeperRegister.getRegister();
register.register(url);//注冊(cè)服務(wù)URL
RpcServer rpcServer?=newRpcServer();
rpcServer.start();//啟動(dòng)進(jìn)程綁定端口
}catch(Exceptione)?{
e.printStackTrace();
}
}
public?void onApplicationEvent(ApplicationEvent?applicationEvent)?{
try{
if(ContextRefreshedEvent.class.getName().equals(applicationEvent.getClass().getName())){
export();
}
}catch(IllegalAccessExceptione)?{
e.printStackTrace();
}catch(InstantiationExceptione)?{
e.printStackTrace();
}catch(UnknownHostExceptione)?{
e.printStackTrace();
}catch(InterruptedExceptione)?{
e.printStackTrace();
}
}
public String getInterfaceClass()?{
return interfaceClass;
}
public?void setInterfaceClass(StringinterfaceClass)?{
this.interfaceClass=?interfaceClass;
}
public T getRef()?{
returnref;
}
public?void setRef(Tref)?{
this.ref=?ref;
}
}