詳解Java如何優(yōu)雅的調(diào)用dubbo同時(shí)不使用其它jar包
1、正常dubbo調(diào)用流程
引入dubbo依賴
引入他人提供的clinet依賴包;
配置相同的注冊(cè)中心,使用@Reference注解注入對(duì)應(yīng)的service接口(注意是Reference是dubbo包下的,不是spring那個(gè))
2、如果想在不引用他人jar包的情況下如何調(diào)用呢
dubbo泛化調(diào)用-dubbo原生支持的優(yōu)雅方法
使用場(chǎng)景:
消費(fèi)者不希望引入生產(chǎn)者提供的clinet依賴;
例如:消費(fèi)者是一個(gè)基礎(chǔ)服務(wù),需要調(diào)用很多生產(chǎn)者的dubbo方法,那他就要引入很多的jar包;
消費(fèi)者不使用java語言,而是使用其他的語言(例如:Python);
如何使用:
1.需要知道對(duì)方方法的全路徑名稱(interfaceName)
2.如果對(duì)方的dubbo有指定的版本號(hào)(version)和組(group)要指定一下,不然有很大可能會(huì)調(diào)用不通
3.要知道對(duì)方的注冊(cè)中心地址和連接方式(如果是在同一個(gè)zk注冊(cè)中心就更好了)
1.獲取泛化對(duì)象
private GenericService getGenericService(String interfaceName, String version, String group) { ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); // set application ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setId(APPLICATION_ID); applicationConfig.setName(APPLICATION_ID); reference.setApplication(applicationConfig); // 通過zookeeper連接 RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress(zkAddress); registryConfig.setProtocol(ZOOKEEPER); registryConfig.setCheck(false); reference.setRegistry(registryConfig); // set timeout reference.setTimeout(syncForwardTimeout); // set retry times reference.setRetries(syncRetries); // set check reference.setCheck(false); // set generic reference.setGeneric(true); // set interface version if (version != null && version.length() != 0) { reference.setVersion(version); } // set interface name reference.setInterface(interfaceName); // set service id reference.setId(interfaceName); // set dubbo protocol reference.setProtocol(DUBBO); // if (group != null && group.length() != 0) { reference.setGroup(group); } // 從zookeeper獲取緩存,從緩存中獲取泛化 return ReferenceConfigCache.getCache().get(reference); }
2.泛化調(diào)用入?yún)⑻幚?/h3>
private ResponseDataDto<R> invoke(GenericService genericService, UpDataReqDto upDataReqDto, String method) {
String[] paramTypes = new String[1];
Object[] paramValues = new Object[1];
int i = 0;
paramTypes[i] = upDataReqDto.getClass().getTypeName();
paramValues[i] = upDataReqDto;
Object object = genericService.$invoke(method, paramTypes, paramValues);
return JSON.parseObject(JSON.toJSONString(object), new TypeReference<ResponseDataDto<R>>(){});
}
private ResponseDataDto<R> invoke(GenericService genericService, UpDataReqDto upDataReqDto, String method) { String[] paramTypes = new String[1]; Object[] paramValues = new Object[1]; int i = 0; paramTypes[i] = upDataReqDto.getClass().getTypeName(); paramValues[i] = upDataReqDto; Object object = genericService.$invoke(method, paramTypes, paramValues); return JSON.parseObject(JSON.toJSONString(object), new TypeReference<ResponseDataDto<R>>(){}); }
實(shí)現(xiàn)原理:
泛化調(diào)用的實(shí)現(xiàn)主要涉及兩個(gè)filter
com.alibaba.dubbo.rpc.filter.GenericFilter
com.alibaba.dubbo.rpc.filter.GenericImplFilter
復(fù)制代碼
泛化調(diào)用的流程:
調(diào)用 <-> GenericImplFilter <-> 網(wǎng)絡(luò)(RPC) <-> GenericFilter <-> 服務(wù)實(shí)現(xiàn)
泛化調(diào)用的核心源碼:
GenericImplFilter: //判斷是不是泛化調(diào)用 if (isCallingGenericImpl(generic, invocation)) { RpcInvocation invocation2 = new RpcInvocation(invocation); /** * Mark this invocation as a generic impl call, this value will be removed automatically before passing on the wire. * See {@link RpcUtils#sieveUnnecessaryAttachments(Invocation)} */ invocation2.put(GENERIC_IMPL_MARKER, true); String methodName = invocation2.getMethodName(); Class<?>[] parameterTypes = invocation2.getParameterTypes(); Object[] arguments = invocation2.getArguments(); String[] types = new String[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { types[i] = ReflectUtils.getName(parameterTypes[i]); } Object[] args; if (ProtocolUtils.isBeanGenericSerialization(generic)) { args = new Object[arguments.length]; for (int i = 0; i < arguments.length; i++) { args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD); } } else { args = PojoUtils.generalize(arguments); } if (RpcUtils.isReturnTypeFuture(invocation)) { invocation2.setMethodName($INVOKE_ASYNC); } else { invocation2.setMethodName($INVOKE); } invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES); invocation2.setParameterTypesDesc(GENERIC_PARAMETER_DESC); invocation2.setArguments(new Object[]{methodName, types, args}); return invoker.invoke(invocation2); } // 普通服務(wù)進(jìn)行通用調(diào)用 else if (isMakingGenericCall(generic, invocation)) { Object[] args = (Object[]) invocation.getArguments()[2]; if (ProtocolUtils.isJavaGenericSerialization(generic)) { for (Object arg : args) { if (byte[].class != arg.getClass()) { error(generic, byte[].class.getName(), arg.getClass().getName()); } } } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { for (Object arg : args) { if (!(arg instanceof JavaBeanDescriptor)) { error(generic, JavaBeanDescriptor.class.getName(), arg.getClass().getName()); } } } invocation.setAttachment( GENERIC_KEY, invoker.getUrl().getParameter(GENERIC_KEY)); } GenericFilter: if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC)) && inv.getArguments() != null && inv.getArguments().length == 3 && !GenericService.class.isAssignableFrom(invoker.getInterface())){ .......泛化調(diào)用處理邏輯...... }
3、總結(jié)
從源碼設(shè)計(jì)來看泛化調(diào)用提供了在沒有接口依賴的情況下進(jìn)行調(diào)用的解決方案;
從擴(kuò)展上來看泛化調(diào)用的侵入性不強(qiáng),可以很好的用于框架擴(kuò)展;
到此這篇關(guān)于詳解Java如何優(yōu)雅的調(diào)用dubbo同時(shí)不使用其它jar包的文章就介紹到這了,更多相關(guān)Java調(diào)用dubbo內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java SpringMVC的@RequestMapping注解使用及說明
這篇文章主要介紹了Java SpringMVC的@RequestMapping注解使用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01Java的Jackson庫中復(fù)雜對(duì)象集合的幾種簡(jiǎn)單轉(zhuǎn)換
本文主要介紹了Java的Jackson庫中復(fù)雜對(duì)象集合的幾種簡(jiǎn)單轉(zhuǎn)換。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02Spring-基于Spring使用自定義注解及Aspect實(shí)現(xiàn)數(shù)據(jù)庫切換操作
這篇文章主要介紹了Spring-基于Spring使用自定義注解及Aspect實(shí)現(xiàn)數(shù)據(jù)庫切換操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09java hibernate使用注解來定義聯(lián)合主鍵
這篇文章主要介紹了java hibernate使用注解來定義聯(lián)合主鍵的相關(guān)資料,需要的朋友可以參考下2017-01-01基于Zookeeper實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能
無論是采用SOA還是微服務(wù)架構(gòu),都需要使用服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)組件,本文將基于 Zookeeper 實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能,如果跟我一樣有同樣的困惑,希望可以通過本文了解其他組件如何使用 Zookeeper 作為注冊(cè)中心的工作原理2023-09-09簡(jiǎn)單了解JAVA SimpleDateFormat yyyy和YYYY的區(qū)別
這篇文章主要介紹了簡(jiǎn)單了解JAVA SimpleDateFormat yyyy和YYYY的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03Java大數(shù)據(jù)處理的核心技術(shù)MapReduce框架
MapReduce是一種分布式計(jì)算框架,適用于大規(guī)模的數(shù)據(jù)處理。它將大數(shù)據(jù)分成多個(gè)小數(shù)據(jù)塊,通過Map和Reduce兩個(gè)階段對(duì)數(shù)據(jù)進(jìn)行處理和分析。MapReduce框架具有可靠、高效、可擴(kuò)展等特點(diǎn),已經(jīng)成為大數(shù)據(jù)處理的核心技術(shù)2023-05-05Mybatis Plus LambdaQueryWrapper的具體用法
Mybatis Plus 在其基礎(chǔ)上擴(kuò)展了 LambdaQueryWrapper,LambdaQueryWrapper 提供了更加簡(jiǎn)便的查詢語法,同時(shí)也避免了SQL注入的風(fēng)險(xiǎn),感興趣的可以了解一下2023-11-11