首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于Netty实现的简单RPC调用

基于Netty实现的简单RPC调用

作者头像
用户1215919
发布于 2021-12-28 04:43:27
发布于 2021-12-28 04:43:27
41500
代码可运行
举报
文章被收录于专栏:大大的微笑大大的微笑
运行总次数:0
代码可运行

模块

rpc-api

rpc-consumer

rpc-provider

依赖:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>4.1.25.Final</version>
 </dependency>
rpc-api代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 接口, consumer和provider分别添加api的依赖
public interface ISayHelloService {
    String say(String name);
}

// 请求参数封装
public class Request{
     private String methodName; // 方法名
    private String className;  // 全类名
    private Object[] values; // 实参列表
}
rpc-provider代码:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Server {
    private void start() throws InterruptedException {
       // 初始化
        ServerHandler h = new ServerHandler();
        h.init();
        
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.channel(NioServerSocketChannel.class)
                    .group(boosGroup, workGroup)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel sc) throws Exception {
                            sc.pipeline()
                                    .addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4,
                                            0, 4))
                                    .addLast(new LengthFieldPrepender(4))
                                    .addLast("encoder", new ObjectEncoder())
                                    .addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))
                                    .addLast(h);
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 10)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture future = bootstrap.bind(8080).sync();
            future.channel()
                    .closeFuture()
                    .sync();
            System.out.println("server running, listener port : 8080 !");
        } finally {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        try {
            new Server().start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
   // 具体业务处理
    
    public class ServerHandler extends ChannelInboundHandlerAdapter {
    private static String bashScanPackage = "com.data.service.impl";
    private ClassLoader classLoader = this.getClass().getClassLoader();
    private static final Map<String, Mapping> SERVICES = new HashMap<>();


    /**
     * 初始化
     *
     * @throws ClassNotFoundException
     */
    public void init() {
        URL url = classLoader.getResource(bashScanPackage.replaceAll("\\.", "/"));
        String filePath = url.getFile();
        File file = new File(filePath);
        for (String s : file.list()) {
            s = s.substring(0, s.indexOf("."));
            Class clazz = null;
            try {
                clazz = Class.forName(bashScanPackage + "." + s);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            Method[] methods = clazz.getDeclaredMethods();
            String interfaceName = clazz.getInterfaces()[0].getName();
            for (Method m : methods) {
                Mapping mapping = new Mapping();
                mapping.setMethod(m);
                mapping.setParameters(m.getParameterTypes());
                try {
                    mapping.setTarget(clazz.newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                SERVICES.putIfAbsent(interfaceName + "." + m.getName(), mapping);
            }

        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Request request = (Request) msg;
        Object result;
        String key = request.getClassName() + "." + request.getMethodName();
        if (!SERVICES.containsKey(key)) {
            return;
        }
        Mapping clazz = SERVICES.get(key);
        result = clazz.getMethod().invoke(clazz.getTarget(), request.getValues());
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
}

// 业务提供方封装的参数
public class Mapping {
    private Object target;
    private Method method;
    private Class[] parameters;
}
rpc-consumer代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 动态代理类
public class ProxyHandler {
    public static <T> T create(Class<?> clazz) {
        MethodProxy proxy = new MethodProxy(clazz);
        Class<?>[] interfaces = clazz.isInterface() ?
                new Class[]{clazz} :
                clazz.getInterfaces();
        T result = (T) Proxy.newProxyInstance(clazz.getClassLoader(), interfaces, proxy);
        return result;
    }

    private static class MethodProxy implements InvocationHandler {
        private Class<?> clazz;

        public MethodProxy(Class<?> clazz) {
            this.clazz = clazz;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return invoke(method, args);
        }

        public Object invoke(Method method, Object[] args) {

            Request msg = new Request();
            msg.setClassName(this.clazz.getName());
            msg.setMethodName(method.getName());
            msg.setValues(args);
            msg.setParameters(method.getParameterTypes());
            EventLoopGroup group = new NioEventLoopGroup();
            RPCBusinessHandler handler = new RPCBusinessHandler();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                        .channel(NioSocketChannel.class)
                        .option(ChannelOption.TCP_NODELAY, true)
                        .handler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                ChannelPipeline pipeline = ch.pipeline();
                                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0,
                                        4, 0, 4));
                                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                                pipeline.addLast("encoder", new ObjectEncoder());
                                pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                                pipeline.addLast("handler", handler);
                            }
                        });

                ChannelFuture future = b.connect("localhost", 8080).sync();
                future.channel().writeAndFlush(msg).sync();
                future.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                group.shutdownGracefully();
            }
            return handler.getResult();
        }
    }
    
// 客户端逻辑处理
public class RPCBusinessHandler extends ChannelInboundHandlerAdapter {
    private Object result;
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        this.result = msg;
    }



    public Object getResult(){
        return this.result;
    }    
    
    
// 测试
 ISayHelloService service = new ProxyHandler().create(ISayHelloService.class);
 System.out.println(service.say("tony"));    
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Python基础(6)—— 函数
关键字参数和函数的调用关系密切,函数调用的时候必须使用函数的参数名称确定传入的参数值一一对应
羊羽shine
2019/05/29
2860
5.2Python函数(二)
目录 目录 前言 (一)偏函数 ==1.说明== ==2.原代码== ==3.显示效果== (二)高阶函数 ==1.说明== ==2.源代码== ==3.运行效果== (三)返回值函数 ==1.说明== ==2.源代码== ==3.运行效果== (四)匿名函数 ==1.说明== ==2.源代码== ==3.运行效果== (五)闭包函数 ==1.说明== ==2.源代码== ==3.运行效果== 目录 前言 这一篇式相继上一篇5.1Python函数(一)的进阶文章。 一个重要的思想是:我们把”函
py3study
2020/01/17
4460
Python编程 装饰器
网络豆
2023/10/15
1520
Python编程 装饰器
python高级-装饰器(19)
某公司有多个研发部⻔,1个基础平台部⻔,基础平台负责提供底层的功能,如:数据库操作、redis调⽤、监控API等功能。研发部⻔使⽤基础功能时,只需调⽤基础平台提供的功能即可。如下:
Se7eN_HOU
2019/09/11
4440
python高级-装饰器(19)
Python自动化开发学习3
函数的最后可以使用return定义返回值,没用retrun或者return后面不带表达式,返回值都是None。一上面的函数为例
py3study
2020/01/03
3750
python3--高阶函数
# Auther: Aaron Fan ''' # 高阶函数:把一个函数名,以实参的形式,传给这个函数的形参,这个函数就称为高阶函数。比如下面的形参c,对应的实参是一个函数名abs。 # 函数abs()的功能是取绝对值 def add(a,b,c):    return c(a) + c(b) add_value = add(-9,1,abs) print(add_value) ''' # 最正确的高阶函数解释 # 满足下面两个条件之一,就可称之为高阶函数: # 1、把一个函数名当做一个实参,传给
py3study
2020/01/07
3150
python-函数基础
def test(): a = 10 ​ # 不能再函数外部使用,此处会报错 print(a)
py3study
2020/01/18
5340
Python中的函数(一)
数学函数的定义:一般在一个变化过程中,如果有两个变量,X,Y,并且对于x的每一个确定值,y都有唯一与之对应的值,那么我们把x称为自变量,y为因变量,y为x的函数。x的取值范围就是函数的定义域。   如 : y = x + 5
py3study
2020/01/19
7080
Python学习笔记(二)
正如英文单词描述的,函数就是“功能”的意思,把完成一个功能所需要的代码打包起来放在一个函数下可以方便以后程序的重复调用,也能使整体代码条理清晰。正如前面用到的print(), input()之类的内置函数,这里讨论的函数为自定义涵数。
py3study
2020/01/17
8720
python 之 函数
现在有这么个情况:假设我们python中的len方法不可以使用了,而恰好你又要计算一个字符串的长度你该怎么办呢?有人说:‘简单,可以使用for循环嘛
全栈程序员站长
2022/07/21
4010
python学习笔记3.1-函数
本文介绍了Python中函数的定义、调用、参数以及lambda表达式的用法。函数是封装特定功能的代码块,可以通过调用进行重复使用,节省代码量并提高代码的可读性。函数的参数分为位置参数、可变参数和关键字参数。lambda表达式是一种匿名函数,语法简洁,常用于函数式编程中。
锦小年
2018/01/02
6580
【Python】函数Д
🚩write in front🚩 🔎大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家^星级博主~掘金⇿InfoQ创作者~周榜66 » 总榜1924🏅 🆔本文由 謓泽 原创 CSDN首发🙉如需转载还请通知⚠ 📝个人主页-打打酱油desuCSDN博客💬 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​ 📣系列专栏-【Python】系列_謓泽的博客-CSDN博客[〇~①]🎓 ✉️我
謓泽
2022/12/12
3870
【Python】函数Д
python基础-函数(9)
如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数
Se7eN_HOU
2019/09/11
5530
python基础-函数(9)
python 函数
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
py3study
2018/08/02
5300
python笔记:#012#函数
函数基础 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体验 1.1 快速体验 所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的 重用 演练步骤 新建 04_函数 项目 复制之前完成的 乘法表 文件 修改文件,增加函数定义 multiple_tab
_gongluck
2018/03/13
6930
Python 函数
一、函数的介绍 所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用: 在开发程序时,使用函数可以提高编写的效率以及代码的 重用 二、函数基本使用 2.1 函数的定义 定义函数的格式如下: def 函数名(): 函数封装的代码 …… def 是英文 define 的缩写 函数名称 应该能够表达 函数封装代码 的功能,方便后续的调用 函数名称 的命名应该 符合
忆想不到的晖
2021/12/06
7670
Python 函数
Python基础之函数和模块
在函数定义下的第一行,添加连续的三对双引号,在双引号中间进行文字注释; 在函数调用处可以用ctrl+q,查看函数说明。 注释如下:
py3study
2020/01/17
4550
python3 入门 (三) 函数与lambda表达式、闭包
函数 是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。 函数代码块以def关键词开头,后接函数标识符名称和圆括号() 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明 函数内容以冒号起始,并且缩进 Return[expression]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None 函数的定义: 1 def test0(): 2 "函数_文档字符串" 3 print(
欠扁的小篮子
2018/04/11
1.1K0
Python3 函数
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
AlexZhang
2021/12/02
1K0
7-2python函数-返回值、嵌套使用
在程序开发中,有时候会希望一个函数执行结束后,告诉调用者一个结果, 以便调用者针对具体的结果做后续的处理。
度假的小鱼
2023/11/12
3740
7-2python函数-返回值、嵌套使用
相关推荐
Python基础(6)—— 函数
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验