当前位置:   article > 正文

简单的rpc实现_@rpcprovider 注解

@rpcprovider 注解

学习summer的github,主要用于记录方便后续查看代码

  1. package com.summer.simplerpc.annotation;
  2. import org.springframework.stereotype.Component;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. /**
  8. * RPC consumer注解
  9. *
  10. * @author summer
  11. * @version $Id: SimpleRpcProviderBean.java, v 0.1 2022年01月16日 11:53 AM summer Exp $
  12. */
  13. @Retention(RetentionPolicy.RUNTIME)
  14. //注解打在属性上
  15. @Target(ElementType.FIELD)
  16. @Component
  17. public @interface SimpleRpcConsumer {
  18. /**
  19. * 服务版本号
  20. * @return
  21. */
  22. String serviceVersion() default "1.0.0";
  23. /**
  24. * 注册中心类型-默认zk
  25. * @return
  26. */
  27. String registerType() default "zookeeper";
  28. /**
  29. * 注册中心地址
  30. * @return
  31. */
  32. String registerAddress() default "127.0.0.1:2181";
  33. }
  1. package com.summer.simplerpc.annotation;
  2. import org.springframework.stereotype.Component;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. /**
  8. * RPC provider注解
  9. *
  10. * @author summer
  11. * @version $Id: SimpleRpcProviderBean.java, v 0.1 2022年01月16日 11:53 AM summer Exp $
  12. */
  13. @Retention(RetentionPolicy.RUNTIME)
  14. //注解打在类上
  15. @Target(ElementType.TYPE)
  16. @Component
  17. public @interface SimpleRpcProvider {
  18. Class<?> serviceInterface() default Object.class;
  19. String serviceVersion() default "1.0.0";
  20. }
  1. package com.summer.simplerpc.consumer;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. /**
  7. * rpc consumer starter
  8. *
  9. * @author summer
  10. * @version $Id: SimplerConsumerAutoConfiguration.java, v 0.1 2022年01月16日 6:19 PM summer Exp $
  11. */
  12. @Configuration
  13. @Slf4j
  14. public class SimplerConsumerAutoConfiguration {
  15. @Bean
  16. public static BeanFactoryPostProcessor initRpcConsumer() throws Exception {
  17. return new SimpleRpcConsumerPostProcessor();
  18. }
  19. }
  1. package com.summer.simplerpc.consumer;
  2. import com.summer.simplerpc.registry.ServiceRegistry;
  3. import com.summer.simplerpc.registry.cache.ServiceProviderCache;
  4. import com.summer.simplerpc.registry.cache.ServiceProviderLocalCache;
  5. import com.summer.simplerpc.registry.zk.ZkServiceRegistry;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.beans.factory.FactoryBean;
  8. import java.lang.reflect.Proxy;
  9. /**
  10. * 生成rpc consumer代理bean的FactoryBean
  11. *
  12. * @author summer
  13. * @version $Id: SimpleRpcConsumerFactoryBean.java, v 0.1 2022年01月18日 8:58 AM summer Exp $
  14. */
  15. @Slf4j
  16. public class SimpleRpcConsumerFactoryBean implements FactoryBean {
  17. /**
  18. * 调用的服务接口类
  19. */
  20. private Class<?> interfaceClass;
  21. /**
  22. * 服务版本号
  23. */
  24. private String serviceVersion;
  25. /**
  26. * 注册中心类型
  27. */
  28. private String registryType;
  29. /**
  30. * 注册中心地址
  31. */
  32. private String registryAddress;
  33. /**
  34. * 实际的bean
  35. */
  36. private Object object;
  37. /**
  38. * init方法,通过动态代理生成bean
  39. *
  40. * @throws Exception
  41. */
  42. public void init() throws Exception {
  43. ServiceProviderCache serviceProviderCache = new ServiceProviderLocalCache();
  44. ServiceRegistry zkServiceRegistry = new ZkServiceRegistry(registryAddress, serviceProviderCache);
  45. //动态代理
  46. this.object = Proxy.newProxyInstance(
  47. interfaceClass.getClassLoader(),
  48. new Class<?>[] {interfaceClass},
  49. new SimpleRpcInvokeHandler<>(this.serviceVersion, zkServiceRegistry));
  50. log.info("SimpleRpcConsumerFactoryBean getObject {}", interfaceClass.getName());
  51. }
  52. /**
  53. * 返回创建的bean实例
  54. *
  55. * @return
  56. * @throws Exception
  57. */
  58. @Override
  59. public Object getObject() throws Exception {
  60. return this.object;
  61. }
  62. /**
  63. * 创建的bean实例的类型
  64. *
  65. * @return
  66. */
  67. @Override
  68. public Class<?> getObjectType() {
  69. return interfaceClass;
  70. }
  71. /**
  72. * 创建的bean实例的作用域
  73. *
  74. * @return
  75. */
  76. @Override
  77. public boolean isSingleton() {
  78. return true;
  79. }
  80. public void setInterfaceClass(Class<?> interfaceClass) {
  81. this.interfaceClass = interfaceClass;
  82. }
  83. public void setServiceVersion(String serviceVersion) {
  84. this.serviceVersion = serviceVersion;
  85. }
  86. public void setRegistryType(String registryType) {
  87. this.registryType = registryType;
  88. }
  89. public void setRegistryAddress(String registryAddress) {
  90. this.registryAddress = registryAddress;
  91. }
  92. }
  1. package com.summer.simplerpc.consumer;
  2. import com.summer.simplerpc.io.RPCDecoder;
  3. import com.summer.simplerpc.io.RPCEncoder;
  4. import com.summer.simplerpc.model.SimpleRpcRequest;
  5. import com.summer.simplerpc.model.SimpleRpcResponse;
  6. import com.summer.simplerpc.registry.ServiceRegistry;
  7. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  8. import com.summer.simplerpc.util.ServiceUtils;
  9. import io.netty.bootstrap.Bootstrap;
  10. import io.netty.channel.*;
  11. import io.netty.channel.nio.NioEventLoopGroup;
  12. import io.netty.channel.socket.SocketChannel;
  13. import io.netty.channel.socket.nio.NioSocketChannel;
  14. import lombok.extern.slf4j.Slf4j;
  15. /**
  16. * consumer netty handler
  17. *
  18. * @author summer
  19. * @version $Id: SimpleRpcConsumerNettyHandler.java, v 0.1 2022年01月19日 8:23 AM summer Exp $
  20. */
  21. @Slf4j
  22. public class SimpleRpcConsumerNettyHandler extends SimpleChannelInboundHandler<SimpleRpcResponse> {
  23. /**
  24. * 注册中心
  25. */
  26. private ServiceRegistry serviceRegistry;
  27. /**
  28. * netty EventLoopGroup
  29. */
  30. private EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);
  31. /**
  32. * netty channel
  33. */
  34. private Channel channel;
  35. /**
  36. * rpc response
  37. */
  38. private SimpleRpcResponse rpcResponse;
  39. /**
  40. * lock
  41. */
  42. private final Object lock = new Object();
  43. /**
  44. * 构造函数
  45. *
  46. * @param serviceRegistry
  47. */
  48. public SimpleRpcConsumerNettyHandler(ServiceRegistry serviceRegistry) {
  49. this.serviceRegistry = serviceRegistry;
  50. }
  51. /**
  52. * 发起RPC网络调用请求
  53. *
  54. * @param simpleRpcRequest 请求参数
  55. * @return
  56. */
  57. public SimpleRpcResponse sendRpcRequest(SimpleRpcRequest simpleRpcRequest) {
  58. try {
  59. Bootstrap bootstrap = new Bootstrap();
  60. bootstrap.group(eventLoopGroup)
  61. .channel(NioSocketChannel.class)
  62. .handler(new ChannelInitializer<SocketChannel>() {
  63. @Override
  64. protected void initChannel(SocketChannel socketChannel) throws Exception {
  65. socketChannel.pipeline()
  66. .addLast(new RPCEncoder())
  67. .addLast(new RPCDecoder())
  68. //通过.class获取此类型的实例(https://www.cnblogs.com/penglee/p/3993033.html)
  69. .addLast(SimpleRpcConsumerNettyHandler.this);
  70. }
  71. });
  72. String key = ServiceUtils.buildServiceKey(simpleRpcRequest.getClassName(), simpleRpcRequest.getServiceVersion());
  73. ServiceMetaConfig serviceMetaConfig = this.serviceRegistry.discovery(key);
  74. if (serviceMetaConfig == null) {
  75. log.error("sendRpcRequest fail,serviceMetaConfig not found");
  76. throw new Exception("serviceMetaConfig not found in registry");
  77. }
  78. log.info("sendRpcRequest begin,serviceMetaConfig=" + serviceMetaConfig.toString() + ",key=" + key);
  79. final ChannelFuture channelFuture = bootstrap.connect(serviceMetaConfig.getAddress(), serviceMetaConfig.getPort())
  80. .sync();
  81. channelFuture.addListener((ChannelFutureListener)args0 -> {
  82. if (channelFuture.isSuccess()) {
  83. log.info("rpc invoke success,");
  84. } else {
  85. log.info("rpc invoke fail," + channelFuture.cause().getStackTrace());
  86. eventLoopGroup.shutdownGracefully();
  87. }
  88. });
  89. this.channel = channelFuture.channel();
  90. this.channel.writeAndFlush(simpleRpcRequest).sync();
  91. synchronized (this.lock) {
  92. log.info("sendRpcRequest lock.wait");
  93. this.lock.wait();
  94. }
  95. log.info("get rpc response=" + rpcResponse.toString());
  96. return this.rpcResponse;
  97. } catch (Exception e) {
  98. log.error("sendRpcRequest exception,", e);
  99. return null;
  100. } finally {
  101. //关闭相关连接
  102. if (this.channel != null) {
  103. this.channel.close();
  104. }
  105. if (this.eventLoopGroup != null) {
  106. this.eventLoopGroup.shutdownGracefully();
  107. }
  108. }
  109. }
  110. @Override
  111. protected void channelRead0(ChannelHandlerContext channelHandlerContext, SimpleRpcResponse simpleRpcResponse) throws Exception {
  112. this.rpcResponse = simpleRpcResponse;
  113. log.info("rpc consumer netty handler,channelRead0,rpcResponse=" + rpcResponse);
  114. //收到远程网络的rpc response,通知调用端
  115. synchronized (lock) {
  116. log.info("channelRead0 simpleRpcResponse lock.notifyAll");
  117. lock.notifyAll();
  118. }
  119. }
  120. }
  1. package com.summer.simplerpc.consumer;
  2. import com.summer.simplerpc.annotation.SimpleRpcConsumer;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.beans.BeansException;
  5. import org.springframework.beans.factory.BeanClassLoaderAware;
  6. import org.springframework.beans.factory.config.BeanDefinition;
  7. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  8. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  9. import org.springframework.beans.factory.support.BeanDefinitionBuilder;
  10. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  11. import org.springframework.core.annotation.AnnotationUtils;
  12. import org.springframework.util.ClassUtils;
  13. import org.springframework.util.ReflectionUtils;
  14. import org.springframework.util.StringUtils;
  15. import java.lang.reflect.Field;
  16. import java.util.HashMap;
  17. import java.util.Map;
  18. /**
  19. * rpc consumer具体处理器。负责扫描代码中含@SimpleRpcConsumer注解的属性,进行代理实现远端网络调用。
  20. *
  21. * @author summer
  22. * @version $Id: SimpleRpcConsumerPostProcessor.java, v 0.1 2022年01月18日 8:28 AM summer Exp $
  23. */
  24. @Slf4j
  25. public class SimpleRpcConsumerPostProcessor implements BeanFactoryPostProcessor, BeanClassLoaderAware {
  26. /**
  27. * classloader
  28. */
  29. private ClassLoader classLoader;
  30. /**
  31. * 保存BeanDefinition列表
  32. */
  33. private Map<String, BeanDefinition> beanDefinitions = new HashMap<>();
  34. @Override
  35. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  36. log.info("SimpleRpcConsumerPostProcessor postProcessBeanFactory begin");
  37. //遍历bean,改些打了SimpleRpcConsumer注解的属性
  38. for (String beanName : beanFactory.getBeanDefinitionNames()) {
  39. BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
  40. if (StringUtils.isEmpty(beanDefinition.getBeanClassName())) {
  41. continue;
  42. }
  43. Class<?> clazz = ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), this.classLoader);
  44. ReflectionUtils.doWithFields(clazz, this::processConsumerBeanDefinition);
  45. }
  46. //将BeanDefinition重新注入spring容器
  47. BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry)beanFactory;
  48. for (Map.Entry<String, BeanDefinition> entry : this.beanDefinitions.entrySet()) {
  49. log.info("register BeanDefinition[" + entry.getKey() + "," + entry.getValue() + "]");
  50. beanDefinitionRegistry.registerBeanDefinition(entry.getKey(), entry.getValue());
  51. }
  52. }
  53. /**
  54. * 带有rpc消费者注解的bean定义的重处理
  55. *
  56. * @param field 属性
  57. */
  58. private void processConsumerBeanDefinition(Field field) {
  59. SimpleRpcConsumer simpleRpcConsumer = AnnotationUtils.getAnnotation(field, SimpleRpcConsumer.class);
  60. //筛选出打了rpc consumer注解的属性
  61. if (simpleRpcConsumer == null) {
  62. return;
  63. }
  64. log.info("processConsumerBeanDefinition,find a simpleRpcConsumer field:" + field.toString());
  65. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleRpcConsumerFactoryBean.class);
  66. beanDefinitionBuilder.setInitMethodName("init");
  67. beanDefinitionBuilder.addPropertyValue("interfaceClass", field.getType());
  68. beanDefinitionBuilder.addPropertyValue("serviceVersion", simpleRpcConsumer.serviceVersion());
  69. beanDefinitionBuilder.addPropertyValue("registryType", simpleRpcConsumer.registerType());
  70. beanDefinitionBuilder.addPropertyValue("registryAddress", simpleRpcConsumer.registerAddress());
  71. BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
  72. log.info("processConsumerBeanDefinition,find a simpleRpcConsumer field,result beanDefinition:" + field.toString());
  73. beanDefinitions.put(field.getName(), beanDefinition);
  74. }
  75. /**
  76. * 获取classloader
  77. *
  78. * @param classLoader
  79. */
  80. @Override
  81. public void setBeanClassLoader(ClassLoader classLoader) {
  82. this.classLoader = classLoader;
  83. }
  84. }
  1. package com.summer.simplerpc.consumer;
  2. import com.summer.simplerpc.model.SimpleRpcRequest;
  3. import com.summer.simplerpc.model.SimpleRpcResponse;
  4. import com.summer.simplerpc.registry.ServiceRegistry;
  5. import lombok.extern.slf4j.Slf4j;
  6. import java.lang.reflect.InvocationHandler;
  7. import java.lang.reflect.Method;
  8. import java.util.UUID;
  9. /**
  10. * RPC调用动态代理handler实现
  11. *
  12. * @author summer
  13. * @version $Id: SimpleRpcInvokeHandler.java, v 0.1 2022年01月18日 9:19 AM summer Exp $
  14. */
  15. @Slf4j
  16. public class SimpleRpcInvokeHandler<T> implements InvocationHandler {
  17. /**
  18. * 服务版本号
  19. */
  20. private String serviceVersion;
  21. /**
  22. * 注册中心
  23. */
  24. private ServiceRegistry serviceRegistry;
  25. /**
  26. * 默认构造函数
  27. */
  28. public SimpleRpcInvokeHandler() {
  29. }
  30. public SimpleRpcInvokeHandler(String serviceVersion, ServiceRegistry serviceRegistry) {
  31. this.serviceVersion = serviceVersion;
  32. this.serviceRegistry = serviceRegistry;
  33. }
  34. @Override
  35. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  36. SimpleRpcRequest simpleRpcRequest = new SimpleRpcRequest();
  37. simpleRpcRequest.setBizNO(UUID.randomUUID().toString());
  38. simpleRpcRequest.setClassName(method.getDeclaringClass().getName());
  39. simpleRpcRequest.setServiceVersion(this.serviceVersion);
  40. simpleRpcRequest.setMethodName(method.getName());
  41. simpleRpcRequest.setParamTypes(method.getParameterTypes());
  42. simpleRpcRequest.setParamValues(args);
  43. log.info("begin simpleRpcRequest=" + simpleRpcRequest.toString());
  44. SimpleRpcConsumerNettyHandler simpleRpcConsumerNettyHandler = new SimpleRpcConsumerNettyHandler(this.serviceRegistry);
  45. SimpleRpcResponse simpleRpcResponse = simpleRpcConsumerNettyHandler.sendRpcRequest(simpleRpcRequest);
  46. log.info("result simpleRpcResponse=" + simpleRpcResponse);
  47. return simpleRpcResponse.getData();
  48. }
  49. }
  1. package com.summer.simplerpc.io;
  2. import com.caucho.hessian.io.HessianInput;
  3. import com.caucho.hessian.io.HessianOutput;
  4. import lombok.extern.slf4j.Slf4j;
  5. import java.io.ByteArrayInputStream;
  6. import java.io.ByteArrayOutputStream;
  7. import java.io.IOException;
  8. /**
  9. * 序列化工具类(Hessian序列化协议)
  10. *
  11. * @author summer
  12. * @version $Id: HessianUtils.java, v 0.1 2022年01月16日 5:00 PM summer Exp $
  13. */
  14. @Slf4j
  15. public class HessianUtils {
  16. /**
  17. * 序列化
  18. *
  19. * @param object
  20. * @param <T>
  21. * @return
  22. */
  23. public final static <T> byte[] serialize(T object) {
  24. ByteArrayOutputStream byteArrayOutputStream = null;
  25. HessianOutput hessianOutput = null;
  26. try {
  27. byteArrayOutputStream = new ByteArrayOutputStream();
  28. hessianOutput = new HessianOutput(byteArrayOutputStream);
  29. hessianOutput.writeObject(object);
  30. return byteArrayOutputStream.toByteArray();
  31. } catch (IOException ioe) {
  32. log.error("serialize io exception,object=" + object, ioe);
  33. } finally {
  34. if (byteArrayOutputStream != null) {
  35. try {
  36. byteArrayOutputStream.close();
  37. } catch (IOException ioe) {
  38. log.error("serialize byteArrayOutputStream close io exception,object=" + object, ioe);
  39. }
  40. }
  41. if (hessianOutput != null) {
  42. try {
  43. hessianOutput.close();
  44. } catch (IOException ioe) {
  45. log.error("serialize hessianOutput close io exception,object=" + object, ioe);
  46. }
  47. }
  48. }
  49. return null;
  50. }
  51. /**
  52. * 反序列化
  53. *
  54. * @param bytes
  55. * @param <T>
  56. * @return
  57. */
  58. public final static <T> T deserialize(byte[] bytes) {
  59. ByteArrayInputStream byteArrayInputStream = null;
  60. HessianInput hessianInput = null;
  61. try {
  62. byteArrayInputStream = new ByteArrayInputStream(bytes);
  63. hessianInput = new HessianInput(byteArrayInputStream);
  64. return (T)hessianInput.readObject();
  65. } catch (IOException ioe) {
  66. log.error("deserialize io exception,bytes=" + bytes, ioe);
  67. } finally {
  68. if (byteArrayInputStream != null) {
  69. try {
  70. byteArrayInputStream.close();
  71. } catch (IOException ioe) {
  72. log.error("deserialize byteArrayOutputStream close io exception,bytes=" + bytes, ioe);
  73. }
  74. }
  75. if (hessianInput != null) {
  76. try {
  77. hessianInput.close();
  78. } catch (Exception ioe) {
  79. log.error("deserialize hessianInput close io exception,bytes=" + bytes, ioe);
  80. }
  81. }
  82. }
  83. return null;
  84. }
  85. }
  1. package com.summer.simplerpc.io;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.channel.ChannelHandlerContext;
  4. import io.netty.handler.codec.ByteToMessageDecoder;
  5. import lombok.extern.slf4j.Slf4j;
  6. import java.util.List;
  7. /**
  8. * 自定义解码器,解析出RPC请求对象
  9. *
  10. * @author summer
  11. * @version $Id: RPCDecoder.java, v 0.1 2022年01月16日 5:22 PM summer Exp $
  12. */
  13. @Slf4j
  14. public class RPCDecoder extends ByteToMessageDecoder {
  15. @Override
  16. public final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
  17. //入参校验
  18. if (in.readableBytes() < 4) {
  19. log.error("decode fail,input ByteBuf illegal,in.readableBytes=" + in.readableBytes());
  20. return;
  21. }
  22. in.markReaderIndex();
  23. //读取长度内容
  24. int dataLen = in.readInt();
  25. //剩余可读内容小于预定长度
  26. if (in.readableBytes() < dataLen) {
  27. log.error("decode fail,input ByteBuf illegal,in.readableBytes {0} less than dataLen {1}", in.readableBytes(), dataLen);
  28. return;
  29. }
  30. //读取实际内容
  31. byte[] actualDataBytes = new byte[dataLen];
  32. in.readBytes(actualDataBytes);
  33. //反序列化
  34. Object dataObj = HessianUtils.deserialize(actualDataBytes);
  35. if (dataObj == null) {
  36. log.error("decode fail,input ByteBuf illegal,dataObj null,actualDataBytes={0}", actualDataBytes);
  37. return;
  38. }
  39. out.add(dataObj);
  40. }
  41. }
  1. package com.summer.simplerpc.io;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.channel.ChannelHandlerContext;
  4. import io.netty.handler.codec.MessageToByteEncoder;
  5. import lombok.extern.slf4j.Slf4j;
  6. /**
  7. * 自动以编码器,将rpc返回结果编码为字节流
  8. *
  9. * @author summer
  10. * @version $Id: RPCEncoder.java, v 0.1 2022年01月16日 5:29 PM summer Exp $
  11. */
  12. @Slf4j
  13. public class RPCEncoder extends MessageToByteEncoder {
  14. @Override
  15. protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception {
  16. byte[] data = HessianUtils.serialize(o);
  17. if (data == null) {
  18. log.error("encode fail,result data null,result object=" + o);
  19. }
  20. byteBuf.writeInt(data.length);
  21. byteBuf.writeBytes(data);
  22. }
  23. }
  1. package com.summer.simplerpc.model;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import org.springframework.stereotype.Component;
  5. /**
  6. * RPC通用配置信息,提供用户自定义的功能
  7. *
  8. * @author summer
  9. * @version $Id: RpcCommonProperty.java, v 0.1 2022年01月16日 6:09 PM summer Exp $
  10. */
  11. @Data
  12. @Component
  13. @ConfigurationProperties(prefix = "summer.simplerpc")
  14. public class RpcCommonProperty {
  15. /**
  16. * 服务提供方地址
  17. */
  18. private String serviceAddress;
  19. /**
  20. * 注册中心类型
  21. */
  22. private String registryType;
  23. /**
  24. * 注册中心地址
  25. */
  26. private String registryAddress;
  27. }
  1. package com.summer.simplerpc.model;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. /**
  5. * RPC请求领域模型
  6. *
  7. * @author summer
  8. * @version $Id: SimpleRpcRequest.java, v 0.1 2022年01月16日 5:37 PM summer Exp $
  9. */
  10. @Data
  11. public class SimpleRpcRequest implements Serializable {
  12. private static final long serialVersionUID = -6523563004185159591L;
  13. /**
  14. * 业务流水号
  15. */
  16. private String bizNO;
  17. /**
  18. * 服务类名
  19. */
  20. private String className;
  21. /**
  22. * 服务方法名
  23. */
  24. private String methodName;
  25. /**
  26. * 服务版本号
  27. */
  28. private String serviceVersion;
  29. /**
  30. * 参数类型列表
  31. */
  32. private Class<?>[] paramTypes;
  33. /**
  34. * 参数值列表
  35. */
  36. private Object[] paramValues;
  37. }
  1. package com.summer.simplerpc.model;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. /**
  5. * rpc处理结果
  6. *
  7. * @author summer
  8. * @version $Id: SimpleRpcResponse.java, v 0.1 2022年01月16日 5:52 PM summer Exp $
  9. */
  10. @Data
  11. public class SimpleRpcResponse implements Serializable {
  12. private static final long serialVersionUID = 7306531831668743451L;
  13. /**
  14. * 业务流水号
  15. */
  16. private String bizNO;
  17. /**
  18. * 错误结果提示消息
  19. */
  20. private String msg;
  21. /**
  22. * 实际结果
  23. */
  24. private Object data;
  25. }
  1. package com.summer.simplerpc.provider;
  2. import com.google.common.util.concurrent.ThreadFactoryBuilder;
  3. import com.summer.simplerpc.annotation.SimpleRpcProvider;
  4. import com.summer.simplerpc.io.RPCDecoder;
  5. import com.summer.simplerpc.io.RPCEncoder;
  6. import com.summer.simplerpc.registry.ServiceRegistry;
  7. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  8. import com.summer.simplerpc.util.ServiceUtils;
  9. import io.netty.bootstrap.ServerBootstrap;
  10. import io.netty.channel.ChannelFuture;
  11. import io.netty.channel.ChannelInitializer;
  12. import io.netty.channel.ChannelOption;
  13. import io.netty.channel.EventLoopGroup;
  14. import io.netty.channel.nio.NioEventLoopGroup;
  15. import io.netty.channel.socket.SocketChannel;
  16. import io.netty.channel.socket.nio.NioServerSocketChannel;
  17. import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.springframework.beans.BeansException;
  20. import org.springframework.beans.factory.InitializingBean;
  21. import org.springframework.beans.factory.config.BeanPostProcessor;
  22. import java.util.Map;
  23. import java.util.concurrent.*;
  24. /**
  25. * rpc provider功能实现。
  26. *
  27. * 负责扫描服务provider注解bean,注册服务到注册中心,启动netty监听。
  28. * 提供RPC请求实际处理。
  29. *
  30. * @author summer
  31. * @version $Id: SimpleRpcProviderBean.java, v 0.1 2022年01月16日 12:19 PM summer Exp $
  32. */
  33. @Slf4j
  34. public class SimpleRpcProviderBean implements InitializingBean, BeanPostProcessor {
  35. /**
  36. * 地址
  37. */
  38. private String address;
  39. /**
  40. * 服务注册中心
  41. */
  42. private ServiceRegistry serviceRegistry;
  43. /**
  44. * 服务提供bean的缓存map
  45. */
  46. private Map<String, Object> providerBeanMap = new ConcurrentHashMap<>(64);
  47. /**
  48. * 处理实际rpc请求的线程池
  49. */
  50. private static ThreadPoolExecutor rpcThreadPoolExecutor;
  51. private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("simplerpc-provider-pool-%d").build();
  52. /**
  53. * netty相关
  54. */
  55. private EventLoopGroup bossGroup = null;
  56. private EventLoopGroup workerGroup = null;
  57. /**
  58. * 构造函数
  59. *
  60. * @param address 地址
  61. * @param serviceRegistry 服务注册中心
  62. */
  63. public SimpleRpcProviderBean(String address, ServiceRegistry serviceRegistry) {
  64. this.address = address;
  65. this.serviceRegistry = serviceRegistry;
  66. }
  67. @Override
  68. public void afterPropertiesSet() throws Exception {
  69. //启动netty服务监听
  70. new Thread(() -> {
  71. try {
  72. startNettyServer();
  73. } catch (InterruptedException e) {
  74. log.error("startNettyServer exception,", e);
  75. }
  76. }).start();
  77. }
  78. /**
  79. * 提交rpc处理任务
  80. *
  81. * @param task 任务
  82. */
  83. public static void submit(Runnable task) {
  84. if (rpcThreadPoolExecutor == null) {
  85. synchronized (SimpleRpcProviderBean.class) {
  86. if (rpcThreadPoolExecutor == null) {
  87. rpcThreadPoolExecutor = new ThreadPoolExecutor(100, 100,
  88. 600L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000),
  89. threadFactory);
  90. }
  91. }
  92. }
  93. rpcThreadPoolExecutor.submit(task);
  94. }
  95. /**
  96. * 启动netty服务监听
  97. *
  98. * @throws InterruptedException
  99. */
  100. private void startNettyServer() throws InterruptedException {
  101. if (workerGroup != null && bossGroup != null) {
  102. return;
  103. }
  104. log.info("startNettyServer begin");
  105. bossGroup = new NioEventLoopGroup();
  106. workerGroup = new NioEventLoopGroup();
  107. ServerBootstrap serverBootstrap = new ServerBootstrap();
  108. serverBootstrap.group(bossGroup, workerGroup)
  109. .channel(NioServerSocketChannel.class)
  110. .childHandler(new ChannelInitializer<SocketChannel>() {
  111. @Override
  112. protected void initChannel(SocketChannel socketChannel) {
  113. socketChannel.pipeline()
  114. .addLast(new LengthFieldBasedFrameDecoder(65535,0,4,0,0))
  115. .addLast(new RPCDecoder())
  116. .addLast(new RPCEncoder())
  117. .addLast(new SimpleRpcProviderNettyHandler(providerBeanMap))
  118. ;
  119. }
  120. })
  121. .option(ChannelOption.SO_BACKLOG, 512)
  122. .childOption(ChannelOption.SO_KEEPALIVE, true);
  123. String[] array = address.split(":");
  124. String host = array[0];
  125. int port = Integer.parseInt(array[1]);
  126. //启动服务
  127. ChannelFuture future = serverBootstrap.bind(host, port).sync();
  128. log.info(String.format("startNettyServer,host=%s,port=%s", host, port));
  129. future.channel().closeFuture().sync();
  130. }
  131. @Override
  132. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  133. return bean;
  134. }
  135. @Override
  136. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  137. //获取bean上的注解
  138. SimpleRpcProvider simpleRpcProvider = bean.getClass().getAnnotation(SimpleRpcProvider.class);
  139. if (simpleRpcProvider == null) {
  140. //无注解直接return原始的bean
  141. return bean;
  142. }
  143. //缓存保存
  144. String serviceName = simpleRpcProvider.serviceInterface().getName();
  145. String version = simpleRpcProvider.serviceVersion();
  146. providerBeanMap.put(ServiceUtils.buildServiceKey(serviceName, version), bean);
  147. log.info("postProcessAfterInitialization find a simpleRpcProvider[" + serviceName + "," + version + "]");
  148. //将服务注册到注册中心
  149. String[] addressArray = address.split(ServiceUtils.SPLIT_CHAR);
  150. String host = addressArray[0];
  151. String port = addressArray[1];
  152. ServiceMetaConfig serviceMetaConfig = new ServiceMetaConfig();
  153. serviceMetaConfig.setAddress(host);
  154. serviceMetaConfig.setName(serviceName);
  155. serviceMetaConfig.setVersion(version);
  156. serviceMetaConfig.setPort(Integer.parseInt(port));
  157. try {
  158. serviceRegistry.register(serviceMetaConfig);
  159. log.info("register service success,serviceMetaConfig=" + serviceMetaConfig.toString());
  160. } catch (Exception e) {
  161. log.error("register service fail,serviceMetaConfig=" + serviceMetaConfig.toString(), e);
  162. }
  163. return bean;
  164. }
  165. }
  1. package com.summer.simplerpc.provider;
  2. import com.summer.simplerpc.model.SimpleRpcRequest;
  3. import com.summer.simplerpc.model.SimpleRpcResponse;
  4. import com.summer.simplerpc.util.ServiceUtils;
  5. import io.netty.channel.ChannelFutureListener;
  6. import io.netty.channel.ChannelHandlerContext;
  7. import io.netty.channel.SimpleChannelInboundHandler;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.springframework.cglib.reflect.FastClass;
  10. import java.util.Map;
  11. /**
  12. * RPC核心处理逻辑handler
  13. *
  14. * @author summer
  15. * @version $Id: SimpleRpcProviderNettyHandler.java, v 0.1 2022年01月16日 5:36 PM summer Exp $
  16. */
  17. @Slf4j
  18. public class SimpleRpcProviderNettyHandler extends SimpleChannelInboundHandler<SimpleRpcRequest> {
  19. /**
  20. * 提供rpc服务的实例缓存map
  21. */
  22. private Map<String, Object> handlerMap;
  23. /**
  24. * 构造函数
  25. *
  26. * @param handlerMap
  27. */
  28. public SimpleRpcProviderNettyHandler(Map<String, Object> handlerMap) {
  29. this.handlerMap = handlerMap;
  30. }
  31. @Override
  32. protected void channelRead0(ChannelHandlerContext channelHandlerContext, SimpleRpcRequest simpleRpcRequest) throws Exception {
  33. SimpleRpcProviderBean.submit(() -> {
  34. log.debug("Receive rpc request {}", simpleRpcRequest.getBizNO());
  35. SimpleRpcResponse simpleRpcResponse = new SimpleRpcResponse();
  36. simpleRpcResponse.setBizNO(simpleRpcRequest.getBizNO());
  37. try {
  38. Object result = doHandle(simpleRpcRequest);
  39. simpleRpcResponse.setData(result);
  40. } catch (Throwable throwable) {
  41. simpleRpcResponse.setMsg(throwable.toString());
  42. log.error("handle rpc request error", throwable);
  43. }
  44. channelHandlerContext.writeAndFlush(simpleRpcResponse).addListener(
  45. (ChannelFutureListener) channelFuture ->
  46. log.info("return response for request " + simpleRpcRequest.getBizNO() + ",simpleRpcResponse=" + simpleRpcResponse));
  47. });
  48. }
  49. /**
  50. * 通过反射,执行实际的rpc请求
  51. * @param simpleRpcRequest
  52. * @return
  53. */
  54. private Object doHandle(SimpleRpcRequest simpleRpcRequest) throws Exception {
  55. String key = ServiceUtils.buildServiceKey(simpleRpcRequest.getClassName(), simpleRpcRequest.getServiceVersion());
  56. if (handlerMap == null || handlerMap.get(key) == null) {
  57. log.error("doHandle,the provider {0} not exist,", simpleRpcRequest.getClassName(), simpleRpcRequest.getServiceVersion());
  58. throw new RuntimeException("the provider not exist");
  59. }
  60. log.info("doHandle,simpleRpcRequest=" + simpleRpcRequest.toString());
  61. Object provider = handlerMap.get(key);
  62. //通过动态代理执行实际的调用
  63. FastClass fastClass = FastClass.create(provider.getClass());
  64. return fastClass.invoke(fastClass.getIndex(simpleRpcRequest.getMethodName(), simpleRpcRequest.getParamTypes()),
  65. provider, simpleRpcRequest.getParamValues());
  66. }
  67. }
  1. package com.summer.simplerpc.provider;
  2. import com.summer.simplerpc.model.RpcCommonProperty;
  3. import com.summer.simplerpc.registry.ServiceRegistry;
  4. import com.summer.simplerpc.registry.cache.ServiceProviderCache;
  5. import com.summer.simplerpc.registry.cache.ServiceProviderLocalCache;
  6. import com.summer.simplerpc.registry.zk.ZkServiceRegistry;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Configuration;
  10. /**
  11. * rpc provider starter
  12. *
  13. * @author summer
  14. * @version $Id: SimplerRpcProviderAutoConfiguration.java, v 0.1 2022年01月16日 6:19 PM summer Exp $
  15. */
  16. @Configuration
  17. @Slf4j
  18. public class SimplerRpcProviderAutoConfiguration {
  19. @Bean
  20. public SimpleRpcProviderBean initRpcProvider() throws Exception {
  21. RpcCommonProperty rpcCommonProperty = new RpcCommonProperty();
  22. rpcCommonProperty.setServiceAddress("127.0.0.1:50001");
  23. rpcCommonProperty.setRegistryAddress("127.0.0.1:2181");
  24. log.info("===================SimplerRpcProviderAutoConfiguration init,rpcCommonProperty=" + rpcCommonProperty.toString());
  25. ServiceProviderCache serviceProviderCache = new ServiceProviderLocalCache();
  26. ServiceRegistry zkServiceRegistry = new ZkServiceRegistry(rpcCommonProperty.getRegistryAddress(), serviceProviderCache);
  27. return new SimpleRpcProviderBean(rpcCommonProperty.getServiceAddress(), zkServiceRegistry);
  28. }
  29. }
  1. package com.summer.simplerpc.registry;
  2. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  3. /**
  4. * 注册中心服务接口定义
  5. *
  6. * @author summer
  7. * @version $Id: ServiceRegistry.java, v 0.1 2022年01月16日 10:56 AM summer Exp $
  8. */
  9. public interface ServiceRegistry {
  10. /**
  11. * 注册服务
  12. *
  13. * @param serviceMetaConfig 服务元数据配置
  14. * @throws Exception
  15. */
  16. void register(ServiceMetaConfig serviceMetaConfig) throws Exception;
  17. /**
  18. * 取消注册服务
  19. *
  20. * @param serviceMetaConfig 服务元数据配置
  21. * @throws Exception
  22. */
  23. void unRegister(ServiceMetaConfig serviceMetaConfig) throws Exception;
  24. /**
  25. * 服务发现
  26. *
  27. * @param serviceName 服务名
  28. * @return
  29. * @throws Exception
  30. */
  31. ServiceMetaConfig discovery(String serviceName) throws Exception;
  32. }
  1. package com.summer.simplerpc.registry.model;
  2. import lombok.Data;
  3. /**
  4. * 服务元数据配置领域模型
  5. *
  6. * @author summer
  7. * @version $Id: ServiceMetaConfig.java, v 0.1 2022年01月16日 10:58 AM summer Exp $
  8. */
  9. @Data
  10. public class ServiceMetaConfig {
  11. /**
  12. * 服务名
  13. */
  14. private String name;
  15. /**
  16. * 服务版本
  17. */
  18. private String version;
  19. /**
  20. * 服务地址
  21. */
  22. private String address;
  23. /**
  24. * 服务端口
  25. */
  26. private Integer port;
  27. }
  1. package com.summer.simplerpc.registry.zk;
  2. import com.summer.simplerpc.registry.cache.ServiceProviderCache;
  3. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  4. import com.summer.simplerpc.registry.ServiceRegistry;
  5. import com.summer.simplerpc.util.ServiceUtils;
  6. import org.apache.curator.framework.CuratorFramework;
  7. import org.apache.curator.framework.CuratorFrameworkFactory;
  8. import org.apache.curator.retry.ExponentialBackoffRetry;
  9. import org.apache.curator.x.discovery.*;
  10. import org.apache.curator.x.discovery.details.JsonInstanceSerializer;
  11. import org.apache.curator.x.discovery.strategies.RoundRobinStrategy;
  12. /**
  13. * 服务注册中心-zk实现
  14. *
  15. * @author summer
  16. * @version $Id: ZkServiceRegistry.java, v 0.1 2022年01月16日 11:07 AM summer Exp $
  17. */
  18. public class ZkServiceRegistry implements ServiceRegistry {
  19. /**
  20. * zk base path
  21. */
  22. private final static String ZK_BASE_PATH = "/simplerpc";
  23. /**
  24. * serviceProvider锁
  25. */
  26. private final Object lock = new Object();
  27. /**
  28. * zk framework client
  29. */
  30. private CuratorFramework client;
  31. /**
  32. * 服务发现
  33. */
  34. private ServiceDiscovery<ServiceMetaConfig> serviceDiscovery;
  35. /**
  36. * serviceProvider缓存
  37. */
  38. private ServiceProviderCache serviceProviderCache;
  39. /**
  40. * 构造函数
  41. *
  42. * @param address 地址
  43. */
  44. public ZkServiceRegistry(String address, ServiceProviderCache serviceProviderCache) throws Exception {
  45. this.client = CuratorFrameworkFactory.newClient(address, new ExponentialBackoffRetry(1000, 3));
  46. this.client.start();
  47. this.serviceProviderCache = serviceProviderCache;
  48. JsonInstanceSerializer<ServiceMetaConfig> serializer = new JsonInstanceSerializer<>(ServiceMetaConfig.class);
  49. serviceDiscovery = ServiceDiscoveryBuilder.builder(ServiceMetaConfig.class)
  50. .client(client)
  51. .serializer(serializer)
  52. .basePath(ZK_BASE_PATH)
  53. .build();
  54. serviceDiscovery.start();
  55. }
  56. @Override
  57. public void register(ServiceMetaConfig serviceMetaConfig) throws Exception {
  58. ServiceInstanceBuilder<ServiceMetaConfig> serviceInstanceBuilder = ServiceInstance.builder();
  59. ServiceInstance<ServiceMetaConfig> serviceInstance = serviceInstanceBuilder
  60. .name(ServiceUtils.buildServiceKey(serviceMetaConfig.getName(), serviceMetaConfig.getVersion()))
  61. .address(serviceMetaConfig.getAddress())
  62. .port(serviceMetaConfig.getPort())
  63. .payload(serviceMetaConfig)
  64. .uriSpec(new UriSpec("{scheme}://{address}:{port}"))
  65. .build();
  66. serviceDiscovery.registerService(serviceInstance);
  67. }
  68. @Override
  69. public void unRegister(ServiceMetaConfig serviceMetaConfig) throws Exception {
  70. ServiceInstanceBuilder<ServiceMetaConfig> serviceInstanceBuilder = ServiceInstance.builder();
  71. ServiceInstance<ServiceMetaConfig> serviceInstance = serviceInstanceBuilder
  72. .name(ServiceUtils.buildServiceKey(serviceMetaConfig.getName(), serviceMetaConfig.getVersion()))
  73. .address(serviceMetaConfig.getAddress())
  74. .port(serviceMetaConfig.getPort())
  75. .payload(serviceMetaConfig)
  76. .uriSpec(new UriSpec("{scheme}://{address}:{port}"))
  77. .build();
  78. serviceDiscovery.unregisterService(serviceInstance);
  79. }
  80. @Override
  81. public ServiceMetaConfig discovery(String serviceName) throws Exception {
  82. //先读缓存
  83. ServiceProvider<ServiceMetaConfig> serviceProvider = serviceProviderCache.queryCache(serviceName);
  84. //缓存miss,需要调serviceDiscovery
  85. if (serviceProvider == null) {
  86. synchronized (lock) {
  87. serviceProvider = serviceDiscovery.serviceProviderBuilder()
  88. .serviceName(serviceName)
  89. .providerStrategy(new RoundRobinStrategy<>())
  90. .build();
  91. serviceProvider.start();
  92. //更新缓存
  93. serviceProviderCache.updateCache(serviceName, serviceProvider);
  94. }
  95. }
  96. ServiceInstance<ServiceMetaConfig> serviceInstance = serviceProvider.getInstance();
  97. return serviceInstance != null ? serviceInstance.getPayload() : null;
  98. }
  99. }
  1. package com.summer.simplerpc.registry.cache;
  2. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  3. import org.apache.curator.x.discovery.ServiceProvider;
  4. /**
  5. *
  6. * @author summer
  7. * @version $Id: ServiceProviderCache.java, v 0.1 2022年01月16日 11:41 AM summer Exp $
  8. */
  9. public interface ServiceProviderCache {
  10. /**
  11. * 查询缓存
  12. * @param serviceName
  13. * @return
  14. */
  15. ServiceProvider<ServiceMetaConfig> queryCache(String serviceName);
  16. /**
  17. * 更新缓存
  18. *
  19. * @param serviceName 服务名
  20. * @param serviceProvider 服务provider
  21. * @return
  22. */
  23. void updateCache(String serviceName, ServiceProvider<ServiceMetaConfig> serviceProvider);
  24. }
  1. package com.summer.simplerpc.registry.cache;
  2. import com.summer.simplerpc.registry.model.ServiceMetaConfig;
  3. import org.apache.curator.x.discovery.ServiceProvider;
  4. import java.util.Map;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. /**
  7. * 本地缓存实现
  8. *
  9. * @author summer
  10. * @version $Id: ServiceProviderLocalCache.java, v 0.1 2022年01月16日 11:43 AM summer Exp $
  11. */
  12. public class ServiceProviderLocalCache implements ServiceProviderCache {
  13. /**
  14. * 本地缓存map
  15. */
  16. private Map<String, ServiceProvider<ServiceMetaConfig>> serviceProviderMap = new ConcurrentHashMap<>();
  17. @Override
  18. public ServiceProvider<ServiceMetaConfig> queryCache(String serviceName) {
  19. return serviceProviderMap.get(serviceName);
  20. }
  21. @Override
  22. public void updateCache(String serviceName, ServiceProvider<ServiceMetaConfig> serviceProvider) {
  23. serviceProviderMap.put(serviceName, serviceProvider);
  24. }
  25. }
  1. package com.summer.simplerpc.util;
  2. /**
  3. * 服务相关通用工具类
  4. *
  5. * @author summer
  6. * @version $Id: ServiceUtils.java, v 0.1 2022年01月16日 11:28 AM summer Exp $
  7. */
  8. public class ServiceUtils {
  9. /**
  10. * 分隔符
  11. */
  12. public final static String SPLIT_CHAR = ":";
  13. /**
  14. * 服务唯一标识key组装
  15. *
  16. * @param serviceName 服务名
  17. * @param serviceVersion 服务版本
  18. * @return
  19. */
  20. public final static String buildServiceKey(String serviceName, String serviceVersion) {
  21. return String.join(SPLIT_CHAR, serviceName, serviceVersion);
  22. }
  23. }
  1. package com.summer.simplerpc;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class SimplerpcApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run(SimplerpcApplication.class, args);
  8. }
  9. }
  1. summer.simplerpc.service.address=127.0.0.1:50001
  2. summer.simplerpc.service.registry.type=zookeeper
  3. summer.simplerpc.service.registry.address=127.0.0.1:2181
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starters</artifactId>
  8. <version>1.5.2.RELEASE</version>
  9. </parent>
  10. <groupId>com.summer</groupId>
  11. <artifactId>simplerpc-starter</artifactId>
  12. <version>0.0.1-SNAPSHOT</version>
  13. <name>simplerpc-starter</name>
  14. <description>Demo project for Spring Boot</description>
  15. <properties>
  16. <java.version>1.8</java.version>
  17. <spring-boot.version>2.2.1.RELEASE</spring-boot.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-dependencies</artifactId>
  23. <version>${spring-boot.version}</version>
  24. <type>pom</type>
  25. <scope>import</scope>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-web</artifactId>
  30. <version>${spring-boot.version}</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-configuration-processor</artifactId>
  35. <version>${spring-boot.version}</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.projectlombok</groupId>
  39. <artifactId>lombok</artifactId>
  40. <version>1.16.22</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.apache.curator</groupId>
  44. <artifactId>curator-x-discovery-server</artifactId>
  45. <version>2.9.1</version>
  46. <exclusions>
  47. <exclusion>
  48. <groupId>log4j</groupId>
  49. <artifactId>log4j</artifactId>
  50. </exclusion>
  51. </exclusions>
  52. </dependency>
  53. <dependency>
  54. <groupId>io.netty</groupId>
  55. <artifactId>netty-all</artifactId>
  56. <version>4.1.45.Final</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>cglib</groupId>
  60. <artifactId>cglib</artifactId>
  61. <version>3.1</version>
  62. <exclusions>
  63. <exclusion>
  64. <groupId>org.ow2.asm</groupId>
  65. <artifactId>asm</artifactId>
  66. </exclusion>
  67. </exclusions>
  68. </dependency>
  69. <dependency>
  70. <groupId>com.caucho</groupId>
  71. <artifactId>hessian</artifactId>
  72. <version>4.0.38</version>
  73. </dependency>
  74. <dependency>
  75. <groupId>org.springframework.boot</groupId>
  76. <artifactId>spring-boot-starter-test</artifactId>
  77. <scope>test</scope>
  78. <exclusions>
  79. <exclusion>
  80. <groupId>net.minidev</groupId>
  81. <artifactId>accessors-smart</artifactId>
  82. </exclusion>
  83. </exclusions>
  84. </dependency>
  85. </dependencies>
  86. <build>
  87. <plugins>
  88. <plugin>
  89. <groupId>org.springframework.boot</groupId>
  90. <artifactId>spring-boot-maven-plugin</artifactId>
  91. </plugin>
  92. </plugins>
  93. </build>
  94. </project>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/424583
推荐阅读
相关标签
  

闽ICP备14008679号