首先是接口的实现,这一点和普通接口实现是一样的
package com.lwl.service;
import com.lwl.common.JSONSerializer;
import com.lwl.common.RpcDecoder;
import com.lwl.common.RpcRequest;
import com.lwl.handler.UserServiceHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
//客户端需要调用的防范
@Override
public String sayHello(String msg) {
System.out.println("sayHello() -->{}"+msg);
return "success";
}
//创建一个方法启动服务器
public static void startServer(String ip,int port) throws InterruptedException {
//创建两个线程池对象
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
//创建服务器启动引导对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//配置启动引导对象
serverBootstrap.group(bossGroup,workGroup)
//设置通道为nio
.channel(NioServerSocketChannel.class)
//创建监听器
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
//获取管道对象
ChannelPipeline pipeline = nioSocketChannel.pipeline();
//设置编码
pipeline.addLast(new StringEncoder());
pipeline.addLast( new RpcDecoder(RpcRequest.class, new JSONSerializer()));
//将自定义的 channelHandler 添加到通道中
pipeline.addLast(new UserServiceHandler());
}
});
//绑定端口号
ChannelFuture sync = serverBootstrap.bind(8999).sync();
}
}
在实现中加入了netty的服务器启动程序,上面的代码中添加了 String类型的编解码 handler,添加了一个自定义handler
自定义 handler 逻辑如下:
package com.lwl.handler;
import com.lwl.common.RpcRequest;
import com.lwl.service.UserServiceImpl;
import com.lwl.util.SpringContextUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.lang.reflect.Method;
/**
* 自定义业务处理器
*/
public class UserServiceHandler extends ChannelInboundHandlerAdapter {
/**
* 当客户端读取数据时,该方法被调用
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// //客户端发送请求时的一个参数 约定 UserService#sayHello#are you ok
// // 判断当前的请求是否符合规则
// if (msg.toString().startsWith("UserService")){
// //符合规则 调用实现类 到一个result
// UserServiceImpl userService = new UserServiceImpl();
// String result = userService.sayHello(msg.toString().substring(msg.toString().lastIndexOf("#") + 1));
// //将结果写到客户端
// ctx.writeAndFlush(result);
// }
/**
* 1、从RpcRequest对象中获取属性 (调用类名,方法,参数等)
*/
RpcRequest rpcRequest =(RpcRequest)msg;
String className = rpcRequest.getClassName();
String methodName = rpcRequest.getMethodName();
Object[] parameters = rpcRequest.getParameters();
Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
Class<?> aClass = Class.forName(className);
//从spring容器获取对象
UserServiceImpl o = (UserServiceImpl) SpringContextUtil.getBean(aClass);
Method method = aClass.getMethod(methodName, parameterTypes);
//反射调用
String result = (String) method.invoke(o, parameters);
ctx.writeAndFlush(result);
}
}
SpringContextUtil
package com.lwl.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* 获取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
还需要一个启动类:
package com.lwl;
import com.lwl.service.UserServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ServerBoot {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(ServerBoot.class, args);
//启动服务器
UserServiceImpl.startServer("127.0.0.1",8999);
}
}