震惊,20岁的小伙子居然通过Netty手写了简单RPC框架

31 篇文章 0 订阅
5 篇文章 0 订阅

看我这标题,越来越觉得自己不去UC上班太浪费了,哈哈哈。。。本来这篇文章之前就要发布的,但是因为一些事情耽搁了

开始步入正题:手写RPC的简单实现

什么是RPC

常用的RPC框架有哪些

怎么实现

一丶什么是RPC

远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。RPC 是一种技术思想而非一种规范或协议。

RPC 的核心功能主要有这几个部分组成,分别是:客户端、客户端 Stub、网络传输模块、服务端 Stub、服务端等。

客户端:调用服务方。

客户端存根:存放服务端地址信息,将请求参数数据信息打包成网络消息,通过网络传输发送给服务端。

服务端存根:接收发送过来的请求消息并进行解包,然后再调用本地服务进行处理。

网络传输:通过TCP 或 HTTP进行网络传输。

RPC调用过程:

  客户端->通过本地调用的方式调用服务->客户端->接收调用请求后负责序列化->找到远程服务地址->将消息发送给服务端->服务端存根->收到消息后进行反序列化操作->根据结果调用本地的服务进行相关处理->本地服务业务处理->处理结果返回->序列化结果->将结果发送至消费方->客户端存根->接收到消息并反序列化->服务消费方得到最终结果。

二、常用的RPC框架有哪些

应用级的服务框架:阿里的 Dubbo、gRPC、SpringCloud和Thrift 等。

远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)等。

通信框架:MINA 和 Netty等。

下面重点介绍几种应用级服务框架:

Dubbo:之前阿里开源的一个极为出名的 RPC 框架,在很多互联网公司和企业应用中广泛使用。后面由Weex捐赠给 Apache,由Apache进行孵化,现如今Apache Dubbo从孵化器毕业。(dubbox是由当当在阿里的基础上升级的)

gRPC:是 Google 的产物,基于 HTTP 协议实现的,底层使用到了 Netty 框架的支持。

SpringCloud:spring的产物,熟悉spring的应该知道,老熟人了。与其说是框架,不如说是是一系列框架的有序集合。

Thrift:是由 Facebook 开源的一个 RPC 框架,现在已经挂在 apache下了。

 

三、怎么实现:

如果想要自己实现一个 RPC,最简单的方式要实现三个技术点,分别是:

服务寻址

数据流的序列化和反序列化

网络传输

本项目的环境

JAVA11,Spring5.1,netty4

话不多说,开始动手。上代码

发布生产者类

public class ProviderBean implements ApplicationContextAware {
   private String interfacea; 
   private String mapping;    
   private String alias;  
    protected void Export() {
        System.out.format("生产者信息", interfacea, mapping, alias);
    }
private Logger logger = LoggerFactory.getLogger(ProviderBean.class);
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    RpcProviderConfig rpcProviderConfig = new RpcProviderConfig();
    rpcProviderConfig.setNozzle(interfacea);
    rpcProviderConfig.setRef(mapping);
    rpcProviderConfig.setAlias(alias);
    rpcProviderConfig.setHost(LocalServerInfo.LOCAL_HOST);
    rpcProviderConfig.setPort(LocalServerInfo.LOCAL_PORT);
    long count = RedisRegistryCenter.registryProvider(interfacea, alias, JSON.toJSONString(rpcProviderConfig));
    logger.info("", interfacea, alias, count);
}
}

消费者类

 

@SuppressWarnings("rawtypes")
public class ConsumerBean<T> implements FactoryBean {
    private ChannelFuture channelFuture;
    private RpcProviderConfig rpcProviderConfig;
    private String interfaceb;
    private String alias;  
    protected synchronized T refer() {
        System.out.format(" \r\n", interfaceb, alias);
        return null;
    }
    public Object getObject() throws Exception {
        if (null == rpcProviderConfig) {
            String infoStr = RedisRegistryCenter.obtainProvider(interfaceb, alias);
            rpcProviderConfig = JSON.parseObject(infoStr, RpcProviderConfig.class);
        }
        Assert.isTrue(null != rpcProviderConfig);
        if (null == channelFuture) {
            ClientSocket clientSocket = new ClientSocket(rpcProviderConfig.getHost(), rpcProviderConfig.getPort());
            new Thread(clientSocket).start();
            for (int i = 0; i < 100; i++) {
                if (null != channelFuture) break;
                Thread.sleep(500);
                channelFuture = clientSocket.getFuture();
            }
        }
        Assert.isTrue(null != channelFuture);
        Request request = new Request();
        request.setChannel(channelFuture.channel());
        request.setNozzle(interfaceb);
        request.setRef(rpcProviderConfig.getRef());
        request.setAlias(alias);
        return (T) JDKProxy.getProxy(ClassLoaderUtils.forName(interfaceb), request);
    }
    public Class<?> getObjectType() {
        try {
            return ClassLoaderUtils.forName(interfaceb);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }
    public boolean isSingleton() {
        return true;
    }
}

通讯这块:

public class ServerBean implements ApplicationContextAware {
   private String host; 
   private int port;     
   private Logger logger = LoggerFactory.getLogger(ServerBean.class);
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          logger.info("启动注册中心 ...");
          RedisRegistryCenter.init(host, port);
          logger.info("启动注册中心完成 {} {}", host, port);
          logger.info("初始化生产端服务 ...");
          ServerSocket serverSocket = new ServerSocket(applicationContext);
          Thread thread = new Thread(serverSocket);
          thread.start();
          while (!serverSocket.isActiveSocketServer()) {
              try {
                  Thread.sleep(500);
              } catch (InterruptedException ignore) {
              }
          }
          logger.info("初始化生产端服务完成 ", LocalServerInfo.LOCAL_HOST, LocalServerInfo.LOCAL_PORT);
      }
}

解析器

public class DefinitionParser implements BeanDefinitionParser {
    private final Class<?> beanClass;
    DefinitionParser(Class<?> beanClass) {
        this.beanClass = beanClass;
    }
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);
        String beanName = element.getAttribute("id");
        parserContext.getRegistry().registerBeanDefinition(beanName, beanDefinition);
        for (Method method : beanClass.getMethods()) {
            if (!isProperty(method, beanClass)) continue;
            String name = method.getName();
            String methodName = name.substring(3, 4).toLowerCase() + name.substring(4);
            String value = element.getAttribute(methodName);
            beanDefinition.getPropertyValues().addPropertyValue(methodName, value);
        }
        return beanDefinition;
    }
    private boolean isProperty(Method method, Class beanClass) {
        String methodName = method.getName();
        boolean flag = methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 1;
        Method getter = null;
        if (!flag) return false;
        Class<?> type = method.getParameterTypes()[0];
        try {
            getter = beanClass.getMethod("get" + methodName.substring(3));
        } catch (Exception e) {
          e.printStackTrace();
        }
        if (null == getter) {
            try {
                getter = beanClass.getMethod("is" + methodName.substring(3));
            } catch (Exception e) {
              e.printStackTrace();
            }
        }
        flag = getter != null && Modifier.isPublic(getter.getModifiers()) && type.equals(getter.getReturnType());
        return flag;
    }
}
//命名空间
public class NamespaceHandler extends NamespaceHandlerSupport {
    public void init() {
        registerBeanDefinitionParser("consumer", new DefinitionParser(ConsumerBean.class));
        registerBeanDefinitionParser("provider", new DefinitionParser(ProviderBean.class));
        registerBeanDefinitionParser("server", new DefinitionParser(ServerBean.class));
    }
}

自定义XML的约束

dtd或者xsd显得稍微规范一点,自己想怎么约束就怎么约束

 

接下来到通讯这块,选择netty作为我们的socket框架,采用future方式进行通信。

客户端套接字

public class ClientSocket implements Runnable {
    private ChannelFuture future;
    private String inetHost;
    private int inetPort;
    public ClientSocket(String inetHost, int inetPort) {
        this.inetHost = inetHost;
        this.inetPort = inetPort;
    }
    public void run() {
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.AUTO_READ, true);
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(
                            new RpcDecoder(Response.class),
                            new RpcEncoder(Request.class),
                            new MyClientHandler());
                }
            });
            ChannelFuture f = b.connect(inetHost, inetPort).sync();
            this.future = f;
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }
    public ChannelFuture getFuture() {
        return future;
    }
    public void setFuture(ChannelFuture future) {
        this.future = future;
    }
}

客户端处理器

​​​​​​​

public class MyClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object obj) throws Exception {
        Response msg = (Response) obj;
        String requestId = msg.getRequestId();
        SyncWriteFuture future = (SyncWriteFuture) SyncWriteMap.syncKey.get(requestId);
        if (future != null) {
            future.setResponse(msg);
        }
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

Redis作为注册中心

public class RedisRegistryCenter {
    private static Jedis jedis;
    public static void init(String host, int port) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(5);
        config.setTestOnBorrow(false);
        JedisPool jedisPool = new JedisPool(config, host, port);
        jedis = jedisPool.getResource();
    }
    public static Long registryProvider(String nozzle, String alias, String info) {
        return jedis.sadd(nozzle + "_" + alias, info);
    }
    public static String obtainProvider(String nozzle, String alias) {
        return jedis.srandmember(nozzle + "_" + alias);
    }
    public static Jedis jedis() {
        return jedis;
    }
}

服务端套接字

public class ServerSocket implements Runnable {
    private ChannelFuture f;
    private transient ApplicationContext applicationContext;
    public ServerSocket(ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }
    public boolean isActiveSocketServer() {
        try {
            if (f != null) {
                return f.channel().isActive();
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }
    public void run() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(
                                    new RpcDecoder(Request.class),
                                    new RpcEncoder(Response.class),
                                    new MyServerHandler(applicationContext));
                        }
                    });
            int port = 22201;
            while (NetUtil.isPortUsing(port)) {
                port++;
            }
            LocalServerInfo.LOCAL_HOST = NetUtil.getHost();
            LocalServerInfo.LOCAL_PORT = port;
            this.f = b.bind(port).sync();
            this.f.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

服务端处理器

public class MyServerHandler extends ChannelInboundHandlerAdapter {
    private ApplicationContext applicationContext;
    MyServerHandler(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    public void channelRead(ChannelHandlerContext ctx, Object obj) {
        try {
            Request msg = (Request) obj;
            Class<?> classType = ClassLoaderUtils.forName(msg.getNozzle());
            Method addMethod = classType.getMethod(msg.getMethodName(), msg.getParamTypes());
            Object objectBean = applicationContext.getBean(msg.getRef());
            Object result = addMethod.invoke(objectBean, msg.getArgs());
            Response request = new Response();
            request.setRequestId(msg.getRequestId());
            request.setResult(result);
            ctx.writeAndFlush(request);
            ReferenceCountUtil.release(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }
}

请求类

public class Request {
    private transient Channel channel;
    private String requestId;
    private String methodName;
    private Class[] paramTypes; 
    private Object[] args; 
    private String nozzle; 
    private String ref;   
    private String alias; 
    public Channel getChannel() {
        return channel;
    }
    public void setChannel(Channel channel) {
        this.channel = channel;
    }
    public String getRequestId() {
        return requestId;
    }
    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public Class[] getParamTypes() {
        return paramTypes;
    }
    public void setParamTypes(Class[] paramTypes) {
        this.paramTypes = paramTypes;
    }
    public Object[] getArgs() {
        return args;
    }
    public void setArgs(Object[] args) {
        this.args = args;
    }
    public String getNozzle() {
        return nozzle;
    }
    public void setNozzle(String nozzle) {
        this.nozzle = nozzle;
    }
    public String getRef() {
        return ref;
    }
    public void setRef(String ref) {
        this.ref = ref;
    }
    public String getAlias() {
        return alias;
    }
    public void setAlias(String alias) {
        this.alias = alias;
    }

响应类

public class Response {
    private transient Channel channel;
    private String requestId;
    private Object result;
    public Channel getChannel() {
        return channel;
    }
    public void setChannel(Channel channel) {
        this.channel = channel;
    }
    public String getRequestId() {
        return requestId;
    }
    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
    public Object getResult() {
        return result;
    }
    public void setResult(Object result) {
        this.result = result;
    }
}

给RPC进行编码​​​​​​​

public class RpcEncoder extends MessageToByteEncoder {
    private Class<?> genericClass;
    public RpcEncoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }
    protected void encode(ChannelHandlerContext ctx, Object in, ByteBuf out)  {
        if (genericClass.isInstance(in)) {
            byte[] data = SerializationUtil.serialize(in);
            out.writeInt(data.length);
            out.writeBytes(data);
        }
    }
}

RPC解码器​​​​​​​

public class RpcDecoder extends ByteToMessageDecoder {
    private Class<?> genericClass;
    public RpcDecoder(Class<?> genericClass) {
        this.genericClass = genericClass;
    }
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() < 4) {
            return;
        }
        in.markReaderIndex();
        int dataLength = in.readInt();
        if (in.readableBytes() < dataLength) {
            in.resetReaderIndex();
            return;
        }
        byte[] data = new byte[dataLength];
        in.readBytes(data);
        out.add(SerializationUtil.deserialize(data, genericClass));
    }
}

输出​​​​​​​

public class SyncWrite {
    public Response writeAndSync(final Channel channel, final Request request, final long timeout) throws Exception {
        if (channel == null) {
            throw new NullPointerException("channel");
        }
        if (request == null) {
            throw new NullPointerException("request");
        }
        if (timeout <= 0) {
            throw new IllegalArgumentException("timeout <= 0");
        }
        String requestId = UUID.randomUUID().toString();
        request.setRequestId(requestId);
        WriteFuture<Response> future = new SyncWriteFuture(request.getRequestId());
        SyncWriteMap.syncKey.put(request.getRequestId(), future);
        Response response = doWriteAndSync(channel, request, timeout, future);
        SyncWriteMap.syncKey.remove(request.getRequestId());
        return response;
    }
    private Response doWriteAndSync(final Channel channel, final Request request, final long timeout, final WriteFuture<Response> writeFuture) throws Exception {
        channel.writeAndFlush(request).addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) {
                writeFuture.setWriteResult(future.isSuccess());
                writeFuture.setCause(future.cause());
                if (!writeFuture.isWriteSuccess()) {
                    SyncWriteMap.syncKey.remove(writeFuture.requestId());
                }
            }
        });
        Response response = writeFuture.get(timeout, TimeUnit.MILLISECONDS);
        if (response == null) {
            if (writeFuture.isTimeout()) {
                throw new TimeoutException();
            } else {
                // write exception
                throw new Exception(writeFuture.cause());
            }
        }
        return response;
    }
}

存放的容器

​​​​​​​

public class SyncWriteMap {
    public static Map<String, WriteFuture> syncKey = new ConcurrentHashMap<String, WriteFuture>();
}

缓冲接口和具体实现类​​​​​​​

public class SyncWriteFuture implements WriteFuture<Response> {
  private CountDownLatch latch = new CountDownLatch(1);
    private final long begin = System.currentTimeMillis();
    private long timeout;
    private Response response;
    private final String requestId;
    private boolean writeResult;
    private Throwable cause;
    private boolean isTimeout = false;
    public SyncWriteFuture(String requestId) {
        this.requestId = requestId;
    }
    public SyncWriteFuture(String requestId, long timeout) {
        this.requestId = requestId;
        this.timeout = timeout;
        writeResult = true;
        isTimeout = false;
    }
    public Throwable cause() {
        return cause;
    }
    public void setCause(Throwable cause) {
        this.cause = cause;
    }
    public boolean isWriteSuccess() {
        return writeResult;
    }


    public void setWriteResult(boolean result) {
        this.writeResult = result;
    }
    public String requestId() {
        return requestId;
    }
    public Response response() {
        return response;
    }
    public void setResponse(Response response) {
        this.response = response;
        latch.countDown();
    }
    public boolean cancel(boolean mayInterruptIfRunning) {
        return true;
    }
    public boolean isCancelled() {
        return false;
    }
    public boolean isDone() {
        return false;
    }
    public Response get() throws InterruptedException, ExecutionException {
        latch.wait();
        return response;
    }
    public Response get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        if (latch.await(timeout, unit)) {
            return response;
        }
        return null;
    }
    public boolean isTimeout() {
        if (isTimeout) {
            return isTimeout;
        }
        return System.currentTimeMillis() - begin > timeout;
    }
}
public class SyncWriteFuture implements WriteFuture<Response> {
  private CountDownLatch latch = new CountDownLatch(1);
    private final long begin = System.currentTimeMillis();
    private long timeout;
    private Response response;
    private final String requestId;
    private boolean writeResult;
    private Throwable cause;
    private boolean isTimeout = false;
    public SyncWriteFuture(String requestId) {
        this.requestId = requestId;
    }
    public SyncWriteFuture(String requestId, long timeout) {
        this.requestId = requestId;
        this.timeout = timeout;
        writeResult = true;
        isTimeout = false;
    }
    public Throwable cause() {
        return cause;
    }
    public void setCause(Throwable cause) {
        this.cause = cause;
    }
    public boolean isWriteSuccess() {
        return writeResult;
    }


    public void setWriteResult(boolean result) {
        this.writeResult = result;
    }
    public String requestId() {
        return requestId;
    }
    public Response response() {
        return response;
    }
    public void setResponse(Response response) {
        this.response = response;
        latch.countDown();
    }
    public boolean cancel(boolean mayInterruptIfRunning) {
        return true;
    }
    public boolean isCancelled() {
        return false;
    }
    public boolean isDone() {
        return false;
    }
    public Response get() throws InterruptedException, ExecutionException {
        latch.wait();
        return response;
    }
    public Response get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        if (latch.await(timeout, unit)) {
            return response;
        }
        return null;
    }
    public boolean isTimeout() {
        if (isTimeout) {
            return isTimeout;
        }
        return System.currentTimeMillis() - begin > timeout;
    }
}

动态代理调用​​​​​​​

public class JDKInvocationHandler implements InvocationHandler {
    private Request request;
    public JDKInvocationHandler(Request request) {
        this.request = request;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class[] paramTypes = method.getParameterTypes();
        if ("toString".equals(methodName) && paramTypes.length == 0) {
            return request.toString();
        } else if ("hashCode".equals(methodName) && paramTypes.length == 0) {
            return request.hashCode();
        } else if ("equals".equals(methodName) && paramTypes.length == 1) {
            return request.equals(args[0]);
        }
        request.setMethodName(methodName);
        request.setParamTypes(paramTypes);
        request.setArgs(args);
        request.setRef(request.getRef());
        Response response = new SyncWrite().writeAndSync(request.getChannel(), request, 5000);
        return response.getResult();
    }
}
}

代理​​​​​​​

public class JDKProxy {
    public static <T> T getProxy(Class<T> interfaceClass, Request request) throws Exception {
        InvocationHandler handler = new JDKInvocationHandler(request);
        ClassLoader classLoader = ClassLoaderUtils.getCurrentClassLoader();
        T result = (T) Proxy.newProxyInstance(classLoader, new Class[]{interfaceClass}, handler);
        return result;
    }

序列化工具类​​​​​​​

public class SerializationUtil {
    @SuppressWarnings("rawtypes")
  private static Map<Class<?>, Schema> cachedSchema = new ConcurrentHashMap();
    private static Objenesis objenesis = new ObjenesisStd();
    private SerializationUtil() {
    }
    @SuppressWarnings("unchecked")
  public static <T> byte[] serialize(T obj) {
    Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema schema = getSchema(cls);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }
    @SuppressWarnings("unchecked")
  public static <T> T deserialize(byte[] data, Class<T> cls) {
        try {
            T message = objenesis.newInstance(cls);
            Schema schema = getSchema(cls);
            ProtostuffIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
    @SuppressWarnings("rawtypes")
  private static <T> Schema getSchema(Class<T> cls) {
        Schema schema = (Schema) cachedSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            cachedSchema.put(cls, schema);
        }
        return schema;
    }
}
public class Constants {

    public static final char HIDE_KEY_PREFIX = '.';
    public static final char INTERNAL_KEY_PREFIX = '_';
}

字符串工具​​​​​​​

public class StringUtils {
    public static final String EMPTY = "";
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }
    public static boolean isNotEmpty(CharSequence cs) {
        return !StringUtils.isEmpty(cs);
    }
    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }
    public static boolean isNotBlank(CharSequence cs) {
        return !StringUtils.isBlank(cs);
    }
    public static String trim(String str) {
        return str == null ? null : str.trim();
    }
    public static String trimToNull(String str) {
        String ts = trim(str);
        return isEmpty(ts) ? null : ts;
    }
    public static String trimToEmpty(String str) {
        return str == null ? EMPTY : str.trim();
    }
    public static String toString(byte[] bytes, String charsetName) throws UnsupportedEncodingException {
        return charsetName == null ? new String(bytes) : new String(bytes, charsetName);
    }
    public static String defaultString(final String str) {
        return str == null ? EMPTY : str;
    }
    public static String[] split(String src, String separator) {
        if (isEmpty(separator)) {
            return new String[]{src};
        }
        if (isEmpty(src)) {
            return new String[0];
        }
        return src.split(separator, -1);
    }
    public static String[] splitWithCommaOrSemicolon(String src) {
        if (isEmpty(src)) {
            return new String[0];
        }
        String[] ss = split(src.replace(',', ';'), ";");
        List<String> list = new ArrayList<String>();
        for (String s : ss) {
            if (!isBlank(s)) {
                list.add(s.trim());
            }
        }
        return list.toArray(new String[list.size()]);
    }
    public static String join(String[] strings, String separator) {
        if (strings == null || strings.length == 0) {
            return EMPTY;
        }
        StringBuilder sb = new StringBuilder();
        for (String string : strings) {
            if (isNotBlank(string)) {
                sb.append(string).append(separator);
            }
        }
        return sb.length() > 0 ? sb.substring(0, sb.length() - separator.length()) : StringUtils.EMPTY;
    }
    public static String joinWithComma(String... strings) {
        return join(strings, ",");
    }
    public static boolean isValidParamKey(String paramkey) {
        char c = paramkey.charAt(0);
        return c != Constants.HIDE_KEY_PREFIX && c != Constants.INTERNAL_KEY_PREFIX;
    }
    public static boolean isInternalParamKey(String paramkey) {
        char c = paramkey.charAt(0);
        return c == Constants.INTERNAL_KEY_PREFIX;
    }
    public static String toString(Object o) {
        return o != null ? o.toString() : null;
    }
}

通讯工具​​​​​​​

public class NetUtil {
    public static boolean isPortUsing(int port) throws UnknownHostException {
        boolean flag = false;
        try {
            Socket socket = new Socket("localhost", port);
            socket.close();
            flag = true;
        } catch (IOException e) {
          e.printStackTrace();
        }
        return flag;
    }
    public static String getHost() throws UnknownHostException {
        return InetAddress.getLocalHost().getHostAddress();
    }
    public static void main(String[] args) throws UnknownHostException {
        NetUtil.isPortUsing(8080);
    }
    }

类加载工具​​​​​​​

public class ClassLoaderUtils {

    private static Set<Class> primitiveSet = new HashSet<Class>();
    static {
        primitiveSet.add(Integer.class);
        primitiveSet.add(Long.class);
        primitiveSet.add(Float.class);
        primitiveSet.add(Byte.class);
        primitiveSet.add(Short.class);
        primitiveSet.add(Double.class);
        primitiveSet.add(Character.class);
        primitiveSet.add(Boolean.class);
    }
    public static ClassLoader getCurrentClassLoader() {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        if (cl == null) {
            cl = ClassLoaderUtils.class.getClassLoader();
        }
        return cl == null ? ClassLoader.getSystemClassLoader() : cl;
    }
    public static ClassLoader getClassLoader(Class<?> clazz) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader != null) {
            return loader;
        }
        if (clazz != null) {
            loader = clazz.getClassLoader();
            if (loader != null) {
                return loader;
            }
            return clazz.getClassLoader();
        }
        return ClassLoader.getSystemClassLoader();
    }
    public static Class forName(String className)
            throws ClassNotFoundException {
        return forName(className, true);
    }
    public static Class forName(String className, boolean initialize)
            throws ClassNotFoundException {
        return Class.forName(className, initialize, getCurrentClassLoader());
    }
    public static Class forName(String className, ClassLoader cl)
            throws ClassNotFoundException {
        return Class.forName(className, true, cl);
    }
    public static <T> T newInstance(Class<T> clazz) throws Exception {
        if(primitiveSet.contains(clazz)){
            return null;
        }
        if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
            Constructor constructorList[] = clazz.getDeclaredConstructors();
            Constructor defaultConstructor = null;
            for (Constructor con : constructorList) {
                if (con.getParameterTypes().length == 1) {
                    defaultConstructor = con;
                    break;
                }
            }
            if (defaultConstructor != null) {
                if (defaultConstructor.isAccessible()) {
                    return (T) defaultConstructor.newInstance(new Object[]{null});
                } else {
                    try {
                        defaultConstructor.setAccessible(true);
                        return (T) defaultConstructor.newInstance(new Object[]{null});
                    } finally {
                        defaultConstructor.setAccessible(false);
                    }
                }
            } else {
                throw new Exception("The " + clazz.getCanonicalName() + " has no default constructor!");
            }
        }
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            Constructor<T> constructor = clazz.getDeclaredConstructor();
            if (constructor.isAccessible()) {
                throw new Exception("The " + clazz.getCanonicalName() + " has no default constructor!", e);
            } else {
                try {
                    constructor.setAccessible(true);
                    return constructor.newInstance();
                } finally {
                    constructor.setAccessible(false);
                }
            }
        }
    }
}

这篇文章,本来我是写了一个简单版的,就是简单的map做注册中心就完事了的。后面被一个京东六年的老哥怼了,经他指点的基础上完成了的中国。测试我就不写了。如果看不懂,就把代码抄下来。运行看效果,然后再慢慢看。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值