1、新建三个模块,第一公共模块
io.netty
netty-all
4.1.6.Final
public interface IUserService {
String sayHello(String msg);
}
2、生产者
public class UserServiceImpl implements IUserService {
@Override
public String sayHello(String msg) {
System.out.println("are you ok ? " + msg);
return "are you ok ? " + msg;
}
//创建一个方法启动服务器
public static void startServer(String ip,int port) throws InterruptedException {
//1、创建两个线程池对象
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
//2、创建服务端的启动引导对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//3、配置启动引导对象
serverBootstrap.group(bossGroup,workGroup)
//设置通道为NIO
.channel(NioServerSocketChannel.class)
//创建监听channel
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
//获取管道对象
ChannelPipeline pipeline = nioSocketChannel.pipeline();
//给管道对象设置编码
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
//自定义一个ChannelHandler添加到通道中
pipeline.addLast(new UserServiceHandler());
}
});
//4、绑定端口
serverBootstrap.bind(8999).sync();
}
}
public class UserServiceHandler extends ChannelInboundHandlerAdapter {
//当客户端读取数据时,该方法会被调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//注意:当客户端将来发送请求的时候会传递一个参数:UserService#sayHello#are you ok
//判断当前的请求是否符合规则
if(msg.toString().startsWith("UserService")){
//2、如果符合规则,调用实现类得到一个result
UserServiceImpl service = new UserServiceImpl();
String result = service.sayHello(msg.toString().substring(msg.toString().lastIndexOf("#") + 1));
//3、把调用实现类的方法获得的结果写回客户端
ctx.writeAndFlush(result);
}
}
}
public class Serverboot {
public static void main(String[] args) throws InterruptedException {
//启动服务器
UserServiceImpl.startServer("127.0.0.1",8999);
}
}
3、消费者
public class RpcConsumer {
//1、创建一个线程池对象,---它需要处理自定义事件
private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//2、声明一个自定义事件处理器 UserClientHandler
private static UserClientHandler userClientHandler;
//3、编写方法,初始化客户端(创建连接池 bootstrap 设置 bootstrap 连接服务器)
public static void initClient() throws InterruptedException {
//1)初始化UserClientHandler
userClientHandler = new UserClientHandler();
//2)创建连接池对象
EventLoopGroup group = new NioEventLoopGroup();
//3)创建客户端的引导对象
Bootstrap bootstrap = new Bootstrap();
//4)配置启动引导对象
bootstrap.group(group)
//设置通道为NIO
.channel(NioSocketChannel.class)
//设置请求协议为TCP
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//获取ChannelPipeline
ChannelPipeline pipeline = socketChannel.pipeline();
//设置编码
pipeline.addLast(new StringEncoder());
pipeline.addLast(new StringDecoder());
pipeline.addLast(userClientHandler);
}
});
//连接服务器端
bootstrap.connect("127.0.0.1",8999).sync();
}
//编写一个方法,使用JDK的动态代理创建对象
//serviceClass接口类型,根据哪个接口生成子类代理对象:providerParam:"UserService#sayHello"
public static Object createProxy(Class> serviceClass,String providerParam){
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{serviceClass}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1)初始化客户端
if(userClientHandler == null){
initClient();
}
//2)给userClientHandler设置参数值
userClientHandler.setParam(providerParam + args[0]);
//3)使用线程池,开启一个线程处理call()写操作,并返回结果
Object result = executorService.submit(userClientHandler).get();
//4)return结果
return result;
}
});
}
}
public class UserClientHandler extends ChannelInboundHandlerAdapter implements Callable {
//1、定义成员变量
private ChannelHandlerContext context;//事件处理器上下文对象(存储handler信息,写操作)
private String result;//记录服务器返回的数据
private String param;//记录将要返送给服务器的数据
//2、实现channelActive,
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//初始化ChannelHandlerContext
this.context = ctx;
}
//3、实现channelRead,当我们读到服务器数据,该方法自动执行
@Override
public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//将读到的服务器的数据msg,设置为成员变量的值
result = msg.toString();
notify();
}
//4、将客户端的数据读到服务器
@Override
public synchronized Object call() throws Exception {
//context给服务器写数据
context.writeAndFlush(param);
wait();
return result;
}
public void setParam(String param) {
this.param = param;
}
}
public class Consumerboot {
//参数定义
private static final String PROVIDER_NAME = "UserService#sayHello";
public static void main(String[] args) throws InterruptedException {
//1、创建代理对象
IUserService service = (IUserService) RpcConsumer.createProxy(IUserService.class,PROVIDER_NAME);
//2、循环给服务器写数据
while(true){
String result = service.sayHello("are you ok!!");
System.out.println(result);
Thread.sleep(2000);
}
}
}