博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Rest服务实现的RPC
阅读量:5107 次
发布时间:2019-06-13

本文共 7549 字,大约阅读时间需要 25 分钟。

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

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;//用户返回json    private 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);    @Autowired    private 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);    @Autowired    private ApiService apiService;    /**     * 系统对外公开调用方法     *     * @param m       接口方法名     * @param reqJson 请求参数     * @param token   请求token     * @return     */    @RequestMapping(value = "/exec", method = RequestMethod.POST)    @ResponseBody    public 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;//供消费者设置的url    public void setUrl(String url) {        this.url = url;    }    public void setToken(String token) {        this.token = token;    }    @Override    public ResponseBean add(UserBean userBean) {        Map
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);//访问资源获取返回的json log.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中加入

会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean否则会出现异常
消费者配置:

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

你可能感兴趣的文章
好莱坞十大导演排名及其代表作,你看过多少?
查看>>
Loj #139
查看>>
StringBuffer是字符串缓冲区
查看>>
hihocoder1187 Divisors
查看>>
Azure 托管镜像和非托管镜像对比
查看>>
js window.open 参数设置
查看>>
032. asp.netWeb用户控件之一初识用户控件并为其自定义属性
查看>>
Ubuntu下安装MySQL及简单操作
查看>>
前端监控
查看>>
clipboard.js使用方法
查看>>
移动开发平台-应用之星app制作教程
查看>>
leetcode 459. 重复的子字符串(Repeated Substring Pattern)
查看>>
伪类与超链接
查看>>
centos 7 redis-4.0.11 主从
查看>>
博弈论 从懵逼到入门 详解
查看>>
永远的动漫,梦想在,就有远方
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
慵懒中长大的人,只会挨生活留下的耳光
查看>>
"远程桌面连接--“发生身份验证错误。要求的函数不受支持
查看>>
【BZOJ1565】 植物大战僵尸
查看>>