前言:现在RPC成熟的框架已经很多了,比喻Motan和Dubbo,但是今天我这里提供一种基于Rest服务的Rpc。和上一篇连着的http://www.cnblogs.com/LipeiNet/p/5856414.html

1:原理

首先我们要建立一个Rest服务,如果其他应用程序想要获取这个服务的资源就只需要一个URI就可以了。但是由于内部程序的调用我们在通过URI获取json然后在自己处理很不方便,也不是很合适,那么我们就需要利用一个中间层,把访问Rest服务返回的资源重新包装,然后其他工程只需要调用这个rpc工程即可。如下图

2:实现Rest服务

2.1:定义一个用于返回给消费者的实现对象(自己约定的)

public class ResponseBean implements Serializable{private static final long serialVersionUID = -1L;public static final int SUCCESS = 10;public static final int FAILURE = 20;public static final int LOCKED = 30;public static final int EXCEPTION = 40;private int returnCode;//返回给消费者的编码(0表示调用成功,1表示调用失败)private String returnMsg;//返回给消费者错误信息private int dataCount;//用于返回int类型private String returnData;//用户返回jsonprivate Object returnObject;//用于返回对象public ResponseBean() {}public ResponseBean(int returnCode, String returnMsg) {this.returnCode = returnCode;this.returnMsg = returnMsg;}public Object getReturnObject() {return this.returnObject;}public void setReturnObject(Object returnObject) {this.returnObject = returnObject;}public int getDataCount() {return this.dataCount;}public void setDataCount(int dataCount) {this.dataCount = dataCount;}public String getReturnData() {return this.returnData;}public void setReturnData(String returnData) {this.returnData = returnData;}public int getReturnCode() {return this.returnCode;}public void setReturnCode(int returnCode) {this.returnCode = returnCode;}public String getReturnMsg() {return this.returnMsg;}public void setReturnMsg(String returnMsg) {this.returnMsg = returnMsg;}
}

2.2:定一个供外部请求的ApiService

public interface ApiService {String getToken();ResponseBean add(String reqJson);
}

public class ApiServiceImpl implements ApiService {private static final Log log = LogFactory.getLog(ApiServiceImpl.class);@Autowiredprivate UserDao userDao;private String token;//供调用rpc校验使用public String getToken() {return token;}public ResponseBean add(String reqJson) {ResponseBean responseBean = new ResponseBean(ResponseBean.SUCCESS, "调用成功");try {Map map = JsonUtil.g.fromJson(reqJson, HashMap.class);String username = map.get("username").toString();String password = map.get("password").toString();String realname = map.get("realname").toString();Long userroleid =Double.valueOf(map.get("userroleid").toString()).longValue() ;UserBean userBean = new UserBean();userBean.setCreatedate(new Date());userBean.setPassword(password);userBean.setUserroleid(userroleid);userBean.setRealname(realname);userBean.setUsername(username);int count = userDao.add(userBean);responseBean.setReturnData(JsonUtil.g.toJson(count));responseBean.setReturnCode(10);} catch (Exception e) {log.error(e.getStackTrace());responseBean.setReturnCode(11);responseBean.setReturnMsg("服务器异常");}return responseBean;}public void setToken(String token) {this.token = token;//用于设置token(用来验证消费者的token是否是服务器的token)}
}

2.3:定义http请求的入口,需要3个参数token(进行安全认证)、m(请求方法名)、reqJson(请求的参数)

@Controller
@RequestMapping(value = "/api")
public class ApiController {private static final Log log = LogFactory.getLog(ApiController.class);@Autowiredprivate ApiService apiService;/*** 系统对外公开调用方法** @param m       接口方法名* @param reqJson 请求参数* @param token   请求token* @return*/@RequestMapping(value = "/exec", method = RequestMethod.POST)@ResponseBodypublic Object exec(@RequestParam(value = "m", required = true) String m,@RequestParam(value = "reqJson", required = true) String reqJson,@RequestParam(value = "token", required = true) String token) {log.info(String.format("m=%s,reqJson=%s,token=%s", m, reqJson, token));Class c = apiService.getClass();Method method = null;ResponseBean responseBean = null;if (!token.equals(apiService.getToken())) {log.error("token校验失败,token=" + token);responseBean = new ResponseBean(ResponseBean.FAILURE, "校验失败");return responseBean;}try {method = c.getMethod(m, String.class);//利用反射找到对应的方法} catch (Exception e) {log.error("m参数错误,m=" + m + ";req=" + reqJson, e);responseBean = new ResponseBean(ResponseBean.FAILURE, "m参数错误m=" + m);return responseBean;}if (StringUtils.isEmpty(reqJson)) {log.error("reqJson为空");responseBean = new ResponseBean(ResponseBean.FAILURE, "reqJson为空");return responseBean;}try {Object json = method.invoke(apiService, reqJson);return json;} catch (Exception e) {log.error("处理异常,m=" + m + ";req=" + reqJson, e);responseBean = new ResponseBean(ResponseBean.FAILURE, "服务器处理异常");return responseBean;}}
}

通过上面我们就实现了一个供消费者调用的rest服务。

3:RPC对rest服务进行包装

3.1:定义消费者需要的webService

public interface WebService {ResponseBean add(UserBean userBean);
}

实现webService

public class WebserviceImpl implements WebService {private final static Log log = LogFactory.getLog(WebserviceImpl.class);private String url;//供消费者设置的url地址private String token;//供消费者设置的urlpublic void setUrl(String url) {this.url = url;}public void setToken(String token) {this.token = token;}@Overridepublic ResponseBean add(UserBean userBean) {Map<String, String> map = new HashMap();ResponseBean rb = null;map.put("token", token);map.put("reqJson", JsonUtil.g.toJson(userBean));String reqUrl = url + "?m=add";//在这里进行设置你需要访问哪个方法log.debug(reqUrl);try {String str = HttpClientUtil.executeHttpRequestUTF(reqUrl, map);//访问资源获取返回的jsonlog.debug("add return data:" + str);rb = JsonUtil.g.fromJson(str, ResponseBean.class);//对json进行转换log.debug("getPromInfo return Regions data" + reqUrl);return rb;} catch (Exception e) {rb = new ResponseBean();rb.setReturnObject(e);log.debug(e.getStackTrace());return rb;}}
}

然后对rpc进行打包发布,其他应用程序就可以直接使用了。

4:配置

在applicationconfig中加入

<mvc:annotation-driven/><mvc:default-servlet-handler /><mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean否则会出现异常

<bean id="ApiService" class="com.lp.rpc.impl.ApiServiceImpl">
    <property name="token" value="41729ff3-3406-4fc5-aeca-04f98892999b"></property></bean>
消费者配置:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="webService" class="com.lp.rpc.impl.WebserviceImpl"><property name="url" value="http://192.168.0.101:8088/api/exec"></property><property name="token" value="41729ff3-3406-4fc5-aeca-04f98892999b"></property>
</bean>
</beans>

5:开启一个项目把rpc项目引进调用

public class AppMain {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("application-config.xml");WebService webService = (WebService) context.getBean("webService");UserBean userBean = new UserBean();userBean.setUsername("lisi");userBean.setPassword("123456");userBean.setRealname("李四");userBean.setUserroleid(2);userBean.setCreatedate(new Date());ResponseBean result = webService.add(userBean);if (StringUtils.equals(result.getReturnData().toString(),"1")){System.out.print("添加成功");}}
}

6:总结

以上级别能完成不同项目之间的调用了

优点:简单上手快,可以自己控制,效率也可以。

缺点:安全性低,需要维护url,有时候别人服务反复开启时候会出现调用不到的情况。

源码地址

转载于:https://www.cnblogs.com/LipeiNet/p/5862962.html

基于Rest服务实现的RPC相关推荐

  1. 基于面向服务体系架构(SOA)和面向资源体系架构(ROA)的业务组件模型

    引言 在<面向服务体系架构(SOA)和业务组件(BC)的思考>(以下简称< SOA 和 BC >)一文中介绍了基于面向服务体系架构(SOA)的组件模型,本文按照"分离 ...

  2. 基于Axis服务端的webservice客户端实现

    之前开发webservice客户端的时候遇到一个使用Axis2开发接口的厂家,查资料把Axis1和Axis2客户端的开发方式总结如下: 基于Axis1服务端的客户端实现: /*** 使用Axis Ca ...

  3. 【2017年第3期】交通大数据:一种基于微服务的敏捷处理架构设计

    杜圣东, 杨燕, 滕飞 西南交通大学信息科学与技术学院,四川 成都 610031 摘要:面对智慧交通广泛的大数据应用场景和技术需求,一般大数据系统难以适应多种处理情况并做出快速响应.针对这一问题,首次 ...

  4. 基于Protobuf的分布式高性能RPC框架——Navi-Pbrpc

    基于Protobuf的分布式高性能RPC框架--Navi-Pbrpc 二月 8, 2016 1 简介 Navi-pbrpc框架是一个高性能的远程调用RPC框架,使用netty4技术提供非阻塞.异步.全 ...

  5. 微服务架构之 —— RPC框架

    RPC简介 RPC是什么 Remote Procedure Call,远程过程调用. 首先来说本地方法调用,假设在main方法中调用一个本地的方法multiply(同一个进程内的方法调用).无非是做了 ...

  6. 亿级用户基于微服务的互联网系统稳定性~

    互联网系统为大量的C端用户提供服务,如果隔三差五的出问题宕机,会严重影响用户体验,甚至导致用户流失.所以稳定性对互联网系统非常重要!接下来,我根据自己的实际经验来聊聊基于微服务的互联网系统的稳定性. ...

  7. 基于微服务的电商系统架构

    分层 微服务设计 微服务微内核 基于微服务的电商系统架构 转载于:https://www.cnblogs.com/davidwang456/articles/9221369.html

  8. 【REST】基于RESTful服务端的客户端实现(HttpClient、RestTemplate、HttpURLConnection)

    最近一直在做针对webservice的接口协议对接,总结了一下基于restful服务端的客户端的实现方式,有以下三种: HTTPClient RestTemplate HttpURLConnectio ...

  9. eShopOnContainers 是一个基于微服务的.NET Core示例框架

    找到一个好的示例框架很难,但不是不可能.大多数是小型Todo风格的应用程序,通常基于SimpleCRUD.值得庆幸的是,Microsoft已经为eShopOnContainers创建了一个基于微服务的 ...

最新文章

  1. 不做“浮冰”,深挖AI技术和场景
  2. MediaSource 缓存
  3. Android借助Application重写App的Crash(简易版)
  4. oracle constraint_type 问题
  5. MySQL InnoDB Memcached Plugin在Oray公司的实践
  6. sql语句中使用函数会耗费性能吗_挽救数据库性能的 30 条黄金法则 | 原力计划...
  7. python 相对路径报错_小白学 Python(18):基础文件操作
  8. 0基础学python要多久-零基础学习python,要多久才可以学好并且找到工作?
  9. Santander Customer Transaction Prediction(2)
  10. 1219v网卡驱动+linux,黑苹果Intel板载网卡驱动-IntelMausiEthernet.kext下载 V2.5.0d0-PC6苹果网...
  11. 计算机实数表示法---浮点数(一)
  12. Etcher 改变一个选项,让所有盘符都乖乖出来
  13. AutoCAD参照编辑期间不允许使用 SAVE 命令怎么办
  14. 多链钱包鼻祖bitpay 10.0.1最新版官方版下载和使用方法
  15. 8.0服务器维护时间,魔兽世界8.0开服第一天遇紧急维护?网友:叫逆水寒还服务器...
  16. PHP2cgoto加密解密
  17. 基于8086单片机的PWM调光(带汇编)
  18. c语言打开文件失败,C / c ++文件打开读取和写入失败的几个常见错误.
  19. 基于ZigBee的智能家居安全监控系统设计
  20. Docker login私有仓库报错:x509: cannot validate certificate for because it doesn‘t contain any IP SANs

热门文章

  1. Crontab作业时间设置
  2. C#将DLL嵌入到exe当中
  3. Ansible-playbook 拾遗
  4. php面试题之一——PHP核心技术(高级部分)
  5. ISA Server 2004 企业 IT 常见应用速查
  6. 创造黑科技,守护新未来 | 360公司2019年春季校园招聘正式启动!
  7. html5调用系统声音1s响一次_HTML5 怎么给网页加屏幕点击声音。
  8. Asp.net五大对象
  9. window.opener.location.reload() and href()的区别
  10. Leetcode-二叉搜索树最近公共祖先