基于http手写rpc框架

什么是RPC?

Remote Procedure Call (RPC) is a protocol that one program can use to request a service from a program located in another computer on a network without having to understand the network's details. A procedure call is also sometimes known as a function call or a subroutine call.

   远程过程调用(RPC)是一种协议,一个程序可以使用该协议从位于网络上另一台计算机中的程序请求服务,而无需了解网络的详细信息。过程调用有时也称为函数调用或子例程调用。

怎么实现RPC?

1.新建springboot工程

使用springBeanfactory获取容器中所有bean

package com.yyl.rpc.common;

import javafx.fxml.Initializable;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 15:24
 */
@Component
public class SpringBeanFactory implements ApplicationContextAware,InitializingBean,BeanPostProcessor {
    /** ApplicationContext 对象 */
    private ApplicationContext applicationContext;

    /** 单子 */
    private static SpringBeanFactory instance = new SpringBeanFactory();

    public static void setInstance(SpringBeanFactory instance) {
        SpringBeanFactory.instance = instance;
    }

    private static SpringBeanFactory getInstance() {
        return SpringBeanFactory.instance;
    }

    public static <T> T getBean(Class<T> type) {
        return instance.getInnerBean(type);
    }
    private <T> T getInnerBean(Class<T> type) {
        String[] names = this.applicationContext.getBeanNamesForType(type);
        if (names == null || names.length == 0) {
            return null;
        }
        return (T) this.applicationContext.getBean(names[0]);
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        SpringBeanFactory.setInstance(this);
        String[] names = this.applicationContext.getBeanDefinitionNames();
        for (int i = 0; i < names.length; i++) {
            System.out.println(" == names[" + i + "]:" + names[i]);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

建rpccontroller接收远程调用

package com.yyl.rpc.controller;

import com.yyl.rpc.common.SpringBeanFactory;
import com.yyl.rpc.domain.RpcRequestData;
import com.yyl.rpc.domain.RpcResponseData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 13:22
 */
@Controller
@RequestMapping("/rpc")
public class RpcController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private final Map<String, Class<?>> primitiveClassMap = new HashMap<String, Class<?>>();
    {
        primitiveClassMap.put(Integer.TYPE.getName(), Integer.TYPE);
        primitiveClassMap.put(Short.TYPE.getName(), Short.TYPE);
        primitiveClassMap.put(Long.TYPE.getName(), Long.TYPE);
        primitiveClassMap.put(Float.TYPE.getName(), Float.TYPE);
        primitiveClassMap.put(Boolean.TYPE.getName(), Boolean.TYPE);
        primitiveClassMap.put(Byte.TYPE.getName(), Byte.TYPE);
        primitiveClassMap.put(Double.TYPE.getName(), Double.TYPE);
        primitiveClassMap.put(Character.TYPE.getName(), Character.TYPE);
        primitiveClassMap.put(Character.TYPE.getName(), Character.TYPE);
    }

    private Class<?> getClass(String className) throws ClassNotFoundException{
        Class<?> clazz = primitiveClassMap.get(className);
        return clazz == null ? Class.forName(className) : clazz;
    }
    @RequestMapping("/invoke")
    @ResponseBody
    public RpcResponseData<Object> invoke(@RequestBody RpcRequestData request, HttpServletRequest httpServletRequest){
        if(request==null){
            logger.debug("请求参数不能为空");
        }
        if(request.getInterfaceType().isEmpty()|| request.getMethodName().isEmpty()){
            throw new IllegalArgumentException("参数有误");
        }
        RpcResponseData<Object> responseData=new RpcResponseData<>();
        try {
            Class<?> clazz = this.getClass(request.getInterfaceType());
            Object serviceImpl=SpringBeanFactory.getBean(clazz);
            if(serviceImpl==null){
                throw new ClassNotFoundException("没发现服务类");
            }
            List<Class<?>> list=new ArrayList<>();
            for (String paramTypeName:request.getParameterTypes()) {
                list.add(this.getClass(paramTypeName));
            }
            final Method method =clazz.getMethod(request.getMethodName(),list.toArray(new Class[0]));
            Object object=method.invoke(serviceImpl,request.getArgs());
            responseData.setSuccess(true);
            responseData.setResult(object);

        }catch (Exception e){
            responseData.setSuccess(false);
            responseData.setErrorMessage(e.getMessage());
        }
        return responseData;
    }

}

封装请求对象和返回对象

package com.yyl.rpc.domain;

import java.util.List;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 13:24
 */
public class RpcRequestData {
    private String clientID;
    private String interfaceType;
    private String serviceName;
    private String methodName;
    private String args[];
    private List<String> parameterTypes;

    public String getClientID() {
        return clientID;
    }

    public void setClientID(String clientID) {
        this.clientID = clientID;
    }

    public String getInterfaceType() {
        return interfaceType;
    }

    public void setInterfaceType(String interfaceType) {
        this.interfaceType = interfaceType;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public String[] getArgs() {
        return args;
    }

    public void setArgs(String[] args) {
        this.args = args;
    }

    public List<String> getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(List<String> parameterTypes) {
        this.parameterTypes = parameterTypes;
    }
}

返回对象

package com.yyl.rpc.domain;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 13:26
 */
public class RpcResponseData<T> {
    private T result;
    private boolean success;
    private String errorMessage;
    private String cause;

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public String getCause() {
        return cause;
    }

    public void setCause(String cause) {
        this.cause = cause;
    }
}

服务接口

package com.yyl.rpc.service;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 13:20
 */
public interface DemoService {
    String add(String a,String b);
}

服务实现类

package com.yyl.rpc.service.impl;

import com.yyl.rpc.service.DemoService;
import org.springframework.stereotype.Service;

/**
 * ${DESCRIPTION}
 *
 * @author yyl
 * @date 2018年11月29日 13:21
 */
@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public String add(String a, String b) {
        return a+b;
    }
}

测试

# rpc
#使用http实现rpc远程调用

步骤
1.启动项目
2.post请求模拟
localhost:8080/rpc/invoke
{
   
   "clientID":"1222",
   "interfaceType":"com.yyl.rpc.service.DemoService",
   "serviceName":"com.yyl.rpc.service.impl.DemoServiceImpl",
   "methodName":"add",
   "args":["1","22222"],
   "parameterTypes":["java.lang.String","java.lang.String"]
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值