什么是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"]
}