[适合初中级Java程序员修炼手册从0搭建整个Web项目](六)

简介: 前言文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在

six-finger-web


一个Web后端框架的轮子从处理Http请求【基于Netty的请求级Web服务器】 到mvc【接口封装转发)】,再到ioc【依赖注入】,aop【切面】,再到 rpc【远程过程调用】最后到orm【数据库操作】全部自己撸一个(简易)的轮子。

github


为啥要写这个轮子

其实是这样的,小六六自己平时呢?有时候喜欢看看人家的源码比如Spring,但是小六六的水平可能不怎么样,每次看都看得晕头转向,然后就感觉里面的细节太难了,然后我就只能观其总体的思想,然后我就想我如果可以根据各位前辈的一些思考,自己撸一个简单的轮子出来,那我后面去理解作者的思想是不是简单点呢?于是呢 six-finger-web就面世了,它其实就是我的一个学习过程,然后我把它开源出来,希望能帮助那些对于学习源码有困难的同学。还有就是可以锻炼一下自己的编码能力,因为平时我们总是crud用的Java api都是那些,久而久之,很多框架类的api我们根本就不熟练了,所以借此机会,锻炼一下。


特点

  • 内置由 Netty 编写 HTTP 服务器,无需额外依赖 Tomcat 之类的 web 服务(刚好小六六把Netty系列写完,顺便用下)
  • 代码简单易懂(小六六自己写不出框架大佬那种高类聚,低耦合的代码),能力稍微强一点看代码就能懂,弱点的也没关系,小六六有配套的从0搭建教程。
  • 支持MVC相关的注解确保和SpringMVC的用法类似
  • 支持Spring IOC 和Aop相关功能
  • 支持类似于Mybatis相关功能
  • 支持类似于Dubbo的rpc相关功能
  • 对于数据返回,只支持Json格式


絮叨

前面是已经写好的章节,下面我给大家来一一走一遍搭建流程

我来总结一下前面我们已经完成的,我们已经完成了基于Netty的Http服务器,和springmvc spring ioc,spring aop相关的功能,小六六自我感觉良好,最少也有人加我微信跟小六六一起学习了,那么我今天继续,今天我们先来简简单单的了解一下rpc呗!


RPC简介


RPC(Remote Procedure Call Protocol)远程调用: 远程过程调用是一种常用的分布式网络通信协议,它允许运行于 一台计算机的程序调用另一台计算机的子程序,同时将网络的通信细节隐藏起来, 使得用户无须额外地为这个交互作用编程。分布式系统之间的通信大都通过RPC实现

基本上很多的框架的底层都是用的rpc通信,比如我们熟知的 ES RocktMq 等等 分布式的框架几乎都是,所以自己撸撸RPC框架那就很有必要了呗!

今天小六六想说的是,我们不要说一口气就吃成一个胖子,我们先来实现一个最最最简单的案例,来看看rpc他的一个大致过程,然后我们再照着我们dubbo来写个rpc框架,可能会好很多,所以今天就是给大家来个小案例,带领大家先来看看rpc框架的主流思想。



RPC请求过程

  • 注册客户端服务
  • 开启rpc服务端
  • 客户端以本地的方式来调用服务端
  • 客户端代理找到服务端地址,连接服务端,然后将参数、方法等通过发送给服务端
  • 服务端接收请求后将数据进行解码,然后根据解码的信息来执行本地程序,并将执行的结果返回给客户端
  • 客户端进行解码获取返回的结果


代码

IHello

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/30 17:46
 * 远程服务接口
 */
public interface IHello {
     String sayHello(String info);
}
复制代码


HelloService

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
import lombok.Data;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/30 17:47
 * 远程服务接口实现类(Server)
 */
@Data
public class HelloService implements IHello {
    @Override
    public String sayHello(String info) {
        String result = "hello : " + info;
        System.out.println(result);
        return result;
    }
}
复制代码


RpcProxyServer 也是服务的暴露过程

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/30 17:47
 * 服务器代理实现
 */
public class RpcProxyServer {
    private IHello hello = new HelloService();
    public void publisherServer(int port) {
        try (ServerSocket ss = new ServerSocket(port)) {
            while (true) {
                try (Socket socket = ss.accept()) {
                    try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
                        String method = ois.readUTF();
                        Object[] objs = (Object[]) ois.readObject();
                        Class<?>[] types = new Class[objs.length];
                        for (int i = 0; i < types.length; i++) {
                            types[i] = objs[i].getClass();
                        }
                        Method m = HelloService.class.getMethod(method, types);
                        Object obj = m.invoke(hello, objs);
                        try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
                            oos.writeObject(obj);
                            oos.flush();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码


RpcProxyClient

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/31 10:24
 * RPC 客户端代理实现
 */
public class RpcProxyClient<T> {
    public static Object proxyClient(Class clazz) {
      return   Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              try (Socket socket = new Socket("localhost", 8000)) {
                  try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
                      oos.writeUTF(method.getName());
                      oos.writeObject(args);
                      oos.flush();
                      try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
                          return ois.readObject();
                      }
                  }
              }
          }
        });
    }
}
复制代码


RpcServer 测试

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/31 10:26
 */
public class RpcServer {
    //发布服务
    public static void main(String[] args) {
        RpcProxyServer server = new RpcProxyServer();
        server.publisherServer(8000);
    }
}
复制代码


RpcClient

package com.xiaoliuliu.six.finger.web.demo.rpc.simple.test;
/**
 * @author 小六六
 * @version 1.0
 * @date 2020/10/31 10:26
 */
public class RpcClient {
    // 调用服务
    public static void main(String[] args) {
        IHello hello = (IHello) RpcProxyClient.proxyClient(IHello.class);
        String s = hello.sayHello("小六六写rpc demo呀");
        System.out.println(s);
    }
}
复制代码


结果

网络异常,图片无法展示
|

网络异常,图片无法展示
|


结尾


好了,rpc的开头,我们就写完了,其实也很简单,通过代理 和网络通信来屏蔽代码的实现细节,做过调用远程服务和本地服务一样,无感知。后面的话,我们就模仿一下dubbo,来完成它的部分功能,dubbo的人家可不是一个单纯的rpc框架,它致力于服务治理,这个就很广了,我们后面再看。

相关文章
|
弹性计算 安全 关系型数据库
阿里云数据库RDS MySQL Serverless测评
就像云服务器和本地服务器的区别一样,云数据库就是云计算版本的数据库。 阿里云数据库有多种,今天尝试的是RDS MySQL Serverless,可以按需付费、动态匹配资源,这样的话如果是短期内使用的话比较划算。 例如某时间段搞活动导致数据库访问量暴涨,就可以临时购买该产品,动态提升性能,还是比较方便的
2098 1
|
弹性计算
关于使用阿里云ECS的体验
关于使用阿里云ECS云服务器的个人体验以及一些平时使用时遇到的问题和解决办法。
|
MySQL 关系型数据库 Linux
教你如何在阿里云服务器上安装Mysql数据库(mysql5.7.23+centos)
对于一个建站新手来讲,最重要的莫过于2件事  1.时间效率 2.性价比 换句话讲,对于非专业选手,在整个建站过程,如何省时省力,用相对简单的方式,花更少的钱建好网站是关键。 基于上述,给大家带来一版适合新手的建站指南,供大家参考。
4171 0
|
数据库 索引
如何让搜索随心所欲?一起来聊聊“以图搜图”
一张图片蕴含的价值远远超过自己本身。相对于传统的文字搜索,图片能给消费者带来更大的冲击力,图片蕴含的价值已成为电商的一个大金矿,我们怎样去挖掘这个金矿呢?博云视觉CEO陈杰在2016云栖大会•北京峰会上分享了以图搜图的电商搜索新模式。
8233 0
|
13天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
5198 27
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
|
8天前
|
存储 定位技术 数据库
CodeGraph 如何让 Claude Code减少 7 成工具调用?
CodeGraph 为 Coding Agent 提供本地代码知识图谱,把函数、类、调用链和框架路由提前整理成“项目地图”,减少盲目搜索和文件读取。它不是新 Agent,而是上下文基础设施,让 Agent 更快找到正确代码路径,平均减少 7 成工具调用。
1028 0
|
15天前
|
人工智能 自然语言处理 供应链