这篇文章主要介绍“怎么用Springboot和Netty实现rpc”,在日常操作中,相信很多人在怎么用Springboot和Netty实现rpc问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用Springboot和Netty实现rpc”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
项目整体结构如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.48.Final</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
这里重点关注一下 RequestModel 和 ResponseModel 两个消息体类,
@Data
@AllArgsConstructor
public class RequestModel {
private String requestId;
private String serviceName;
private String methodName;
private Class[] paramTypes;
private Object[] paramValues;
}
@Data
@AllArgsConstructor
public class ResponseModel {
private String responseId;
private String serviceName;
private String methodName;
private String code;
private String data;
}
用于服务端和客户端的数据传输;再者就是关注 ServerChannelInboundHandler 中的 channelRead0() 报文解码处理;
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
StringBuilder sb = null;
RequestModel result = null;
try {
// 报文解析处理
sb = new StringBuilder();
result = JSON.parseObject(msg, RequestModel.class);
requestId = result.getRequestId();
String serviceName = result.getServiceName();
String methodName = result.getMethodName();
Class[] paramType = result.getParamTypes();
Object[] paramValue = result.getParamValues();
System.out.println(serviceName + " " + methodName);
String substring = serviceName.substring(serviceName.lastIndexOf(".") + 1);
String s = substring.substring(0, 1).toLowerCase() + substring.substring(1);
Object serviceObject = applicationContext.getBean(s);
Method method = Class.forName(serviceName).getMethod(methodName, paramType);
Object returnValue = method.invoke(serviceObject, paramValue);
ResponseModel responseModel = new ResponseModel(requestId,serviceName,methodName,"200",JSON.toJSONString(returnValue));
sb.append(JSON.toJSONString(responseModel));
sb.append("\n");
System.out.println(sb.toString());
ctx.writeAndFlush(sb);
} catch (Exception e) {
ResponseModel responseModel = new ResponseModel(requestId,"","","500",e.getMessage());
String errorCode = JSON.toJSONString(responseModel)+"\n";
log.error(errorCode);
ctx.writeAndFlush(errorCode);
log.error("报文解析失败: " + e.getMessage());
}
}
客户端的模块代码如下;
这里重点关注的是 ClientHandler 类中 channelRead0() 方法的处理
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("收到服务端消息: " + msg);
ResponseModel responseModel = JSON.parseObject(msg,ResponseModel.class);
String responseId = responseModel.getResponseId();
Promise promise = LocalPromise.promiseMap.remove(responseId);
if(promise != null){
String code = responseModel.getCode();
if(code.equals("200")){
promise.setSuccess(responseModel.getData());
}else{
promise.setFailure(new RuntimeException(responseModel.getData()));
}
}
}
和 AppStart 类中获取获取服务的处理;
private <T> T getProxyService(Class<T> serviceClass) {
Object service = Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class[]{serviceClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Channel channel = NettyClient.getChannel(host, port);
RequestModel requestModel = new RequestModel("100001", method.getDeclaringClass().getName(), method.getName(), method.getParameterTypes(), args);
channel.writeAndFlush(JSON.toJSONString(requestModel) + "\n");
Promise promise = new DefaultPromise(channel.eventLoop());
LocalPromise.promiseMap.put(requestModel.getRequestId(), promise);
System.out.println(LocalPromise.promiseMap+">>>>>>>>>>>>");
promise.await();
if (promise.isSuccess()) {
Class<?> returnType = method.getReturnType();
return JSON.toJavaObject(JSON.parseObject(promise.getNow()+""),returnType);
} else {
System.out.println(promise.cause());
return promise.cause();
}
}
});
return (T) service;
}
测试结果:
到此,关于“怎么用Springboot和Netty实现rpc”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。