dubbo暴露出HTTP服务
dubbo暴露出HTTP服务
点关注不迷路,欢迎再访!
精简博客内容,尽量已专业术语来分享。
努力做到对每一位认可自己的读者负责。
帮助别人的同时更是丰富自己的良机。
目录
- dubbo暴露出HTTP服务
- 前言
- 准备工作
- HttpProviderConf配置类
- 请求响应入参、出参
- HttpRequest入参
- HttpResponse 响应
- 暴露服务controller
最近接触dubbo+zuul,涉及到将dubbo服务暴露为http,简单记录下。
前言
通常来说一个dubbo服务都是对内给内部调用的,但也有可能一个服务就是需要提供给外部使用,并且还不能有使用语言的局限性。本章讲到的没有那么复杂,就只是把一个不需要各种权限检验的dubbo服务对外提供为HTTP服务。
准备工作
以下是本文所涉及到的一些知识点:
Spring相关知识
Java反射相关知识
SpringMVC相关知识
其实思路很简单,利用SpringMVC提供一个HTTP接口。在该接口中通过入参进行反射找到具体的dubbo服务实现进行调用。
HttpProviderConf配置类
首先需要定义一个HttpProviderConf类用于保存声明需要对外提供服务的包名,毕竟我们反射时需要用到一个类的全限定名:
public class HttpProviderConf {/*** 提供http访问的包*/private List<String> usePackage ;public List<String> getUsePackage() {return usePackage;}public void setUsePackage(List<String> usePackage) {this.usePackage = usePackage;}}
请求响应入参、出参
HttpRequest入参
public class HttpRequest {private String param ;//入参private String service ;//请求serviceprivate String method ;//请求方法public String getParam() {return param;}public void setParam(String param) {this.param = param;}public String getService() {return service;}public void setService(String service) {this.service = service;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}
}
其中param是用于存放真正调用dubbo服务时的入参,传入json在调用的时候解析成具体的参数对象。
service存放dubbo服务声明的interface API的包名。
method则是真正调用的方法名称。
HttpResponse 响应
public class HttpResponse implements Serializable{private static final long serialVersionUID = -6296842759601736401L; private boolean success;// 成功标志private String code;// 信息码private String description;// 描述public boolean isSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}
}
这里只是封装了常用的HTTP服务的响应数据。
暴露服务controller
@Controller
@RequestMapping("/dubboAPI")
public class DubboController implements ApplicationContextAware {private final static Logger logger = LoggerFactory.getLogger(DubboController.class);@Autowiredprivate HttpProviderConf httpProviderConf;// 缓存作用的mapprivate final Map<String, Class<?>> cacheMap = new HashMap<String, Class<?>>();protected ApplicationContext applicationContext;@ResponseBody@RequestMapping(value = "/{service}/{method}", method = RequestMethod.GET)public String api(HttpRequest httpRequest, HttpServletRequest request, @PathVariable String service,@PathVariable String method) {logger.info("ip:{}-httpRequest:{}");String invoke = invoke(httpRequest, service, method);logger.debug("callback :" + invoke);return invoke;}private String invoke(HttpRequest httpRequest, String service, String method) {httpRequest.setService(service);httpRequest.setMethod(method);HttpResponse response = new HttpResponse();logger.debug("input param:" + JSON.toJSONString(httpRequest));if (!CollectionUtils.isEmpty(httpProviderConf.getUsePackage())) {boolean isPac = false;for (String pac : httpProviderConf.getUsePackage()) {if (service.startsWith(pac)) {isPac = true;break;}}if (!isPac) {// 调用的是未经配置的包logger.error("service is not correct,service=" + service);response.setCode("2");response.setSuccess(false);response.setDescription("service is not correct,service=" + service);}}try {Class<?> serviceCla = cacheMap.get(service);if (serviceCla == null) {serviceCla = Class.forName(service);logger.debug("serviceCla:" + JSON.toJSONString(serviceCla));// 设置缓存cacheMap.put(service, serviceCla);}Method[] methods = serviceCla.getMethods();Method targetMethod = null;for (Method m : methods) {if (m.getName().equals(method)) {targetMethod = m;break;}}if (method == null) {logger.error("method is not correct,method=" + method);response.setCode("2");response.setSuccess(false);response.setDescription("method is not correct,method=" + method);}Object bean = this.applicationContext.getBean(serviceCla);Object result = null;Class<?>[] parameterTypes = targetMethod.getParameterTypes();if (parameterTypes.length == 0) {// 没有参数result = targetMethod.invoke(bean);} else if (parameterTypes.length == 1) {Object json = JSON.parseObject(httpRequest.getParam(), parameterTypes[0]);result = targetMethod.invoke(bean, json);} else {logger.error("Can only have one parameter");response.setSuccess(false);response.setCode("2");response.setDescription("Can only have one parameter");}return JSON.toJSONString(result);} catch (ClassNotFoundException e) {logger.error("class not found", e);response.setSuccess(false);response.setCode("2");response.setDescription("class not found");} catch (InvocationTargetException e) {logger.error("InvocationTargetException", e);response.setSuccess(false);response.setCode("2");response.setDescription("InvocationTargetException");} catch (IllegalAccessException e) {logger.error("IllegalAccessException", e);response.setSuccess(false);response.setCode("2");response.setDescription("IllegalAccessException");}return JSON.toJSONString(response);}/*** 获取IP* * @param request* @return*/private String getIP(HttpServletRequest request) {if (request == null)return null;String s = request.getHeader("X-Forwarded-For");if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("Proxy-Client-IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("WL-Proxy-Client-IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("HTTP_CLIENT_IP");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getHeader("HTTP_X_FORWARDED_FOR");}if (s == null || s.length() == 0 || "unknown".equalsIgnoreCase(s)) {s = request.getRemoteAddr();}if ("127.0.0.1".equals(s) || "0:0:0:0:0:0:0:1".equals(s))try {s = InetAddress.getLocalHost().getHostAddress();} catch (UnknownHostException unknownhostexception) {return "";}return s;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}
首先是定义了一个DubboController,并使用了SpringMVC的注解对外暴露HTTP服务。
实现了org.springframework.context.ApplicationContextAware类, 实现了setApplicationContext()方法用于初始化Spring上下文对象,在之后可以获取到容器里的相应对象。
核心的invoke()方法。
调用时:http://127.0.0.1:8080/dubbo-provider/dubboAPI/com.dubbo.service.IDubboService/getUser。
具体如上文的调用实例。先将com.dubbo.service.IDubboService、getUser赋值到httpRequest入参中。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!-- 定义了提供方应用信息,用于计算依赖关系。在dubbo-admin 或 dubbo-monitor 会显示这个名字,方便识别 --><dubbo:application name="admin-provider" owner="admin" organization="dubbox"/><!-- 使用zookeeper 注册中心暴露服务,注意要先开启 zookeeper --><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!-- 用dubbo协议在20880端口暴露服务 --><dubbo:protocol name="dubbo" port="20880"/><!-- 用dubbo 协议实现定义好的 api 接口 --><dubbo:service interface="com.dubbo.service.IDubboService" ref="dubboService" protocol="dubbo"/><dubbo:service interface="com.dubbo.service.IUserService" ref="userService" protocol="dubbo"/><!--dubbo服务暴露为http服务--><bean class="com.dubbo.http.conf.HttpProviderConf"><property name="usePackage"><list><!--需要暴露服务的接口包名,可多个--><value>com.dubbo.service</value></list></property></bean>
</beans>
其中的com.dubbo.service就是自己需要暴露的包名,可以多个。
- 接着在缓存map中取出反射获取到的接口类类型,如果获取不到则通过反射获取,并将值设置到缓存map中,这样不用每次都反射获取,可以节省系统开销(反射很耗系统资源)。
- 接着也是判断该接口中是否有传入的getUser方法。
- 取出该方法的参数列表,如果没有参数则直接调用。
- 如果有参数,判断个数。这里最多只运行一个参数。也就是说在真正的dubbo调用的时候只能传递一个BO类型,具体的参数列表可以写到BO中。因为如果有多个在进行json解析的时候是无法赋值到两个参数对象中去的。
- 之后进行调用,将调用返回的数据进行返回即可。
dubbo暴露出HTTP服务相关推荐
- dubbo k8s 服务发现_工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇
作者 | 张远征来源|阿里巴巴云原生公众号 导读:Dubbo 作为分布式微服务框架,众多公司在实践中基于 Dubbo 进行分布式系统架构.重启开源后,我们不仅看到 Dubbo 3.0 最新的 Road ...
- Dubbo 源码分析 - 服务引用
1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...
- Dubbo 源码分析 - 服务导出
1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可 ...
- 【DUBBO】——dubbo是什么以及使用dubbo 实现远程接口服务调用
1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...
- Dubbo的服务暴漏与服务发现源码详解
服务暴漏 如果配置需要刷新则根据配置优先级刷新服务配置 如果服务已经导出,则直接返回 是否异步导出(全局或者服务级别配置了异步,则需要异步导出服务) 服务暴漏入口DefaultModuleDeploy ...
- Dubbo:Spring Cloud 服务调用的新选择
无论是Dubbo,还是Spring Cloud,大家可能都不会感到陌生. 那什么是Dubbo Spring Cloud呢?使用Dubbo Spring Cloud可以实现什么目的?基于其实现的路由和负 ...
- Dubbo使用Zooker注册服务
一.安装配置Zooker 1.下载Zooker 在apache mirros上下载Zooker :https://mirror.bit.edu.cn/apache/zookeeper/,下载后解压到指 ...
- dubbo启动时检查服务
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true". 可以通过 che ...
- 基于Dubbo框架构建分布式服务(三)
我们将上面开发的服务提供方服务,部署到2个独立的节点上(192.168.14.1和10.10.4.125),然后可以通过Dubbo管理中心查看对应服务的状况,如图所示: 上图中可以看出,该服务有两个独 ...
- SpringBoot2.0 整合 Dubbo框架 ,实现RPC服务远程调用
一.Dubbo框架简介 1.框架依赖 图例说明: 1)图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层 ...
最新文章
- web.config中sessionState节点的配置方案
- php 报错乱码,thinkphp3 phpexcel 导出报错乱码清除ob
- 一个 .git 目录,领悟 Git 的强大!
- 淘宝从几百到千万级并发的十四次架构演进之路!
- 解析字符串,每8位将2进制转为16进制
- clion修改选中行的背景颜色
- (转)Android中尺寸单位杂谈
- 使用Eclipse和Open Liberty的Java EE 8上的Java 9
- Altium AD20如何选择重叠在下方的元件?如何对元件快速选择、选择区域内部、选择矩形接触到的对象
- SOTA集结,2020登顶关系抽取的3篇佳作
- A+B Problem(再升级)
- python指纹识别_指纹识别是目前最成熟的识别技术!Python能分分钟做出一个来!...
- 笔记本电脑怎么录制屏幕
- C语言中callback回调函数,C++回调函数(callback)的使用
- VBScript教程-第二章. 运行脚本
- Vue 单文件模板中覆盖引入库 CSS 样式
- 揭秘“爆款级”产品!看葡萄城活字格低代码平台是如何诞生的
- Dispatch I/O
- 「趣小面」寻融资:前景美好,“钱”景难说
- 如何学好 java?