diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/Client.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/Client.java
index ad7f1271..c1199a8c 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/Client.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/Client.java
@@ -23,12 +23,35 @@ import cn.hippo4j.rpc.model.Response;
import java.io.Closeable;
/**
- * the client for RPC, Explain the role of the client in the request
+ *
CLIENT
+ * The highest level interface for the client, it does not care how to communicate with the server,
+ * nor can it know the specific connection information. The client plays the role of message producer
+ * in the whole connection.By sending a Request to the server ({@link Request}), the client will be
+ * able to communicate with the server. Wait for the server's Response ({@link Response})
+ *
METHOD
+ *
+ *
{@link #connection(Request)}
+ *
{@link #isActive()}
+ *
{@link #close()}
+ *
+ * You can usually use the client in this way:
+ *
+ *
+ * The client implements Closeable and supports automatic shutdown, However, you can manually
+ * disable it when you want to use it
*/
public interface Client extends Closeable {
/**
* Start the client and try to send and receive data
+ *
+ * @param request Request information, Requested methods and parameters
+ * @return response Response from server side
*/
Response connection(Request request);
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/ClientConnection.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/ClientConnection.java
index 43791228..5588d8e2 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/ClientConnection.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/ClientConnection.java
@@ -22,7 +22,7 @@ import cn.hippo4j.rpc.model.Request;
import cn.hippo4j.rpc.model.Response;
/**
- * Applicable to client connections
+ * Applicable to client connections
*/
public interface ClientConnection extends Connection {
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/NettyClientConnection.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/NettyClientConnection.java
index 293002d6..3a3b92e1 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/NettyClientConnection.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/NettyClientConnection.java
@@ -37,6 +37,7 @@ import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.util.LinkedList;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.locks.LockSupport;
/**
@@ -114,12 +115,12 @@ public class NettyClientConnection implements ClientConnection {
@Override
public void close() {
- if (this.channel == null) {
- return;
- }
- worker.shutdownGracefully();
- this.future.channel().close();
- this.channel.close();
+ Optional.ofNullable(this.channel)
+ .ifPresent(c -> {
+ worker.shutdownGracefully();
+ this.future.channel().close();
+ this.channel.close();
+ });
}
@Override
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/RPCClient.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/RPCClient.java
index abc3ed9e..76b4d8f9 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/RPCClient.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/client/RPCClient.java
@@ -23,7 +23,8 @@ import cn.hippo4j.rpc.model.Response;
import java.io.IOException;
/**
- * The client, which provides a closing mechanism, maintains a persistent connection if not closed
+ * The client, which provides a closing mechanism, maintains a persistent connection if not closed
+ * Delegate the method to the {@link ClientConnection} for implementation
*/
public class RPCClient implements Client {
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/coder/NettyDecoder.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/coder/NettyDecoder.java
deleted file mode 100644
index 42223e44..00000000
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/coder/NettyDecoder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cn.hippo4j.rpc.coder;
-
-import cn.hippo4j.rpc.exception.CoderException;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.serialization.ClassResolver;
-import io.netty.handler.codec.serialization.ObjectDecoder;
-
-/**
- * According to the decoder for java objects implemented by ObjectDecoder,
- * it is necessary to ensure that the transmitted objects can be serialized
- */
-public class NettyDecoder extends ObjectDecoder {
-
- public NettyDecoder(ClassResolver classResolver) {
- super(classResolver);
- }
-
- @Override
- protected Object decode(ChannelHandlerContext ctx, ByteBuf in) {
- ByteBuf byteBuf = in.retainedDuplicate();
- try {
- Object o = super.decode(ctx, in);
- if (o == null) {
- return byteBuf;
- } else {
- return o;
- }
- } catch (Exception e) {
- throw new CoderException("The encoding is abnormal, which may be caused by the failure of the transfer object to be deserialized");
- }
- }
-}
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/AbstractNettyTakeHandler.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/AbstractNettyTakeHandler.java
index 4cb61a28..9d037b33 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/AbstractNettyTakeHandler.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/AbstractNettyTakeHandler.java
@@ -24,6 +24,8 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
+import java.util.Optional;
+
/**
* the abstract base of {@link ConnectHandler} and {@link ChannelInboundHandlerAdapter}
*/
@@ -42,9 +44,10 @@ public abstract class AbstractNettyTakeHandler extends ChannelInboundHandlerAdap
if (channel.isActive()) {
ctx.close();
}
- if (cause != null) {
- throw new ConnectionException(cause);
- }
+ Optional.ofNullable(cause)
+ .ifPresent(t -> {
+ throw new ConnectionException(cause);
+ });
}
/**
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/Connection.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/Connection.java
index 77ce2211..0cb5a97d 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/Connection.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/Connection.java
@@ -20,7 +20,12 @@ package cn.hippo4j.rpc.handler;
import java.io.Closeable;
/**
- * Represents a network request connection and provides IO layer support
+ * Represents a network request connection and provides IO layer support
+ *
+ * This is not a strict and stateless Connection interface, it contains the necessary
+ * operations that should be done in the connection. It is more like integrating the
+ * connection and the connection channel together, so creating {@link Connection} is
+ * very resource intensive, for which caching is recommended
*/
public interface Connection extends Closeable {
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/HandlerManager.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/HandlerManager.java
index f4ebb4b9..cf72aea3 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/HandlerManager.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/handler/HandlerManager.java
@@ -17,6 +17,8 @@
package cn.hippo4j.rpc.handler;
+import cn.hippo4j.common.web.exception.IllegalException;
+import io.netty.channel.ChannelHandler;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -72,6 +74,14 @@ public interface HandlerManager {
* @return HandlerEntity
*/
default HandlerEntity getHandlerEntity(long order, T handler, String name) {
+ Class> cls = handler.getClass();
+ boolean b = cls.isAnnotationPresent(ChannelHandler.Sharable.class)
+ || HandlerManager.class.isAssignableFrom(cls);
+ if (!b) {
+ throw new IllegalException("Join the execution of the handler must add io.netty.channel.ChannelHandler." +
+ "Sharable annotations, Please for the handler class " + cls.getName() + " add io.netty.channel." +
+ "ChannelHandler.Sharable annotation");
+ }
return new HandlerEntity<>(order, handler, name);
}
diff --git a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/support/ClientFactoryBean.java b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/support/ClientFactoryBean.java
index b63e81b6..3b115bca 100644
--- a/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/support/ClientFactoryBean.java
+++ b/hippo4j-rpc/src/main/java/cn/hippo4j/rpc/support/ClientFactoryBean.java
@@ -17,6 +17,7 @@
package cn.hippo4j.rpc.support;
+import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.rpc.client.Client;
import cn.hippo4j.rpc.discovery.DiscoveryAdapter;
import cn.hippo4j.rpc.exception.ConnectionException;
@@ -30,10 +31,28 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.net.InetSocketAddress;
+import java.util.Optional;
/**
* A FactoryBean that builds interfaces to invoke proxy objects
* is responsible for managing the entire life cycle of the proxy objects
+ *
APPLICATION START
+ * When the application is started, the request initiator needs to complete the proxy of the calling interface,
+ * which ensures that the method can be requested to the server side when the method is called, rather than simply
+ * request an interface that cannot be instantiated. The classes involved in adding proxy to the interface are:
+ *
+ *
{@link NettyClientSupport}
+ *
{@link NettyProxyCenter}
+ *
{@link NettyClientPoolHandler}
+ *
+ *
AND SPRING
+ * In order to fully integrate {@link ClientFactoryBean} into the life cycle of spring beans,
+ * {@link ClientFactoryBean} also needs to implement the following interfaces:
+ *
+ *
{@link InitializingBean}
+ *
{@link ApplicationContextAware}
+ *
{@link DisposableBean}
+ *
*
* @deprecated With {@link cn.hippo4j.config.service.ThreadPoolAdapterService} structure, FactoryBean is not the best choice
*/
@@ -52,10 +71,16 @@ public class ClientFactoryBean implements FactoryBean