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服务相关推荐

  1. dubbo k8s 服务发现_工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇

    作者 | 张远征来源|阿里巴巴云原生公众号 导读:Dubbo 作为分布式微服务框架,众多公司在实践中基于 Dubbo 进行分布式系统架构.重启开源后,我们不仅看到 Dubbo 3.0 最新的 Road ...

  2. Dubbo 源码分析 - 服务引用

    1. 简介 在上一篇文章中,我详细的分析了服务导出的原理.本篇文章我们趁热打铁,继续分析服务引用的原理.在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直联的方式引用服务,第二种 ...

  3. Dubbo 源码分析 - 服务导出

    1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可 ...

  4. 【DUBBO】——dubbo是什么以及使用dubbo 实现远程接口服务调用

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  5. Dubbo的服务暴漏与服务发现源码详解

    服务暴漏 如果配置需要刷新则根据配置优先级刷新服务配置 如果服务已经导出,则直接返回 是否异步导出(全局或者服务级别配置了异步,则需要异步导出服务) 服务暴漏入口DefaultModuleDeploy ...

  6. Dubbo:Spring Cloud 服务调用的新选择

    无论是Dubbo,还是Spring Cloud,大家可能都不会感到陌生. 那什么是Dubbo Spring Cloud呢?使用Dubbo Spring Cloud可以实现什么目的?基于其实现的路由和负 ...

  7. Dubbo使用Zooker注册服务

    一.安装配置Zooker 1.下载Zooker 在apache mirros上下载Zooker :https://mirror.bit.edu.cn/apache/zookeeper/,下载后解压到指 ...

  8. dubbo启动时检查服务

    Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true". 可以通过 che ...

  9. 基于Dubbo框架构建分布式服务(三)

    我们将上面开发的服务提供方服务,部署到2个独立的节点上(192.168.14.1和10.10.4.125),然后可以通过Dubbo管理中心查看对应服务的状况,如图所示: 上图中可以看出,该服务有两个独 ...

  10. SpringBoot2.0 整合 Dubbo框架 ,实现RPC服务远程调用

    一.Dubbo框架简介 1.框架依赖 图例说明: 1)图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层 ...

最新文章

  1. web.config中sessionState节点的配置方案
  2. php 报错乱码,thinkphp3 phpexcel 导出报错乱码清除ob
  3. 一个 .git 目录,领悟 Git 的强大!
  4. 淘宝从几百到千万级并发的十四次架构演进之路!
  5. 解析字符串,每8位将2进制转为16进制
  6. clion修改选中行的背景颜色
  7. (转)Android中尺寸单位杂谈
  8. 使用Eclipse和Open Liberty的Java EE 8上的Java 9
  9. Altium AD20如何选择重叠在下方的元件?如何对元件快速选择、选择区域内部、选择矩形接触到的对象
  10. SOTA集结,2020登顶关系抽取的3篇佳作
  11. A+B Problem(再升级)
  12. python指纹识别_指纹识别是目前最成熟的识别技术!Python能分分钟做出一个来!...
  13. 笔记本电脑怎么录制屏幕
  14. C语言中callback回调函数,C++回调函数(callback)的使用
  15. VBScript教程-第二章. 运行脚本
  16. Vue 单文件模板中覆盖引入库 CSS 样式
  17. 揭秘“爆款级”产品!看葡萄城活字格低代码平台是如何诞生的
  18. Dispatch I/O
  19. 「趣小面」寻融资:前景美好,“钱”景难说
  20. 如何学好 java?

热门文章

  1. 证件照怎么制作?怎样自己在线制作2寸照片?
  2. 宽带通云解析结合用友致远A6使用方法
  3. 研究了1天的ckfinder记录
  4. C# 16进制与2进制互转
  5. 【信息系统项目管理师】案例分析记忆题
  6. 我的编程之路点滴记录(二)
  7. linux命令中ll和ls的区别
  8. linux根文件系统与内核合二为一
  9. win10计算机禁用用户账户控制,win10用户账户控制怎么关闭_用户账户控制如何解除win10-win7之家...
  10. filco的pin码_Filco圣手二代双模蓝牙机械键盘连接方法