基于 web请求的远程调用学习
1概述
本文模拟远程过程调用进行实战总结,总的内容如下;
- 抽查接口公共部分
- 服务端,提供指定的服务列表(基于服务端提供的服务包路径并进行包扫描,根据服务实现类的注解类及注解方法进行过滤)
- 客户端封装请求参数为序列化对象,基于原生Socket进行发送请求
- 服务端对请求进行发序列化,并进行解析处理及结果返回
我的另外一篇文章是基于netty通讯框架,并结合zookeeper进行服务的负载均衡进行改写的,感兴趣的朋友可以借鉴,地址: https://www.jianshu.com/p/78b5f3b2a823
,里面也是完整的源码,直接放入工程即可运行,调试。
2公共部分
2.1注解定义
2.1.1RpcClazzAnno
package com.kikop.common.rpc.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: RpcClazzAnno
* @desc 功能描述 服务类注解
* @date 2020/8/23
* @time 17:21
* @by IDE: IntelliJ IDEA
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RpcClazzAnno {
}
2.1.2RpcMethodAnno
package com.kikop.common.rpc.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: RpcMethodAnno
* @desc 功能描述 服务类中方法注解
* @date 2020/8/23
* @time 17:21
* @by IDE: IntelliJ IDEA
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RpcMethodAnno {
}
2.2通讯结构体
2.2.1请求
package com.kikop.common.rpc.model;
import java.io.Serializable;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: MyRpcReqInfo
* @desc 功能描述 RPC通信请求数据结构
* @date 2020/8/23
* @time 16:52
* @by IDE: IntelliJ IDEA
*/
public class MyRpcReqInfo implements Serializable {
private static final long serialVersionUID = 5774354750836094390L;
/**
* 包名:com.kikop.myrpcdiy.advancedBasedNetty.server.provider
*
*/
private String packetName;
/**
* 仅仅类名
* simpled:OrderImpl、IOrder and so on
* advanced:com.kikop.myrpcdiy.advancedBasedNetty.server.provider.IOrder
*/
private String clazzName;
/**
* 方法名
*/
private String methodName;
/**
* 方法参数值列表
*/
private Object[] args;
/**
* 方法参数类型集合
*/
private Class<?>[] paramTypes;
public Class<?>[] getParamTypes() {
return paramTypes;
}
public void setParamTypes(Class<?>[] paramTypes) {
this.paramTypes = paramTypes;
}
private String additionInfo;
public String getAdditionInfo() {
return additionInfo;
}
public void setAdditionInfo(String additionInfo) {
this.additionInfo = additionInfo;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public String getPacketName() {
return packetName;
}
public void setPacketName(String packetName) {
this.packetName = packetName;
}
public String getClazzName() {
return clazzName;
}
public void setClazzName(String clazzName) {
this.clazzName = clazzName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
}
2.2.2响应
package com.kikop.common.rpc.model;
import java.io.Serializable;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: MyRpcReqInfo
* @desc 功能描述 RPC通信响应结构
* @date 2020/8/23
* @time 16:52
* @by IDE: IntelliJ IDEA
*/
public class MyRpcRespInfo implements Serializable {
private static final long serialVersionUID = 6027658366486943598L;
/**
* 请求方法名
*/
private String methodName;
/**
* 请求结果
*/
private Object result;
private String additionInfo;
public String getAdditionInfo() {
return additionInfo;
}
public void setAdditionInfo(String additionInfo) {
this.additionInfo = additionInfo;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
}
2.3注解工具类
package com.kikop.common.rpc;
import com.alibaba.fastjson.JSONObject;
import com.kikop.common.rpc.annotations.RpcClazzAnno;
import com.kikop.common.rpc.annotations.RpcMethodAnno;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: MyAnnotationUtil
* @desc 功能描述 注解读取工具类
* @date 2020/8/23
* @time 17:24
* @by IDE: IntelliJ IDEA
*/
public class MyAnnotationUtil {
/**
* 获取包中指定类注解的指定方法
*
* @param basePackage 包名 com.kikop.simpledBasedTomcat.service
* @return {"com.kikop.simpledBasedTomcat.service.OrderImpl":
* [{"getName":[]},
* {"setName":["String"]},
* {"getOrderCount":["String","Integer"]}
* ]
* }
* @throws ClassNotFoundException
*/
public static Map<String, List<Map<String, List<String>>>> parse(String basePackage) throws ClassNotFoundException {
Map<String, List<Map<String, List<String>>>> resultClazzMap = new HashMap<>();
// 1.获取当前注解所在的资源classPath类路径:
// /E:/workdirectory/Dev/study/MySimpledRpcBasedTomcat/target/classes/
String rootPath = MyAnnotationUtil.class.getResource("/").getPath();
// 1.1.转换包路径到文件结构:
// :com/kikop/simpledBasedTomcat/service
String basePacketPath = basePackage.replace(".", "/");
// 1.2.构造File对象
// /E:/workdirectory/Dev/study/MySimpledRpcBasedTomcat/target/classes/com/kikop/simpledBasedTomcat/service
String packagePathName = rootPath + basePacketPath;
File file = new File(packagePathName);
// 2.遍历包下的所有文件
// 2.1.遍历得到文件名列表
// [0]:OrderImpl.class
String[] names = file.list();
for (String fileName : names) {
// OrderImpl.class--> OrderImpl
String className = fileName.replaceAll(".class", "");
// com.kikop.simpledBasedTomcat.service.OrderImpl
String fullClazzName = basePackage + "." + className;
Class<?> aClass = Class.forName(fullClazzName);
if (aClass.isAnnotationPresent(RpcClazzAnno.class)) { // 指定类上的注解
Method[] declaredMethods = aClass.getDeclaredMethods();
List<Map<String, List<String>>> resulMethodsWithinClazzMap = new ArrayList<>();
// 2.1.遍历类上定义的需要对外提供服务的方法,并缓存到MethodMap中
for (Method declaredMethod : declaredMethods) {
if (declaredMethod.isAnnotationPresent(RpcMethodAnno.class)) { // 指定方法上的注解
//1.1.Map:key 包名+类名,v:方法列表
// key:方法名
// value:方法参数类型
Map<String, List<String>> methodMap = new HashMap<>();
List<String> params = new ArrayList<>(); // 方法的参数列表
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
String simpleName = parameterType.getSimpleName();
params.add(simpleName);
}
methodMap.put(declaredMethod.getName(), params);
resulMethodsWithinClazzMap.add(methodMap);
}
}
// key:com.kikop.simpledBasedTomcat.service.OrderImpl
// value:resulMethodsWithinClazzMap
resultClazzMap.put(fullClazzName, resulMethodsWithinClazzMap);
}
}
// System.out.println(JSONObject.toJSON(resultClazzMap));
return resultClazzMap;
}
public static void main(String[] args) throws ClassNotFoundException {
MyAnnotationUtil.parse(ServerConfig.BASEPACKAGE);
}
}
2.3.1打印服务端服务列表
[图片上传失败...(image-ce4126-1615726129915)]
2.4原生socket接口封装
package com.kikop.common.rpc;
import com.kikop.common.rpc.model.MyRpcReqInfo;
import com.kikop.common.rpc.model.MyRpcRespInfo;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Arrays;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: MySocketUtils
* @desc 功能描述 socket数据序列化发送
* @date 2021/3/13
* @time 17:24
* @by IDE: IntelliJ IDEA
*/
public class MySocketUtils {
/**
* 获取请求元数据
*
* @param currentSocket
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static MyRpcReqInfo getReqMetaData(Socket currentSocket) throws IOException, ClassNotFoundException {
// 1.获取远程请求参数并反序列化
ObjectInputStream objectInputStream = new ObjectInputStream(currentSocket.getInputStream());
MyRpcReqInfo myRpcReqInfo = (MyRpcReqInfo) objectInputStream.readObject();
return myRpcReqInfo;
}
/**
* 发送请求元数据
*
* @param currentSocket
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static void sendReqMetaData(Socket currentSocket, MyRpcReqInfo myRpcReqInfo) throws IOException, ClassNotFoundException {
// 1.获取通道写入流
ObjectOutputStream objectOutputStream = new ObjectOutputStream(currentSocket.getOutputStream());
// 2.发起请求
objectOutputStream.writeObject(myRpcReqInfo);
// 提交
objectOutputStream.flush();
// 关闭输出流
currentSocket.shutdownOutput();
// 3.获取输入流,并读取服务器端的响应信息
ObjectInputStream objectInputStream = new ObjectInputStream(currentSocket.getInputStream());
Object respResult = objectInputStream.readObject();
if (respResult instanceof MyRpcRespInfo) {
MyRpcRespInfo myRpcRespInfo = (MyRpcRespInfo) respResult;
System.out.println(String.format("taskInfo:[%s],reqClazzInfo:[%s.%s:%s]-->reqResult:%s",
myRpcReqInfo.getAdditionInfo(),
myRpcReqInfo.getClazzName(), myRpcReqInfo.getMethodName(), Arrays.toString(myRpcReqInfo.getArgs()),
String.valueOf(myRpcRespInfo.getResult())));
}
//4.关闭资源
objectOutputStream.close();
objectInputStream.close();
currentSocket.close();
}
/**
* 发送请求结果
*
* @param currentSocket
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static void sendRespResult(Socket currentSocket, MyRpcRespInfo myRpcRespInfo) throws IOException, ClassNotFoundException {
// 1.获取输出流,向服务器端发送信息
ObjectOutputStream objectOutputStream = new ObjectOutputStream(currentSocket.getOutputStream());
// 2.发起请求
objectOutputStream.writeObject(myRpcRespInfo);
// 3.提交并关闭流
objectOutputStream.flush();
objectOutputStream.close();
}
}
2.5服务参数配置
package com.kikop.common.rpc;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: ServerConfig
* @desc 功能描述 服务配置类,定义对外抛出的服务
* @date 2020/8/23
* @time 17:21
* @by IDE: IntelliJ IDEA
*/
public class ServerConfig {
public final static String HOST = "127.0.0.1";
public final static int PORT = 6666;
public static final String BASEPACKAGE = "com.kikop.simpledBasedTomcat.service";
}
3服务端
3.1maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kikop</groupId>
<artifactId>MySimpledRpcBasedTomcat</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MySimpledRpcBasedTomcat Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<fastjson.version>1.2.29</fastjson.version>
<!-- slf4j日志文件管理包版本 -->
<slf4j.version>1.7.12</slf4j.version>
<!--jstl -->
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<!--1.单元测试类-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--2.servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--3.fastjson-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--4.JSTL标签类-->
<!--<dependency>-->
<!--<groupId>jstl</groupId>-->
<!--<artifactId>jstl</artifactId>-->
<!--<version>${jstl.version}</version>-->
<!--</dependency>-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<!--<dependency>-->
<!--<groupId>javax.servlet.jsp</groupId>-->
<!--<artifactId>jsp-api</artifactId>-->
<!--<version>2.2</version>-->
<!--<scope>provided</scope>-->
<!--</dependency>-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<!--<dependency>-->
<!--<groupId>javax.servlet.jsp</groupId>-->
<!--<artifactId>javax.servlet.jsp-api</artifactId>-->
<!--<version>2.3.0</version>-->
<!--<scope>provided</scope>-->
<!--</dependency>-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<!--<dependency>-->
<!--<groupId>javax.servlet</groupId>-->
<!--<artifactId>javax.servlet-api</artifactId>-->
<!--<version>3.1.0</version>-->
<!--<scope>provided</scope>-->
<!--</dependency>-->
</dependencies>
<build>
<finalName>MySimpledRpcBasedTomcat</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3.2对外接口服务
注意,对外接口服务统一放在:com.kikop.simpledBasedTomcat.service这个包路径下。
package com.kikop.simpledBasedTomcat.service;
import com.kikop.common.rpc.annotations.RpcClazzAnno;
import com.kikop.common.rpc.annotations.RpcMethodAnno;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: OrderImpl
* @desc 功能描述 模拟对外提供的订单服务
* @date 2020/8/23
* @time 17:21
* @by IDE: IntelliJ IDEA
*/
@RpcClazzAnno
public class OrderImpl {
private String orderName;
@RpcMethodAnno
public String getOrderName() {
return orderName;
}
@RpcMethodAnno
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@RpcMethodAnno
public Integer getOrderCount(String orderName) {
if (orderName.equalsIgnoreCase("apple")) {
return 100;
}
return 10;
}
}
3.3调度层
3.3.1服务端业业务处理
package com.kikop.simpledBasedTomcat.dispatcher;
import com.kikop.common.rpc.MySocketUtils;
import com.kikop.common.rpc.model.MyRpcReqInfo;
import com.kikop.common.rpc.model.MyRpcRespInfo;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Arrays;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: ServerThread
* @desc 功能描述
* @date 2020/8/23
* @time 17:02
* @by IDE: IntelliJ IDEA
*/
public class ServerTaskHandler implements Runnable {
private Socket currentSocket;
public ServerTaskHandler(Socket currentSocket) {
this.currentSocket = currentSocket;
}
@Override
public void run() {
try {
// 1.获取远程请求参数并反序列化
MyRpcReqInfo myRpcReqInfo = MySocketUtils.getReqMetaData(currentSocket);
// 2.反射得到类信息
Class<?> aClass = Class.forName(myRpcReqInfo.getPacketName() + "." + myRpcReqInfo.getClazzName());
Class[] params = new Class[myRpcReqInfo.getArgs().length];
for (int i = 0; i < params.length; i++) {
params[i] = myRpcReqInfo.getArgs()[i].getClass();
}
Method method = aClass.getMethod(myRpcReqInfo.getMethodName(), params);
Object result = method.invoke(aClass.newInstance(), myRpcReqInfo.getArgs());
System.out.println(String.format("taskInfo:[%s],reqClazzInfo:[%s.%s:%s]-->reqResult:%s",
myRpcReqInfo.getAdditionInfo(),
method.getDeclaringClass().getName(), method.getName(), Arrays.toString(myRpcReqInfo.getArgs()),
result)
);
//3.返回结果
MyRpcRespInfo myRpcRespInfo = new MyRpcRespInfo();
myRpcRespInfo.setMethodName(method.getName());
myRpcRespInfo.setResult(result);
myRpcRespInfo.setAdditionInfo(myRpcReqInfo.getAdditionInfo());
MySocketUtils.sendRespResult(currentSocket, myRpcRespInfo);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
3.3.2服务管理类
package com.kikop.simpledBasedTomcat.dispatcher;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: ServerManager
* @desc 功能描述
* @date 2020/8/23
* @time 16:33
* @by IDE: IntelliJ IDEA
*/
public class ServerManager {
private int totalClientCount = 0;
/**
* 启动服务
*
* @param port
* @throws IOException
*/
public void startSvr(int port) throws IOException {
totalClientCount = 0;
ServerSocket serverSocket = new ServerSocket(port);
// 创建5个固定的线程
// 使用 LinkedBlockingQueue队列管理等待数据
ExecutorService executorService = Executors.newFixedThreadPool(5);
System.out.println("服务器即将启动,等待客户端的连接 ...");
while (true) {
Socket clientSocket = serverSocket.accept();
executorService.execute(new ServerTaskHandler(clientSocket));
// System.out.println(String.format("a client connect success,getRemoteSocketAddress%s-->getLocalSocketAddress:%s!"
// , clientSocket.getRemoteSocketAddress().toString(), clientSocket.getLocalSocketAddress().toString())
// );
totalClientCount++;//统计客户端的数量
InetAddress clientSocketInetAddress = clientSocket.getInetAddress(); // clientSocketInetAddress.getHostAddress()
System.out.println(String.format("客户端的数量:%d,当前客户端的信息%s", totalClientCount,
clientSocket.getRemoteSocketAddress().toString()));
}
}
}
3.4控制层
控制层接收客户端web请求,客户端通过浏览器登录,输入服务接口访问即可,控制层主要是向客户端展示当前可用的服务列表。
package com.kikop.simpledBasedTomcat.Controller;
import com.alibaba.fastjson.JSON;
import com.kikop.common.rpc.MyAnnotationUtil;
import com.kikop.common.rpc.ServerConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: SimpledRpcServlet
* @desc 功能描述 基于tomcat的 htttp协议
* WebServlet代替 web.xml
* http://localhost:8080/simpledRpc/simpledRpcServlet
* @date 2020/8/23
* @time 18:20
* @by IDE: IntelliJ IDEA
*/
//@WebServlet(name = "simpledRpcServlet", urlPatterns = "/demo/simpledRpcServlet")
@WebServlet("/simpledRpcServlet")
public class SimpledRpcServlet extends HttpServlet {
private Map<String, List<Map<String, List<String>>>> resultClazzMap;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.service(req, resp);
// :/simpledRpc/simpledRpcServlet
System.out.println(req.getRequestURI());
// :http://localhost:8080/simpledRpc/simpledRpcServlet
System.out.println(req.getRequestURL());
String reqServerName = req.getParameter("reqServerName");
try {
if (resultClazzMap != null) {
if (reqServerName == null) {
responseData(resp, resultClazzMap);
} else {
List<Map<String, List<String>>> maps = resultClazzMap.get(reqServerName);
responseData(resp, maps);
}
} else {
resultClazzMap = MyAnnotationUtil.parse(ServerConfig.BASEPACKAGE);
if (reqServerName == null) {
responseData(resp, resultClazzMap);
} else {
List<Map<String, List<String>>> maps = resultClazzMap.get(reqServerName);
responseData(resp, (maps == null) ? new Object() : maps);
}
}
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
/**
* 发送请求结果
*
* @param resp
* @param javaObject
* @throws IOException
*/
private void responseData(HttpServletResponse resp, Object javaObject) throws IOException {
PrintWriter pw = resp.getWriter();
pw.println(JSON.toJSON(javaObject));
pw.flush();
pw.close();
}
}
4客户端
由于客户端只需要登录浏览器即可,没用额外接口开发,只需建立正常的socket连接,发送标准的序列化请求结构即可。
4测试
4.1启动服务端
package com.kikop.simpledBasedTomcat.SimpledRpcTest;
import com.kikop.common.rpc.ServerConfig;
import com.kikop.simpledBasedTomcat.dispatcher.ServerManager;
import java.io.IOException;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: producerTest
* @desc 功能描述
* @date 2020/8/23
* @time 16:36
* @by IDE: IntelliJ IDEA
*/
public class producerTest {
public static void main(String[] args) throws IOException {
publisherSvrTest();
}
private static void publisherSvrTest() throws IOException {
ServerManager serverManager = new ServerManager();
serverManager.startSvr(ServerConfig.PORT);
}
}
4.2模拟客户端发送请求
package com.kikop.simpledBasedTomcat.SimpledRpcTest;
import com.kikop.common.rpc.MySocketUtils;
import com.kikop.common.rpc.ServerConfig;
import com.kikop.common.rpc.model.MyRpcReqInfo;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
/**
* @author kikop
* @version 1.0
* @project Name: MySimpledRpcBasedTomcat
* @file Name: consumerTest
* @desc 功能描述
* @date 2020/8/23
* @time 16:37
* @by IDE: IntelliJ IDEA
*/
public class consumerTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
IntStream.range(0, 10).parallel().forEach(value -> {
try {
String reqTaskInfo = String.format("%s:%d",
Thread.currentThread().getName(), Thread.currentThread().getId());
sendReqMetaData(value, reqTaskInfo);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
}
/**
* 模拟查询用户名为kikop的订单信息
*
* @return
*/
private static void sendReqMetaData(int dataType, String reqTaskInfo) throws IOException, ClassNotFoundException {
// 1.创建一个客户端socket通道
Socket socket = new Socket(ServerConfig.HOST, ServerConfig.PORT);
// 2.封装请求参数
MyRpcReqInfo myRpcReqInfo = new MyRpcReqInfo();
myRpcReqInfo.setPacketName("com.kikop.simpledBasedTomcat.service");
myRpcReqInfo.setClazzName("OrderImpl");
myRpcReqInfo.setMethodName("getOrderCount");
Object[] args = new Object[]{(dataType % 2 == 0) ? "banana" : "apple"};
myRpcReqInfo.setArgs(args);
myRpcReqInfo.setAdditionInfo(reqTaskInfo);
// 3.发送请求
MySocketUtils.sendReqMetaData(socket, myRpcReqInfo);
}
}
网友评论