Netty实现RPC服务器之最终章Netty实现RPC服务器之最终章 前言 本篇是用Netty实现一个RPC中间件的最后
Netty实现RPC服务器之最终章
前言
本篇在之前三篇的介绍上进行整合介绍,并从落地使用方面对该RPC组件进行探讨。
愿我们在技术的浩瀚中游刃有余。
项目介绍
此处准备分模块进行编写,便于后期的SPI模式下的依赖构建。
执行流程
核心流程图
使用步骤
服务端
@RpcServer
标记在service
端,对service的实现类进行标记,以表示该类提供远程调用。
示例如下:
@RpcServer
public class HelloServiceImpl implements HelloService{
@Override
public JsonObject sayHello(String name) {
// return "XiaoSheng say 你好, " + name;
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("result", "XiaoSheng say 你好, " + name);
return jsonObject;
}
@Override
public JsonObject sayHello2(String name) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("HelloName", name);
return jsonObject;
}
}
@RpcServerScan
该注解存在一个value值,value值表示限定了服务扫描的路径。将从哪个包中将服务添加到rpc容器中。
如果不设置value值,将默认从主类的路径进行扫描加载服务类。
@EnableRpcServer
表示开启RpcServer
服务,如果需要使用该组件,在启动类或者配置类中进行添加,默认为开启服务。
注册逻辑
在RpcServiceManager类中,对服务类进行注入,具体逻辑如下:
/**
* 自动扫描@RpcServer注解 注册服务
*/
public void autoRegistry() {
// 获取启动类路径
String mainClassPath = PackageScanUtils.getStackTrace();
Class<?> mainClass;
log.info("mainClassPath:" + mainClassPath);
try {
mainClass = Class.forName(mainClassPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("启动类未找到!");
}
log.info("mainClass:" + mainClass);
if (!mainClass.isAnnotationPresent(EnableRpcServer.class)) {
throw new RuntimeException("启动类缺少@EnableRpcServer注解!");
} else {
if (!mainClass.getAnnotation(EnableRpcServer.class).enable()) {
throw new RuntimeException("请开启@EnableRpcServer注解");
}
}
String annotationPath = mainClass.getAnnotation(RpcServerScan.class).value();
// 如果注解的路径为空,则默认从main父路径包下进行查找
if(null == annotationPath || "".equals(annotationPath)) {
annotationPath = mainClassPath.substring(0, mainClassPath.lastIndexOf("."));
}
// 获取所有类的set集合
Set<Class<?>> classSet = PackageScanUtils.getClasses(annotationPath);
for (Class<?> c : classSet) {
// 只注册含有@RpcServer注解的类
if (c.isAnnotationPresent(RpcServer.class)) {
String serverNameValue = c.getAnnotation(RpcServer.class).name();
Object object;
try {
object = c.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
log.error("创建对象" + c + "发生错误");
continue;
}
// 若注解值为空,则使用类名
if ("".equals(serverNameValue)) {
// 将简单类注入到服务中
addServer(c.getSimpleName(), object);
} else {
addServer(serverNameValue, object);
}
}
}
}
客户端
@RpcClient
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RpcClient {
// 服务名 (服务类的类名)
public String serverName() default "";
// 调用的远程方法名
public String methodName() default "";
// 调用的远程返回类型
public Class returnType();
}
具体使用方案如下:
/**
* @author XiaoSheng
* @date 2024/8/22 下午5:27
*/
@Service
public class HelloService {
@RpcClient(serverName = "HelloServiceImpl", methodName = "sayHello", returnType = String.class)
// @RpcClient(returnType = String.class)
public String sayHello(String name){return null;}
@RpcClient(serverName = "HelloServiceImpl", returnType = JsonObject.class)
public String sayHello2(String name){return null;}
}
通过在服务端内创建对应的方法,并在注解内填写对应的信息,后续客户端其他类就可以直接通过调用该类的方法获取到对应的值,目前暂时只能返回String
对象的值。后续会进行修改完善。
最后
以上就是使用Netty再利用反射,实现了RPC组件,源代码开放给大家,在文章开头即可获取,最后希望大家在技术的道路上行稳致远,精益求精,愿大家在技术的浩瀚中游刃有余。
转载自:https://juejin.cn/post/7412647317238759458