结构图
代码
代码结构
服务提供者provider
结构
核心代码
注册中心
package com.ql.learn.registry;
import com.ql.learn.pojo.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author qinlei
* @description 本地注册中心
* @date 2020/9/18 17:12
*/
public class NativeRegistry {
//注册中心
private static Map<String, Map<URL,Class>> registryCenter = new HashMap<String, Map<URL,Class>>();
/**
* 注册服务
*/
public static void registry(String interfaceName,URL url,Class implClass){
Map<URL, Class> hashMap = new HashMap<>();
hashMap.put(url,implClass);
registryCenter.put(interfaceName,hashMap);
}
/**
* 从注册中心获取服务
* @param url 请求的路径(ip port)
* @param interfaceName 接口名称
* @return
*/
public static Class get(URL url,String interfaceName){
return registryCenter.get(interfaceName).get(url);
}
}
配置tomcat
package com.ql.learn.tomcat;
import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;
/**
* @author qinlei
* @description 构建一个tomcat
* @date 2020/9/18 17:24
*/
public class HttpServer {
public void start(String hostname,Integer port){
//实例化tomcat
Tomcat tomcat = new Tomcat();
//创建server
Server server = tomcat.getServer();
//获取service
Service service = server.findService("Tomcat");
//构建connector
Connector connector = new Connector();
connector.setPort(port);
connector.setURIEncoding("UTF-8");
//构建engine
Engine engine = new StandardEngine();
engine.setDefaultHost(hostname);
//构建host
Host host = new StandardHost();
host.setName(hostname);
//构建context
String contextPath = "";
Context context = new StandardContext();
context.setPath(contextPath);
//tomcat的生命周期监听器
context.addLifecycleListener(new Tomcat.FixContextListener());
//一层一层将子节点添加到父节点
host.addChild(context);
engine.addChild(host);
service.setContainer(engine);
service.addConnector(connector);//这里的service本来就是从server中拿到的
//tomcat是一个servlet,设置路径和映射
tomcat.addServlet(contextPath,"dispatcher",new DispatcherServlet());
context.addServletMappingDecoded("/*","dispatcher");
try {
tomcat.start();//启动tomcat
tomcat.getServer().await();//接受请求
} catch (LifecycleException e) {
e.printStackTrace();
}
}
}
package com.ql.learn.tomcat;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author qinlei
* @description todo
* @date 2020/9/18 17:38
*/
public class DispatcherServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp){
//处理远程调用请求
new HttpServerHandler().handle(req,resp);
}
}
package com.ql.learn.tomcat;
import com.ql.learn.pojo.Invocation;
import com.ql.learn.pojo.URL;
import com.ql.learn.registry.NativeRegistry;
import org.apache.commons.io.IOUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author qinlei
* @description 处理远程调用请求
* @date 2020/9/18 17:41
*/
public class HttpServerHandler {
public void handle(HttpServletRequest req, HttpServletResponse resp) {
//服务请求处理逻辑
try {
//1.通过请求流获取请求服务调用的参数
InputStream inputStream = req.getInputStream();
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
Invocation invocation = (Invocation) objectInputStream.readObject();
//2.从注册中心获取服务的列表
Class implClass = NativeRegistry.get(new URL("localhost",8899),invocation.getInterfaceName());
//3.调用服务-映射
Method method = implClass.getMethod(invocation.getMethodName(),invocation.getParamTypes());
String result = (String) method.invoke(implClass.newInstance(),invocation.getParams());
//4.返回结果
IOUtils.write(result,resp.getOutputStream());
} 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();
}
}
}
服务提供者启动类
package com.ql.learn.provider;
import com.ql.learn.pojo.URL;
import com.ql.learn.registry.NativeRegistry;
import com.ql.learn.service.HelloService;
import com.ql.learn.service.impl.HelloServiceImpl;
import com.ql.learn.tomcat.HttpServer;
/**
* @author qinlei
* @description todo
* @date 2020/9/18 17:19
*/
public class ServiceProvider {
public static void main(String[] args) {
//真正的注册服务
URL url = new URL("localhost",8899);
NativeRegistry.registry(HelloService.class.getName(),url,HelloServiceImpl.class);
//启动tomcat,暴露服务
HttpServer httpServer = new HttpServer();
httpServer.start(url.getHostname(),url.getPort());
}
}
服务消费者consumer
代码结构
核心代码
发起远程调用
package com.ql.learn.consumer;
import com.ql.learn.pojo.Invocation;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* @author qinlei
* @description 发起远程调用
* @date 2020/9/19 9:02
*/
public class HttpClient {
public String post(String hostname, int port , Invocation invocation){
try {
//进行连接
URL url = new URL("http",hostname,port,"/client");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
//发送调用信息
OutputStream ops = connection.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ops);
oos.writeObject(invocation);
oos.flush();
oos.close();
//将输入流转为字符串(这里可以是java对象) 获取远程调用的结果
InputStream ins = connection.getInputStream();
return IOUtils.toString(ins,"UTF-8");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
消费者入口
package com.ql.learn.consumer;
import com.ql.learn.pojo.Invocation;
import com.ql.learn.service.HelloService;
/**
* @author qinlei
* @description todo
* @date 2020/9/19 9:32
*/
public class ConsumerMain {
public static void main(String[] args) {
Object[] params = new Object[1];
params[0] = "rpcDemo客户端";
Invocation invocation = new Invocation(HelloService.class.getName(), "sayHello", params, new Class[]{String.class});
HttpClient httpClient = new HttpClient();
String post = httpClient.post("localhost", 8899, invocation);
System.out.println(post);
}
}
源码地址:
https://github.com/qlanto224/RpcDemo.git