话不多说直接上代码
首先定义服务器和客户端的公共接口
public interface HelloService { String hello(String mes); }
编写提供者代码
服务端的接口实现类
public class HelloServiceImp implements HelloService { private int count =0; @Override public String hello(String mes) { System.out.println("收到客户端消息="+mes); if(mes!=null) {return "你好客户端,我已经收到的你消息----"+mes+",第"+(++count)+"次";}else{ return "你好客户端"; } } }
编写服务器的ServerBootstrap
public class ServerBootstrap { public static void main(String[] args) { NettyServer.startServer("127.0.0.1",8881);//使用8881端口 } }
编写NettyServer类
public class NettyServer { public static void startServer(String hostName,int prot){ startServer0(hostName,prot); } //nettyserver初始化 private static void startServer0(String hostName,int prot){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workgroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workgroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new NettyServerHandler());//调用自定义的handler处理事务 } }); ChannelFuture channelFuture = serverBootstrap.bind(hostName, prot).sync(); System.out.println("------服务端启动成功-----"); channelFuture.channel().closeFuture().sync(); }catch (Exception e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workgroup.shutdownGracefully(); } } }
编写NettyServerHandler
public class NettyServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //获取客户端发送的消息 System.out.println("msg="+msg); //客户端在调用服务器的api必须要定义一个协议 if(msg.toString().startsWith("HelloService#hello#")){ String hello = new HelloServiceImp().hello(msg.toString().substring(msg.toString().lastIndexOf("#") + 1)); ctx.writeAndFlush(hello); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } }
至此提供者代码编写完毕
接下来是消费者代码
编写ClientServerHandler
public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable { private ChannelHandlerContext context; private String result;//返回结果 private String para;//客户端调用方法 //调用1 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { context=ctx; } //调用4 @Override public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { result=msg.toString(); notify();//唤醒等待的线程 } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } //被代理对象调用,发送数据给服务器,-》wait 等待唤醒 //调用3,5 @Override public synchronized Object call() throws Exception { context.writeAndFlush(para); wait();//等待channelRead方法唤醒 return result; } //调用2 void setPara(String para) { this.para=para; } } 编写NettyClient类 public class NettyClient { private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); private static NettyClientHandler clientHandler; //通过动态代理,执行远程调用 public Object getBean(final Class<?> serviceClass,final String providerName){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> { if(clientHandler ==null) { initClient(); } //设置给服务器发送的消息 //providerName协议头args[0]解释客户端api hello(???)参数 clientHandler.setPara(providerName+args[0]); return executor.submit(clientHandler).get(); }); } private static void initClient(){ clientHandler = new NettyClientHandler(); NioEventLoopGroup group = new NioEventLoopGroup(); try{ Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY,true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(clientHandler); } }); bootstrap.connect("127.0.0.1",8881).sync(); }catch (Exception e){ e.printStackTrace(); } } }
编写消费者ClientBootstrap类
public class ClientBootstrap { public static final String provideName ="HelloService#hello#"; public static void main(String[] args) throws InterruptedException { NettyClient customer = new NettyClient(); HelloService customerBean = (HelloService) customer.getBean(HelloService.class, provideName); for(;;){ Thread.sleep(10*1000); String res =customerBean.hello("你好,rpc"); System.out.println(res); } } }
编写完成,分别运行提供者的ServerBootstrap和ClientBootstarp结果如下
每次请求提供者都会new一个新的HelloServiceImp。
项目结构如下