rpc是远程过程调用的简称,它可以通过网络调用另一台服务器的某个方法
网络编程,反射,协议
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.25.Final</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.googlecode.protobuf-java-format</groupId>-->
<!-- <artifactId>protobuf-java-format</artifactId>-->
<!-- <version>1.2</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.26</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- marshalling -->
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-serial</artifactId>
<!-- <version>2.0.0.Final</version> --> <!-- 需要JDK1.8支持 -->
<version>1.4.11.Final</version> <!-- 需要JDK1.7支持 -->
</dependency>
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling</artifactId>
<version>1.4.11.Final</version>
</dependency>
<!-- log4j start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- log4j end -->
<!-- slf4j bound to Log4j start -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
<!-- slf4j bound to Log4j end -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.10.0-m1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
public class ClassInfo implements Serializable {
//类全路径名,方法名,参数类型数组,参数数组
private String className;
private String methodName;
private Class[] paramsTypeArr;
private Object[] paramsArr;
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[] getParamsTypeArr() {
return paramsTypeArr;
}
public void setParamsTypeArr(Class[] paramsTypeArr) {
this.paramsTypeArr = paramsTypeArr;
}
public Object[] getParamsArr() {
return paramsArr;
}
public void setParamsArr(Object[] paramsArr) {
this.paramsArr = paramsArr;
}
}
public class User implements Serializable{
private int id;
private String name;
private int age;
public User(){ }
public User(int id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
public interface UserService {
User getUser(int id);
}
public class UserServiceImpl implements UserService{
List<User> userList = new ArrayList<>();
{
for(int i=0;i<10;i++){
User user = new User(i,"name"+i,20+i);
userList.add(user);
}
}
@Override
public User getUser(int id) {
return userList.get(id);
}
}
public class ServerMain {
public static void main(String[] args) {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(boss,worker);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.option(ChannelOption.SO_BACKLOG,128); //设置线程队列中等待连接的个数
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE,true);//保持活动连接状态
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ObjectEncoder());
pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
pipeline.addLast(new ServerHandler());
}
});
try{
ChannelFuture future = serverBootstrap.bind(9999).sync();//设置端口 非阻塞
System.out.println(".........server start..........");
future.channel().closeFuture().sync();
}catch (InterruptedException e){
e.printStackTrace();
}finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
public class ServerHandler extends ChannelInboundHandlerAdapter {
private static ExecutorService executorService= Executors.newFixedThreadPool(1000);
@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
executorService.submit(new Runnable() {
@Override
public void run() {
try {
ClassInfo classInfo= (ClassInfo) msg;
Object o = Class.forName(getImplClassName(classInfo)).newInstance();
Method method = o.getClass().getMethod(classInfo.getMethodName(), classInfo.getParamsTypeArr());
Object invoke = method.invoke(o, classInfo.getParamsArr());
ctx.channel().writeAndFlush(invoke);
}catch (Exception e){
e.printStackTrace();
}
}
});
}
//得到某个接口下的实现类
public String getImplClassName(ClassInfo classInfo) throws Exception {
//服务器接口与实现类地址; 这个路径是server包接口UserService所在路径
String iName="com.lry.basic.netty.demo4.server";
int i = classInfo.getClassName().lastIndexOf(".");
String className=classInfo.getClassName().substring(i);
Class aClass = Class.forName(iName + className);
Reflections reflections=new Reflections(iName);
Set<Class<?>> classes=reflections.getSubTypesOf(aClass);
if(classes.size()==0){
System.out.println("未找到实现类");
return null;
}else if(classes.size()>1){
System.out.println("找到多个实现类,未明确使用哪个实现类");
return null;
}else{
Class[] classes1 = classes.toArray(new Class[0]);
return classes1[0].getName();
}
}
}
public interface UserService {
User getUser(int id);
}
public class ClientMain {
public static void main(String[] args) {
UserService userService = (UserService) RpcProxy.remoteCall(UserService.class);
System.out.println(userService.getUser(1));
}
}
public class ClientHandler extends ChannelInboundHandlerAdapter {
private Object response;
public Object getResponse() {
return response;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
response = msg;
ctx.close();
}
}
public class RpcProxy {
public static Object remoteCall(final Class clazz){
return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//组装ClassInfo发送给服务器
ClassInfo classInfo = new ClassInfo();
classInfo.setClassName(clazz.getName());
classInfo.setMethodName(method.getName());
classInfo.setParamsTypeArr(method.getParameterTypes());
classInfo.setParamsArr(args);
EventLoopGroup group = new NioEventLoopGroup();
final ClientHandler clientHandler = new ClientHandler();
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ObjectEncoder());
pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
pipeline.addLast(clientHandler);
}
});
ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost",9999)).sync();
future.channel().writeAndFlush(classInfo).sync();
future.channel().closeFuture().sync();
}finally {
group.shutdownGracefully();
}
return clientHandler.getResponse();
}
});
}
}