因为在IDEA中的netty包里没显示example包,所以需要找到maven下载的netty包,找到netty-all-4.1.20.Final-sources.jar文件,把后缀jar改为rar,然后解压,点进去就可以找到example包了。 我已经把源码的案例和老师的文档上传到了百度云,需要的可以自行下载:https://pan.baidu.com/s/1txMv9I8YYflztT19DYc7LA 密码: vdei
publicinterface
//公共接口 public interface HelloService { //由服务提供者进行实现,为服务消费者提供服务 String hello(String mes); }provider
public class HelloServiceImpl implements HelloService { private static int count = 0; //为消费者提供服务,当消费者调用此方法时,返回一个结果 @Override public String hello(String mes) { System.out.println("收到客户端消息:" + mes); //根据mes返回不同的结果 if(mes != null){ return "服务器已收到消息【" + mes + "】" + (++count); }else{ return "服务器已收到消息"; } } } //启动服务的提供者(NettyServer) public class ServerBootstrap { public static void main(String[] args) { NettyServer.startServer("127.0.0.1", 7000); } }netty
public class NettyClient { //创建线程池(数量:CPU核数) private static ExecutorService executor = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors()); private static NettyClientHandler client; private int count; //初始化客户端 private static void initClient(){ client = new NettyClientHandler(); EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new 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(client); } }); try { bootstrap.connect("127.0.0.1", 7000).sync(); } catch (InterruptedException e) { e.printStackTrace(); } } //代理模式获取代理对象 public Object getBean(final Class<?> serviceClass, final String providerName){ return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] {serviceClass}, (proxy, method, args) -> { System.out.println("(proxy, method, args)进入..." + (++count)); if(client == null){ //初始化 initClient(); } //设置要发给服务器端的信息 //providerName为协议头,args[0]客户端调用api hello(xxx) 的参数 client.setPara(providerName + args[0]); return executor.submit(client).get(); }); } } public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable { private ChannelHandlerContext context; //上下文 private String result; //调用后返回的结果 private String para; //客户端调用方法时,传入的参数 //设置参数 (2) void setPara(String para){ System.out.println("setPara 被调用"); this.para = para; } //与服务器连接成功后,就会被触发调用 (1) @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("channelActive 被调用"); //因为在其他方法(call方法)里也要使用到ctx context = ctx; } //收到服务器回复的数据后,触发调用 (4) @Override public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("channelRead 被调用"); //保存服务方返回的结果 result = msg.toString(); //唤醒等待的线程 notify(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } //客户端真正发送数据的方法 (3) (5) //被代理对象调用,发送数据给服务器 -> 发送完后,wait -> 等待被唤醒(channelRead) -> 服务方返回结果 //服务器回复结果会发送触发channelRead()方法,由这个方法来唤醒此线程 @Override public synchronized Object call() throws Exception { System.out.println("call1 被调用"); //发送数据给服务器端 context.writeAndFlush(para); //进行wait,等待channelRead()方法获取到服务器回复的结果后唤醒 wait(); System.out.println("call2 被调用"); //服务方返回的结果 return result; } } public class NettyServer { //对外暴露 public static void startServer(String hostname, int port){ startServer0(hostname, port); } //NettyServer的初始化和启动 private static void startServer0(String hostname, int port){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap() .group(bossGroup, workerGroup) .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()); } }); ChannelFuture channelFuture = serverBootstrap.bind(hostname, port).sync(); System.out.println("服务提供者启动成功,开始提供服务~"); channelFuture.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } public class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //获取客户端发送的消息,并调用服务 System.out.println("msg=" + msg); //客户端在调用服务器api时,需要遵循定义的协议 //比如:每次发送的消息必须以某个字符串开头 "HelloService#hello#" if(msg.toString().startsWith("HelloService#hello#")){ //截取内容并调用api String result = new HelloServiceImpl().hello(msg.toString().substring( msg.toString().lastIndexOf("#") + 1)); ctx.writeAndFlush(result); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }customer
public class ClientBootstrap { //定义协议头 public static final String providerName = "HelloService#hello#"; public static void main(String[] args) throws Exception { //创建一个消费者 NettyClient customer = new NettyClient(); //创建代理对象 HelloService service = (HelloService) customer.getBean(HelloService.class, providerName); while (true){ Thread.sleep(5 * 1000); //通过代理对象调用服务提供者的方法(服务) //每次调用时,HelloServiceImpl都会创建新对象 String res = service.hello("你好,dubbo~"); System.out.println("调用结果:" + res); } } }学习视频(p92-p116):https://www.bilibili.com/video/BV1DJ411m7NR?p=92