Add dependent
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.2.Final</version> </dependency> <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.10</version> </dependency>
Organization
Server
Packaging class information
public class ClassInfo implements Serializable { private static final long serialVersionUID = 1L; private String className; //类名 private String methodName;//方法名 private Class<?>[] types; //参数类型 private Object[] objects;//参数列表 public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Class<?>[] getTypes() { return types; } public void setTypes(Class<?>[] types) { this.types = types; } public Object[] getObjects() { return objects; } public void setObjects(Object[] objects) { this.objects = objects; } }
Server network processing server
public class NettyRPCServer { private int port; public NettyRPCServer(int port) { this.port = port; } public void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true) .localAddress(port).childHandler( new ChannelInitializer<SocketChannel>() { @Override protected void initChannel (the SocketChannel CH) throws Exception { the ChannelPipeline Pipeline ch.pipeline = (); // encoder pipeline.addLast ( "Encoder", new new ObjectEncoder ()); // decoder pipeline.addLast ( "decoder" , new new ObjectDecoder (Integer.MAX_VALUE, ClassResolvers.cacheDisabled (null))); // server class service processing pipeline.addLast(new InvokeHandler()); } }); ChannelFuture = serverBootstrap.bind Future (Port) .sync (); System.out.println("......server is ready......"); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new NettyRPCServer(9999).start(); } }
Class service processing server
InvokeHandler class the extends ChannelInboundHandlerAdapter {public // get a class that implements an interface under the name private String getImplClassName (ClassInfo classInfo) throws Exception { package path // service interface and implementation class party where the String interfacePath = "com.lyz.server" ; int = lastDot classInfo.getClassName () lastIndexOf ( ".");. . interfaceName = classInfo.getClassName String () the substring (lastDot); Class = superClass the Class.forName (interfacePath interfaceName +); Reflections Reflections = new new Reflections (interfacePath ); // get all classes implement an interface in the Set <class> ImplClassSet = reflections.getSubTypesOf (superClass); IF (ImplClassSet.size () == 0) { System.out.println ( "implementation class not found") ; return null; IF the else} (ImplClassSet.size ()>. 1) { System.out.println ( "Found plurality implementation classes, which do not specifically use"); return null; } the else { // to set into an array Class [] = ImplClassSet.toArray classes (class new new [0]); return classes [0] .getName (); implementation class // get the name } } @Override // read the data sent by the client and implementation class invoked by reflection method public void channelRead (ChannelHandlerContext CTX, Object MSG) throws Exception { ClassInfo classInfo = (ClassInfo) MSG; System.out.println (classInfo); . = Object clazz the Class.forName (getImplClassName (classInfo)) the newInstance (); Method = clazz.getClass Method, () getMethod (classInfo.getMethodName (), classInfo.getTypes ());. // reflection method by calling the implementation class Object Method.invoke Result = (clazz, classInfo.getObjects ()); CTX .writeAndFlush (Result); } }
Server interfaces and implementation classes
// 无参接口 public interface HelloNetty { String hello(); } // 实现类 public class HelloNettyImpl implements HelloNetty { @Override public String hello() { return "hello,netty"; } } // 带参接口 public interface HelloRPC { String hello(String name); } // 实现类 public class HelloRPCImpl implements HelloRPC { @Override public String hello(String name) { return "hello," + name; } }
Client
Acting Class
public class NettyRPCProxy { //根据接口创建代理对象 public static Object create(Class target) { return Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //封装ClassInfo ClassInfo classInfo = new ClassInfo(); classInfo.setClassName(target.getName()); classInfo.setMethodName(method.getName()); classInfo.setObjects(args); classInfo.setTypes(method.getParameterTypes()); //开始用Netty发送数据 EventLoopGroup group = new NioEventLoopGroup(); ResultHandler resultHandler = new ResultHandler(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //编码器 pipeline.addLast ( "Encoder", new new ObjectEncoder ()); // constructor first decoder parameter set maximum number of bytes of binary data, the second parameter set which parser class specific use pipeline.addLast ( "decoder" , new new ObjectDecoder (Integer.MAX_VALUE, ClassResolvers.cacheDisabled (null))); // the client service processing based pipeline.addLast ( "Handler", resultHandler); } }); ChannelFuture Future = b.connect ( "127.0.0.1 ", 9999) .sync (); . future.channel () writeAndFlush (classInfo) .sync (); .. future.channel () closeFuture () Sync (); } {the finally group.shutdownGracefully(); } return resultHandler.getResponse(); } }); } }
The client service processing class
the extends the ResultHandler ChannelInboundHandlerAdapter {class public Private Object Response; public getResponse Object () { return Response; } @Override // read the data returned by the server (the result of the remote call) public void channelRead (ChannelHandlerContext CTX, Object MSG) throws Exception { MSG = Response; ctx.close (); } }
Client Interface
No interface parameters // public interface HelloNetty { String Hello (); } // parameter interfaces with public interface HelloRPC { String Hello (String name); } a write
Test class service caller
public class TestNettyRPC { public static void main(String [] args){ //第1次远程调用 HelloNetty helloNetty=(HelloNetty) NettyRPCProxy.create(HelloNetty.class); System.out.println(helloNetty.hello()); //第2次远程调用 HelloRPC helloRPC = (HelloRPC) NettyRPCProxy.create(HelloRPC.class); System.out.println(helloRPC.hello("RPC")); } }
Output
Server
......server is ready...... com.lyz.serverStub.ClassInfo@2b894733 com.lyz.serverStub.ClassInfo@167bfa9
Client
hello,netty hello,RPC
Under a line chat achieved by netty
public class NettyRPCProxy {
//根据接口创建代理对象
public static Object create(Class target) {
return Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//封装ClassInfo
ClassInfo classInfo = new ClassInfo();
classInfo.setClassName(target.getName());
classInfo.setMethodName(method.getName());
classInfo.setObjects(args);
classInfo.setTypes(method.getParameterTypes());
//开始用Netty发送数据
EventLoopGroup group = new NioEventLoopGroup();
ResultHandler resultHandler = new ResultHandler();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel (the SocketChannel CH) throws Exception {
the ChannelPipeline Pipeline ch.pipeline = ();
// encoder
pipeline.addLast ( "Encoder" , new new ObjectEncoder ());
// decoder first constructor parameter setting the maximum binary data The number of bytes which the second parameter set based parsers specific use
pipeline.addLast ( "Decoder" , new new ObjectDecoder (Integer. MAX_VALUE , ClassResolvers. cacheDisabled ( null )));
// the client service processing based
pipeline.addLast ( " Handler " , resultHandler );
}
});
ChannelFuture future = b.connect("127.0.0.1", 9999).sync();
future.channel().writeAndFlush(classInfo).sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
return resultHandler.getResponse();
}
});
}
}