架构师日记——手写利用HTTP协议远程模块调用
来源:互联网 发布:阿里云注册会员名 编辑:程序博客网 时间:2024/06/18 15:32
远程模块调用比较流行的协议有RPC协议、RMI协议和HTTP协议
本篇博客教大家如何使用HTTP协议试远程模块的调用
1.定架构
总体架构如下
接下来我一个一个讲解他们的作用
2.ModuleModel
这个类的作用是记录不同uuid对应的module的信息,包括远端ip和url等,代码如下
/** * 调用远端方法的协议类 */public class InteractiveModel { /** * 操作类型 */ private String opeType; /** * 操作参数 */ private Map<String,Object>map=new HashMap<String ,Object>(); public InteractiveModel(String opeType, Map<String, Object> map) { this.opeType = opeType; this.map = map; } public InteractiveModel() { } public String getOpeType() { return opeType; } public void setOpeType(String opeType) { this.opeType = opeType; } public Map<String, Object> getMap() { return map; } public void setMap(Map<String, Object> map) { this.map = map; }}
3.InteractiveModel
这个类可以说是调用方法的协议类,它包含操作类型和操作参数,代码如下
/** * 调用远端方法的协议类 */public class InteractiveModel { /** * 操作类型 */ private String opeType; /** * 操作参数 */ private Map<String,Object>map=new HashMap<String ,Object>(); public InteractiveModel(String opeType, Map<String, Object> map) { this.opeType = opeType; this.map = map; } public InteractiveModel() { } public String getOpeType() { return opeType; } public void setOpeType(String opeType) { this.opeType = opeType; } public Map<String, Object> getMap() { return map; } public void setMap(Map<String, Object> map) { this.map = map; }}
4.InteractiveCallHelper
InteractiveCallHelper是调用远端方法的发起者,这个类可以独立于这个项目,为了方便我就我不把它单独提取出来了,既可以返回string也可以返还一个指定类型的对象。这个类的作用主要有以下几个
1.根据不同的uuid去获取到远端方法的url
2.实现参数中非法字符的转换
3.组合url和参数
代码如下
/** * 调用远端方法的发起者 */public class InteractiveCallHelper { /** * * @param moduleId 模块Id * @param opeType 需要调用的具体的业务操作类型 * @param mapParams 调用所需要传递的参数 * @return 服务端返回的Json数据 */ public String call(String moduleId, String opeType, Map<String,Object>mapParams){ //1.根据moduleId去获取到该模块部署的信息,理论上要根据moduleId去设置,这里写死 ModuleModel moduleModel=new ModuleModel(); moduleModel.setDeployIP("localhost"); moduleModel.setDeployPort("8080"); moduleModel.setIntereractiveUrl("/goods/call"); //2.准备要传递的数据,把Map转换为JSON String paramStr= JSON.toJSONString(mapParams); //因为#在url里有特殊含义,所以将#替换为* paramStr=paramStr.replace("#","*"); //3.拼接一个远程调用的URL String urlStr="http://"+ moduleModel.getDeployIP()+":"+moduleModel.getDeployPort()+moduleModel.getIntereractiveUrl() +"?jsonParam={opeType:"+opeType+",map:"+paramStr+"}"; //4.使用URL进行远程调用,流式操作 BufferedReader in =null; String retJson=""; try { URL url=new URL(urlStr); URLConnection urlConnection=url.openConnection(); // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( urlConnection.getInputStream())); String line; while ((line = in.readLine()) != null) { retJson += line; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } return retJson; } /** * * @param moduleId 模块Id * @param opeType 需要调用的具体的业务操作类型 * @param mapParams 调用所需要传递的参数 * @param cls 需要转的类型 * @return 服务器返回的对象 */ public <T>T call(String moduleId, String opeType, Map<String,Object>mapParams,Class<T> cls){ String json=call(moduleId,opeType,mapParams); return JSON.parseObject(json,cls); } /** * 测试方法 * @param args */ public static void main(String[]args){ InteractiveCallHelper interactiveCallHelper=new InteractiveCallHelper(); Map<String,Object>map=new HashMap<String,Object>(); String str=interactiveCallHelper.call("goods","1",map); System.out.println(str); }}
5.InteractiveBaseController
这个类是远端被调用方法的基类,这个类是个抽象类,任何远端可被调用的controller都要继承它,继承call方法和实现它的doCall方法,代码如下
/** * 远端被调用方法的基类 */public abstract class InteractiveBaseController { /** * 解析参数 * @param jsonParam * @return */ @RequestMapping("/call") @ResponseBody public Object call(String jsonParam){ if (jsonParam!=null&&jsonParam.contains("*")){ //将*变回# jsonParam=jsonParam.replace("*","#"); } InteractiveModel interactiveModel= JSON.parseObject(jsonParam,InteractiveModel.class); Object ret=doCall(interactiveModel.getOpeType(),interactiveModel.getMap()); return ret; } protected abstract Object doCall(String opetype, Map<String,Object>map);}
6.GoodsModel
这个类是JavaBean,和数据库对应的实体类,可自由替换,代码如下
/** * 要操作的实体类 */public class GoodsModel { private String uuid; private String name; public GoodsModel(String uuid, String name) { this.uuid = uuid; this.name = name; } public GoodsModel() { } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "GoodsModel{" + "uuid='" + uuid + '\'' + ", name='" + name + '\'' + '}'; }}
7.GoodsController
远程方法示例,根据不同opetype执行不同的操作,如opetype为1时往数据库插入一个实体,代码如下
@RestController@RequestMapping(value = "goods")public class GoodsController extends InteractiveBaseController{ @Override protected Object doCall(String opetype, Map<String, Object> map) { //执行不同的操作 if ("1".equals(opetype)){ }else if ("2".equals(opetype)){ } GoodsModel goodsModel=new GoodsModel(); goodsModel.setName("abc"); goodsModel.setUuid("132132"); System.out.println("call"); return goodsModel; }}
一个利用HTTP远程调用模块的Demo就写好了,但HTTP协议效率较低,所以在日常开发中,我们常常使用RPC协议实现远程调用模块,比如使用著名的Dubbo框架
完整代码已上传到github:https://github.com/jkgeekJack/UseRemoteInvoker
阅读全文
0 0
- 架构师日记——手写利用HTTP协议远程模块调用
- 架构师日记——Nginx的HTTP模块配置
- 架构师日记——Nginx的Rewrite模块配置
- RPC——远程过程调用协议
- RPC——远程过程调用协议
- http协议学习日记
- 架构师日记——Nginx简介
- 架构师日记——ActiveMQ简介
- Go日记——手写一个资源池
- 手写日记
- transmission远程调用协议
- 远程过程调用协议
- Http 远程调用
- Http Post远程调用
- 安卓日记——利用http上传文件到服务器
- 《Spring技术内幕》学习笔记17——Spring HTTP调用器实现远程调用
- 《Spring技术内幕》学习笔记17——Spring HTTP调用器实现远程调用
- 《Spring技术内幕》学习笔记17——Spring HTTP调用器实现远程调用
- [Shell]使用find命令查找最近修改过的文件
- build.gradle导入com.android.support:percent 的依赖错误
- 虚拟机 Centos 7安装Zookeeper集群注意事项
- Mybatis Interceptor 拦截器原理 源码分析
- Android使用XML文件绘图(Shape,Layer,Selector)
- 架构师日记——手写利用HTTP协议远程模块调用
- io流
- 数据分析及机器学习环境配置(docker极简入门指南)
- editPlus使用技巧
- 饿了么项目---1、vue-cli快速构建项目(包括兼容老项目时需引入bootstrap、jquery的方法)
- 引导页面
- hdu4513_吉哥系列故事——完美队形II
- 人工智能
- 写在前面 程序员 迷茫且坚定地向前走着(一)