广告位联系
返回顶部
分享到

基于Springboot+Netty实现rpc的方法 附demo

java 来源:互联网 作者:秩名 发布时间:2022-02-28 14:27:56 人浏览
摘要

今天翻看了一下Netty相关的知识点,正好练练手,简单捣鼓了这个demo;这里简单梳理一下; 前提知识点: Springboot、Netty、动态代理(反射)、反射 项目整体结构如下: 1.在父项目中引入相

今天翻看了一下Netty相关的知识点,正好练练手,简单捣鼓了这个demo;这里简单梳理一下;

前提知识点:

Springboot、 Netty、动态代理(反射)、反射

项目整体结构如下:

 1.在父项目中引入相关依赖;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<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>

2.服务提供模块整体结构如下:

 这里重点关注一下 RequestModel  和 ResponseModel 两个消息体类,

1

2

3

4

5

6

7

8

9

10

11

@Data

@AllArgsConstructor

public class RequestModel {

  

    private String requestId;

    private String serviceName;

    private String methodName;

    private Class[] paramTypes;

    private Object[] paramValues;

  

}

1

2

3

4

5

6

7

8

9

@Data

@AllArgsConstructor

public class ResponseModel {

    private String responseId;

    private String serviceName;

    private String methodName;

    private String code;

    private String data;

}

用于服务端和客户端的数据传输;再者就是关注 ServerChannelInboundHandler 中的 channelRead0() 报文解码处理;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

@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() 方法的处理

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@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 类中获取获取服务的处理;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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;

    }

 测试结果:

总结: 这个demo相对比较简单,但对于理解rpc 远程调用有一定帮助,最后分享一下这个代码地址:

nettydemo: netty springboot rpc远程调用demo 

https://gitee.com/lizhiyunfengxiang/nettydemo


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/qq_21299835/article/details/123154558
相关文章
  • SpringBoot自定义错误处理逻辑介绍

    SpringBoot自定义错误处理逻辑介绍
    1. 自定义错误页面 将自定义错误页面放在 templates 的 error 文件夹下,SpringBoot 精确匹配错误信息,使用 4xx.html 或者 5xx.html 页面可以打印错误
  • Java实现手写一个线程池的代码

    Java实现手写一个线程池的代码
    线程池技术想必大家都不陌生把,相信在平时的工作中没有少用,而且这也是面试频率非常高的一个知识点,那么大家知道它的实现原理和
  • Java实现断点续传功能的代码

    Java实现断点续传功能的代码
    题目实现:网络资源的断点续传功能。 二、解题思路 获取要下载的资源网址 显示网络资源的大小 上次读取到的字节位置以及未读取的字节
  • 你可知HashMap为什么是线程不安全的
    HashMap 的线程不安全 HashMap 的线程不安全主要体现在下面两个方面 在 jdk 1.7 中,当并发执行扩容操作时会造成环形链和数据丢失的情况 在
  • ArrayList的动态扩容机制的介绍

    ArrayList的动态扩容机制的介绍
    对于 ArrayList 的动态扩容机制想必大家都听说过,之前的文章中也谈到过,不过由于时间久远,早已忘却。 所以利用这篇文章做做笔记,加
  • JVM基础之字节码的增强技术介绍

    JVM基础之字节码的增强技术介绍
    字节码增强技术 在上文中,着重介绍了字节码的结构,这为我们了解字节码增强技术的实现打下了基础。字节码增强技术就是一类对现有字
  • Java中的字节码增强技术

    Java中的字节码增强技术
    1.字节码增强技术 字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。 参考地址 2.常见技术 技术分类 类
  • Redis BloomFilter布隆过滤器原理与实现

    Redis BloomFilter布隆过滤器原理与实现
    Bloom Filter 概念 布隆过滤器(英语:Bloom Filter)是1970年由一个叫布隆的小伙子提出的。它实际上是一个很长的二进制向量和一系列随机映射
  • Java C++算法题解leetcode801使序列递增的最小交换次

    Java C++算法题解leetcode801使序列递增的最小交换次
    题目要求 思路:状态机DP 实现一:状态机 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int minSwap(int[] nums1, int[] nums2) { int n
  • Mybatis结果集映射与生命周期介绍

    Mybatis结果集映射与生命周期介绍
    一、ResultMap结果集映射 1、设计思想 对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了 2、resultMap的应用场
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计