RPC基础知识
 
什么是RPC?
RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。
RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
 
RPC的模型
C/S模式 
基于传输层协议(例如TCP/IP)  远程调用不是新的一种数据传输协议
事件响应基本模型(请求、计算、响应)
 
RPC设计的目的
通过固定的协议调用非本机的方法
提供不同语言程序之间通信
可以在不了解底层通信,像本地方法一样调用
 
 
RPC框架完全封装了网络传输以及其他细节,比如Spring 的RPC框架在调用远程对象的方法时就像调用Spring Bean 对象一样使用.
RPC的应用 大量的分布式应用都使用了RPC协议,比如分布式操作系统、分布式计算、分布式软件设计
 
RPC过程详解

RPC框架封装网络传输和其他细节,消费者和生产者不用去关心底层原理

消费者的代理层控制了整个RPC调用的流程,生成代理对象,封装请求报文,发送请求之类的

服务提供者会有一个监听模块,用来监听请求,并且按照约定,应该是注册了的服务才会被消费者调用到,注册的服务需要被反射调用到,用来计算结果
 
RPC框架的特点和设计模型
 
封装网络交互
尽量不要让RPC框架的使用者涉及到过多的网络层的开发
远程调用对象的代理
将接口代理的对象放入到Spring 容器之中,方便服务端开发
支持容器(Spring、Jetty等)
支持Spring容器,还有Jetty这样的web容器
可配置,可扩展
尽量做到可配置,可扩展
 
设计模型

 
Proxy代理层
用于对象的代理,对象的反射调用,RPC流程的控制
Serialize序列化层
将请求和结果做序列化和反序列化
Invoke网络模块
网络通信相关的处理
Container容器组件
支持代理层监听网络请求
 
代码实现

pom.xml
 
- <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.ibigsea</groupId>  
 
-   <artifactId>http-rpc</artifactId>  
 
-   <version>0.0.1-SNAPSHOT</version>  
 
-     
 
-   <dependencies>  
 
-         <dependency>  
 
-             <groupId>com.alibaba</groupId>  
 
-             <artifactId>fastjson</artifactId>  
 
-             <version>1.2.3</version>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>ch.qos.logback</groupId>  
 
-             <artifactId>logback-classic</artifactId>  
 
-             <version>1.0.13</version>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>org.mortbay.jetty</groupId>  
 
-             <artifactId>jetty</artifactId>  
 
-             <version>6.1.26</version>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>org.apache.httpcomponents</groupId>  
 
-             <artifactId>httpcore</artifactId>  
 
-             <version>4.3.3</version>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>org.apache.httpcomponents</groupId>  
 
-             <artifactId>httpclient</artifactId>  
 
-             <version>4.3.6</version>  
 
-             <exclusions>  
 
-                 <exclusion>  
 
-                     <artifactId>commons-logging</artifactId>  
 
-                     <groupId>commons-logging</groupId>  
 
-                 </exclusion>  
 
-             </exclusions>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>org.springframework</groupId>  
 
-             <artifactId>spring-context</artifactId>  
 
-             <version>3.2.8.RELEASE</version>  
 
-             <exclusions>  
 
-                 <exclusion>  
 
-                     <artifactId>commons-logging</artifactId>  
 
-                     <groupId>commons-logging</groupId>  
 
-                 </exclusion>  
 
-             </exclusions>  
 
-         </dependency>  
 
-         <dependency>  
 
-           <groupId>commons-logging</groupId>  
 
-           <artifactId>commons-logging</artifactId>  
 
-           <version>1.2</version>  
 
-         </dependency>  
 
-   </dependencies>  
 
- </project>  
 
 
config包下面的
 
ConsumerConfig.java
 
- package com.ibigsea.rpc.config;  
 
-   
 
- public class ConsumerConfig {  
 
-   
 
-     
 
-     private String url;  
 
-   
 
-     public String getUrl() {  
 
-         return url;  
 
-     }  
 
-   
 
-     public void setUrl(String url) {  
 
-         this.url = url;  
 
-     }  
 
-   
 
- }   
 
 
ProviderConfig.java
- package com.ibigsea.rpc.config;  
 
-   
 
- public class ProviderConfig {  
 
-   
 
-     
 
-     private int port;  
 
-   
 
-     public ProviderConfig() {  
 
-     }  
 
-   
 
-     public ProviderConfig(int port) {  
 
-         this.port = port;  
 
-     }  
 
-   
 
-     public int getPort() {  
 
-         return port;  
 
-     }  
 
-   
 
-     public void setPort(int port) {  
 
-         this.port = port;  
 
-     }  
 
-   
 
- }   
 
 
 
序列化层
Request.java
 
- package com.ibigsea.rpc.serizlize;  
 
-   
 
- import java.io.Serializable;  
 
-   
 
- import com.alibaba.fastjson.annotation.JSONType;  
 
-   
 
- public class Request implements Serializable {  
 
-   
 
-     private static final long serialVersionUID = -4363326153251862952L;  
 
-   
 
-     private Class clazz;  
 
-   
 
-     private String method;  
 
-   
 
-     private Object param;  
 
-   
 
-     public Request() {  
 
-     }  
 
-   
 
-     public Request(Class clazz, String method, Object param) {  
 
-         this.clazz = clazz;  
 
-         this.method = method;  
 
-         this.param = param;  
 
-     }  
 
-   
 
-     public Class getClazz() {  
 
-         return clazz;  
 
-     }  
 
-   
 
-     public void setClazz(Class clazz) {  
 
-         this.clazz = clazz;  
 
-     }  
 
-   
 
-     public String getMethod() {  
 
-         return method;  
 
-     }  
 
-   
 
-     public void setMethod(String method) {  
 
-         this.method = method;  
 
-     }  
 
-   
 
-     public Object getParam() {  
 
-         return param;  
 
-     }  
 
-   
 
-     public void setParam(Object param) {  
 
-         this.param = param;  
 
-     }  
 
-   
 
-     
 
-     public Object invoke(Object bean) throws Exception {  
 
-         return clazz.getMethod(method, param.getClass()).invoke(bean, param);  
 
-     }  
 
-   
 
- }  
 
 
JsonParser.java
 
 
- package com.ibigsea.rpc.serizlize;  
 
-   
 
- import com.alibaba.fastjson.JSON;  
 
- import com.alibaba.fastjson.parser.ParserConfig;  
 
- import com.alibaba.fastjson.serializer.SerializerFeature;  
 
-   
 
- public class JsonParser {  
 
-     
 
-     public static Request reqParse(String param) {  
 
-         return JSON.parseObject(param, Request.class);  
 
-     }  
 
-   
 
-     
 
-     public static <T> T resbParse(String result) {  
 
-         return (T) JSON.parse(result);  
 
-     }  
 
-   
 
- }  
 
 
JsonFormatter.java
 
 
- package com.ibigsea.rpc.serizlize;  
 
-   
 
- import com.alibaba.fastjson.JSON;  
 
- import com.alibaba.fastjson.parser.ParserConfig;  
 
- import com.alibaba.fastjson.serializer.SerializerFeature;  
 
-   
 
- public class JsonFormatter {  
 
-   
 
-     
 
-     public static String reqFormatter(Class clazz, String method, Object param) {  
 
-         Request request = new Request(clazz, method, param);  
 
-         return JSON.toJSONString(request, SerializerFeature.WriteClassName);  
 
-     }  
 
-   
 
-     
 
-     public static String resbFormatter(Object param) {  
 
-         return JSON.toJSONString(param, SerializerFeature.WriteClassName);  
 
-     }  
 
-   
 
- }  
 
 
http容器  httpContainer.java
 
 
- package com.ibigsea.rpc.container;  
 
-   
 
- import org.mortbay.jetty.Connector;  
 
- import org.mortbay.jetty.Server;  
 
- import org.mortbay.jetty.handler.AbstractHandler;  
 
- import org.mortbay.jetty.nio.SelectChannelConnector;  
 
- import org.slf4j.Logger;  
 
- import org.slf4j.LoggerFactory;  
 
-   
 
- import com.ibigsea.rpc.config.ProviderConfig;  
 
-   
 
- public class HttpContainer {  
 
-   
 
-     private Logger LOG = LoggerFactory.getLogger(HttpContainer.class);  
 
-   
 
-     private AbstractHandler httpHandler;  
 
-     private ProviderConfig providerConfig;  
 
-   
 
-     
 
-     public HttpContainer(AbstractHandler httpHandler) {  
 
-         this(httpHandler, new ProviderConfig(8080));  
 
-     }  
 
-   
 
-     
 
-     public HttpContainer(AbstractHandler httpHandler, ProviderConfig providerConfig) {  
 
-         this.httpHandler = httpHandler;  
 
-         this.providerConfig = providerConfig;  
 
-     }  
 
-   
 
-     public void start() {  
 
-         
 
-         Server server = new Server();  
 
-         try {  
 
-             SelectChannelConnector connector = new SelectChannelConnector();  
 
-             
 
-             connector.setPort(providerConfig.getPort());  
 
-             
 
-             server.setHandler(httpHandler);  
 
-             server.setConnectors(new Connector[] { connector });  
 
-             server.start();  
 
-             LOG.info("容器启动~");  
 
-         } catch (Exception e) {  
 
-             LOG.error("容器启动异常~", e);  
 
-         }  
 
-   
 
-     }  
 
-   
 
- }   
 
 
RpcException.java
 
 
- package com.ibigsea.rpc.exception;  
 
-   
 
- public class RpcException extends Throwable {  
 
-     private Object data;  
 
-   
 
-     public RpcException(String message, Throwable cause, Object data) {  
 
-         super(message, cause);  
 
-         this.data = data;  
 
-     }  
 
-   
 
-     public RpcException(Object data) {  
 
-         super();  
 
-         this.data = data;  
 
-     }  
 
-   
 
-     public Object getData() {  
 
-         return data;  
 
-     }  
 
- }  
 
 
HttpInvoke.java
 
 
- package com.ibigsea.rpc.invoke;  
 
-   
 
- import java.io.OutputStream;  
 
- import java.util.ArrayList;  
 
- import java.util.List;  
 
-   
 
- import org.apache.http.HttpHost;  
 
- import org.apache.http.HttpResponse;  
 
- import org.apache.http.NameValuePair;  
 
- import org.apache.http.client.HttpClient;  
 
- import org.apache.http.client.entity.UrlEncodedFormEntity;  
 
- import org.apache.http.client.methods.HttpPost;  
 
- import org.apache.http.conn.routing.HttpRoute;  
 
- import org.apache.http.impl.client.HttpClients;  
 
- import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
 
- import org.apache.http.message.BasicNameValuePair;  
 
- import org.apache.http.util.EntityUtils;  
 
-   
 
- import com.ibigsea.rpc.config.ConsumerConfig;  
 
- import com.ibigsea.rpc.exception.RpcException;  
 
-   
 
- public class HttpInvoke {  
 
-   
 
-     private static final HttpClient httpClient = getHttpClient();  
 
-   
 
-     
 
-     private static HttpInvoke httpInvoke;  
 
-   
 
-     private HttpInvoke() {  
 
-   
 
-     }  
 
-   
 
-     public static synchronized HttpInvoke getInstance() {  
 
-         if (httpInvoke == null) {  
 
-             httpInvoke = new HttpInvoke();  
 
-         }  
 
-         return httpInvoke;  
 
-     }  
 
-   
 
-     
 
-     public String request(String request, ConsumerConfig consumerConfig) throws RpcException {  
 
-         HttpPost post = new HttpPost(consumerConfig.getUrl());  
 
-         
 
-         post.setHeader("Connection", "Keep-Alive");  
 
-         List<NameValuePair> params = new ArrayList<NameValuePair>();  
 
-         params.add(new BasicNameValuePair("data", request));  
 
-   
 
-         try {  
 
-             post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));  
 
-             HttpResponse response = httpClient.execute(post);  
 
-             if (response.getStatusLine().getStatusCode() == 200) {  
 
-                 return EntityUtils.toString(response.getEntity(), "UTF-8");  
 
-             }  
 
-             throw new RpcException(request);  
 
-         } catch (Exception e) {  
 
-             throw new RpcException("http调用异常", e, request);  
 
-         }  
 
-     }  
 
-   
 
-     
 
-     public void response(String response, OutputStream outputStream) throws RpcException {  
 
-         try {  
 
-             outputStream.write(response.getBytes("UTF-8"));  
 
-             outputStream.flush();  
 
-         } catch (Exception e) {  
 
-             e.printStackTrace();  
 
-         }  
 
-     }  
 
-   
 
-     private static HttpClient getHttpClient() {  
 
-         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();  
 
-         
 
-         cm.setMaxTotal(200);  
 
-         
 
-         cm.setDefaultMaxPerRoute(20);  
 
-         
 
-         HttpHost localhost = new HttpHost("localhost", 8080);  
 
-         cm.setMaxPerRoute(new HttpRoute(localhost), 50);  
 
-         
 
-         return HttpClients.custom().setConnectionManager(cm).build();  
 
-     }  
 
-   
 
- }  
 
 
接下来就是代理成了,因为我们使用了jetty容器,所以这里对服务提供者的代理我们通过jetty的AbstractHandler来实现请求的处理
 
ProviderProxyFactory.java
 
- package com.ibigsea.rpc.proxy;  
 
-   
 
- import java.io.IOException;  
 
- import java.util.Map;  
 
- import java.util.concurrent.ConcurrentHashMap;  
 
-   
 
- import javax.servlet.ServletException;  
 
- import javax.servlet.http.HttpServletRequest;  
 
- import javax.servlet.http.HttpServletResponse;  
 
-   
 
- import org.mortbay.jetty.handler.AbstractHandler;  
 
- import org.mortbay.log.Log;  
 
- import org.slf4j.Logger;  
 
- import org.slf4j.LoggerFactory;  
 
-   
 
- import com.ibigsea.rpc.config.ProviderConfig;  
 
- import com.ibigsea.rpc.container.HttpContainer;  
 
- import com.ibigsea.rpc.exception.RpcException;  
 
- import com.ibigsea.rpc.invoke.HttpInvoke;  
 
- import com.ibigsea.rpc.serizlize.JsonFormatter;  
 
- import com.ibigsea.rpc.serizlize.JsonParser;  
 
- import com.ibigsea.rpc.serizlize.Request;  
 
-   
 
- public class ProviderProxyFactory extends AbstractHandler {  
 
-   
 
-     private Logger LOG = LoggerFactory.getLogger(ProviderProxyFactory.class);  
 
-   
 
-     
 
-     private Map<Class, Object> providers = new ConcurrentHashMap<Class, Object>();  
 
-   
 
-     
 
-     private static ProviderProxyFactory factory;  
 
-   
 
-     private static HttpInvoke invoke = HttpInvoke.getInstance();  
 
-   
 
-     
 
-     public ProviderProxyFactory(Map<Class, Object> providers, ProviderConfig config) {  
 
-         this.providers = providers;  
 
-         HttpContainer container = new HttpContainer(this, config);  
 
-         container.start();  
 
-         factory = this;  
 
-         for (Map.Entry<Class, Object> entry : providers.entrySet()) {  
 
-             Log.info(entry.getKey().getSimpleName() + " register");  
 
-         }  
 
-     }  
 
-   
 
-     
 
-     public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)  
 
-             throws IOException, ServletException {  
 
-         
 
-         String data = request.getParameter("data");  
 
-   
 
-         try {  
 
-             
 
-             Request req = JsonParser.reqParse(data);  
 
-             
 
-             Object res = req.invoke(ProviderProxyFactory.getInstance().getBeanByClass(req.getClazz()));  
 
-             
 
-             invoke.response(JsonFormatter.resbFormatter(res), response.getOutputStream());  
 
-         } catch (Exception e) {  
 
-             e.printStackTrace();  
 
-         } catch (RpcException e) {  
 
-             e.printStackTrace();  
 
-         }  
 
-   
 
-     }  
 
-   
 
-     public Object getBeanByClass(Class clazz) throws RpcException {  
 
-         Object bean = providers.get(clazz);  
 
-         if (bean != null) {  
 
-             return bean;  
 
-         }  
 
-         throw new RpcException("service no register", new NullPointerException(), clazz);  
 
-     }  
 
-   
 
-     public static ProviderProxyFactory getInstance() {  
 
-         return factory;  
 
-     }  
 
-   
 
- }  
 
 
对于服务消费者,我们通过jdk的invocationHandler来生成代理对象,对于生成的代理对象都会去执行invoke方法
 
ConsumerProxyFatory.java
 
- package com.ibigsea.rpc.proxy;  
 
-   
 
- import java.lang.reflect.InvocationHandler;  
 
- import java.lang.reflect.Method;  
 
- import java.lang.reflect.Proxy;  
 
-   
 
- import com.ibigsea.rpc.config.ConsumerConfig;  
 
- import com.ibigsea.rpc.invoke.HttpInvoke;  
 
- import com.ibigsea.rpc.serizlize.JsonFormatter;  
 
- import com.ibigsea.rpc.serizlize.JsonParser;  
 
-   
 
- public class ConsumerProxyFactory implements InvocationHandler {  
 
-   
 
-     
 
-     private ConsumerConfig config;  
 
-   
 
-     
 
-     private String clazz;  
 
-   
 
-     private static HttpInvoke invoke = HttpInvoke.getInstance();  
 
-   
 
-     
 
-     public Object create() throws ClassNotFoundException {  
 
-         Class interfaceClass = Class.forName(clazz);  
 
-         return Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[] { interfaceClass }, this);  
 
-     }  
 
-   
 
-     
 
-     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
 
-         
 
-         Class interfaceClass = proxy.getClass().getInterfaces()[0];  
 
-         
 
-         String req = JsonFormatter.reqFormatter(interfaceClass, method.getName(), args[0]);  
 
-         
 
-         String resb = invoke.request(req, config);  
 
-         
 
-         return JsonParser.resbParse(resb);  
 
-     }  
 
-   
 
-     public ConsumerConfig getConfig() {  
 
-         return config;  
 
-     }  
 
-   
 
-     public void setConfig(ConsumerConfig config) {  
 
-         this.config = config;  
 
-     }  
 
-   
 
-     public String getClazz() {  
 
-         return clazz;  
 
-     }  
 
-   
 
-     public void setClazz(String clazz) {  
 
-         this.clazz = clazz;  
 
-     }  
 
-   
 
- }  
 
 
简单的RPC框架已经写好
 
然后我们准备一个公共的接口jar

pom里面什么依赖都没有
HelloInterface.java
 
- package com.ibigsea.facade;  
 
-   
 
- import com.ibigsea.vo.People;  
 
-   
 
- public interface HelloInterface {  
 
-   
 
-     public String speak(People people);  
 
-       
 
- }  
 
 
People.java
 
 
- package com.ibigsea.vo;  
 
-   
 
- import java.io.Serializable;  
 
-   
 
- public class People implements Serializable {  
 
-   
 
-     private static final long serialVersionUID = 1L;  
 
-       
 
-     private String name;  
 
-   
 
-     public People() {  
 
-     }  
 
-   
 
-     public People(String name) {  
 
-         this.name = name;  
 
-     }  
 
-   
 
-     public String getName() {  
 
-         return name;  
 
-     }  
 
-   
 
-     public void setName(String name) {  
 
-         this.name = name;  
 
-     }  
 
-       
 
- }  
 
 
接口定义好了 ,我们可以开始弄服务提供者和服务消费者了
 
服务提供者

pom.xml
 
- <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.ibigsea</groupId>  
 
-   <artifactId>demo-provider</artifactId>  
 
-   <version>0.0.1-SNAPSHOT</version>  
 
-   <dependencies>  
 
-     <dependency>    
 
-         <groupId>com.ibigsea</groupId>  
 
-         <artifactId>http-rpc</artifactId>  
 
-         <version>0.0.1-SNAPSHOT</version>  
 
-     </dependency>  
 
-     <dependency>    
 
-           <groupId>com.ibigsea</groupId>  
 
-           <artifactId>demo-facade</artifactId>  
 
-           <version>0.0.1-SNAPSHOT</version>  
 
-     </dependency>  
 
-   </dependencies>  
 
- </project>  
 
 
HelloService.java
 
 
- package com.ibigsea.service;  
 
-   
 
- import org.springframework.stereotype.Service;  
 
-   
 
- import com.ibigsea.facade.HelloInterface;  
 
- import com.ibigsea.vo.People;  
 
-   
 
- @Service("helloInterface")  
 
- public class HelloService implements HelloInterface {  
 
-   
 
-     
 
-     public String speak(People people) {  
 
-         return "Hello " + people.getName();  
 
-     }  
 
-   
 
- }   
 
 
启动类App.java
 
 
- package com.ibigsea;  
 
-   
 
- import java.util.concurrent.CountDownLatch;  
 
-   
 
- import org.springframework.context.support.ClassPathXmlApplicationContext;  
 
-   
 
- public class App {  
 
-       
 
-      public static void main(String[] args) throws Exception {  
 
-          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:spring-*.xml");  
 
-          context.start();  
 
-          CountDownLatch countDownLatch = new CountDownLatch(1);  
 
-          countDownLatch.await();  
 
-      }  
 
-       
 
- }   
 
 
spring-context.xml
 
 
- <?xml version="1.0" encoding="UTF-8"?>  
 
- <beans xmlns="http://www.springframework.org/schema/beans"  
 
-     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"  
 
-     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
 
-     xmlns:util="http://www.springframework.org/schema/util"  
 
-     xsi:schemaLocation="  
 
-           http://www.springframework.org/schema/beans  
 
-           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
 
-        http://www.springframework.org/schema/tx  
 
-        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
 
-        http://www.springframework.org/schema/aop  
 
-        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
 
-        http://www.springframework.org/schema/util  
 
-        http://www.springframework.org/schema/util/spring-util-3.1.xsd  
 
-        http://www.springframework.org/schema/context  
 
-        http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
 
-   
 
-   
 
-     
 
-     <context:component-scan base-package="com.ibigsea" />  
 
-     
 
-     <context:annotation-config />  
 
-   
 
-     
 
-     <bean class="com.ibigsea.rpc.proxy.ProviderProxyFactory">  
 
-         <constructor-arg name="providers">  
 
-             <map key-type="java.lang.Class" value-type="java.lang.Object">  
 
-                 
 
-                 <entry key="com.ibigsea.facade.HelloInterface" value-ref="helloInterface"/>  
 
-             </map>  
 
-         </constructor-arg>  
 
-         <constructor-arg name="config">  
 
-             <bean id="providerConfig" class="com.ibigsea.rpc.config.ProviderConfig">  
 
-                 <property name="port" value="8888"/>  
 
-             </bean>  
 
-         </constructor-arg>  
 
-     </bean>  
 
-   
 
- </beans>  
 
 
服务消费者
 

pom.xml
 
- <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.ibigsea</groupId>  
 
-   <artifactId>demo-comsumer</artifactId>  
 
-   <version>0.0.1-SNAPSHOT</version>  
 
-     
 
-   <dependencies>  
 
-     <dependency>    
 
-         <groupId>com.ibigsea</groupId>  
 
-         <artifactId>http-rpc</artifactId>  
 
-         <version>0.0.1-SNAPSHOT</version>  
 
-     </dependency>  
 
-     <dependency>    
 
-           <groupId>com.ibigsea</groupId>  
 
-           <artifactId>demo-facade</artifactId>  
 
-           <version>0.0.1-SNAPSHOT</version>  
 
-     </dependency>  
 
-         <dependency>  
 
-             <groupId>junit</groupId>  
 
-             <artifactId>junit</artifactId>  
 
-             <version>4.11</version>  
 
-         </dependency>  
 
-         <dependency>  
 
-             <groupId>org.springframework</groupId>  
 
-             <artifactId>spring-test</artifactId>  
 
-             <version>3.2.8.RELEASE</version>  
 
-             <scope>test</scope>  
 
-         </dependency>  
 
-   </dependencies>  
 
-     
 
- </project>  
 
 
RefService.java
 
 
- package com.ibigsea.comsumer;  
 
-   
 
- import javax.annotation.Resource;  
 
-   
 
- import org.springframework.stereotype.Service;  
 
-   
 
- import com.ibigsea.facade.HelloInterface;  
 
- import com.ibigsea.vo.People;  
 
-   
 
- @Service("refService")  
 
- public class RefService {  
 
-       
 
-     
 
-     @Resource  
 
-     private HelloInterface helloInterface;  
 
-       
 
-     public void sayHello(String name) {  
 
-         System.out.println(helloInterface.speak(new People(name)));  
 
-     }  
 
-       
 
- }   
 
 
spring-context.xml
 
 
- <?xml version="1.0" encoding="UTF-8"?>  
 
- <beans xmlns="http://www.springframework.org/schema/beans"  
 
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"  
 
-        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
 
-        xmlns:util="http://www.springframework.org/schema/util"  
 
-        xsi:schemaLocation="  
 
-           http://www.springframework.org/schema/beans  
 
-           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
 
-        http://www.springframework.org/schema/tx  
 
-        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
 
-        http://www.springframework.org/schema/aop  
 
-        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
 
-        http://www.springframework.org/schema/util  
 
-        http://www.springframework.org/schema/util/spring-util-3.1.xsd  
 
-        http://www.springframework.org/schema/context  
 
-        http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
 
-   
 
-     <context:component-scan base-package="com.ibigsea" />  
 
-     <context:annotation-config />  
 
-   
 
-     <bean id="consumerConfig" class="com.ibigsea.rpc.config.ConsumerConfig">  
 
-         <property name="url" value="http://localhost:8888/invoke" />  
 
-     </bean>  
 
-   
 
-     <bean id="helloInterfaceInvoke" class="com.ibigsea.rpc.proxy.ConsumerProxyFactory">  
 
-         <property name="config" ref="consumerConfig"/>  
 
-         <property name="clazz" value="com.ibigsea.facade.HelloInterface"/>  
 
-     </bean>  
 
-     <bean id="helloInterface" factory-bean="helloInterfaceInvoke" factory-method="create"/>  
 
- </beans>  
 
 
测试类HttpRpcTest.java
 
 
- package com.zto.test;  
 
-   
 
- import org.junit.Test;  
 
- import org.junit.runner.RunWith;  
 
- import org.slf4j.Logger;  
 
- import org.slf4j.LoggerFactory;  
 
- import org.springframework.beans.factory.annotation.Autowired;  
 
- import org.springframework.test.context.ContextConfiguration;  
 
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
 
-   
 
- import com.ibigsea.comsumer.RefService;  
 
- import com.ibigsea.facade.HelloInterface;  
 
- import com.ibigsea.rpc.serizlize.JsonFormatter;  
 
-   
 
- @RunWith(SpringJUnit4ClassRunner.class)  
 
- @ContextConfiguration({"classpath*:spring-*.xml"})  
 
- public class HttpRpcTest  
 
- {  
 
-     private static final Logger logger = LoggerFactory.getLogger(HttpRpcTest.class);  
 
-   
 
-     @Autowired  
 
-     private RefService service;  
 
-   
 
-     @Test  
 
-     public void test() throws InterruptedException {  
 
-         service.sayHello("张三");  
 
-     }  
 
- }  
 
 
我们可以启动程序看看
 
先启动服务提供者,服务提供者控制台
 
- 五月 01, 2017 2:43:43 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh  
 
- 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@685f4c2e: startup date [Mon May 01 14:43:43 CST 2017]; root of context hierarchy  
 
- 五月 01, 2017 2:43:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions  
 
- 信息: Loading XML bean definitions from file [E:\workspace\rpcworkspace\demo-provider\target\classes\spring-context.xml]  
 
- 五月 01, 2017 2:43:44 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons  
 
- 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@26be92ad: defining beans [helloInterface,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,com.ibigsea.rpc.proxy.ProviderProxyFactory#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy  
 
- 14:43:45.608 [main] INFO  org.mortbay.log - Logging to Logger[org.mortbay.log] via org.mortbay.log.Slf4jLog  
 
- 14:43:45.622 [main] DEBUG org.mortbay.log - Container Server@4562e04d + ProviderProxyFactory@2a65fe7c as handler  
 
- 14:43:45.622 [main] DEBUG org.mortbay.log - Container Server@4562e04d + SelectChannelConnector@0.0.0.0:8888 as connector  
 
- 14:43:45.622 [main] INFO  org.mortbay.log - jetty-6.1.26  
 
- 14:43:45.638 [main] DEBUG org.mortbay.log - Container Server@4562e04d + org.mortbay.thread.QueuedThreadPool@235834f2 as threadpool  
 
- 14:43:45.639 [main] DEBUG org.mortbay.log - started org.mortbay.thread.QueuedThreadPool@235834f2  
 
- 14:43:45.640 [main] DEBUG org.mortbay.log - starting ProviderProxyFactory@2a65fe7c  
 
- 14:43:45.640 [main] DEBUG org.mortbay.log - started ProviderProxyFactory@2a65fe7c  
 
- 14:43:45.640 [main] DEBUG org.mortbay.log - starting Server@4562e04d  
 
- 14:43:45.691 [main] DEBUG org.mortbay.log - started org.mortbay.jetty.nio.SelectChannelConnector$1@2b71e916  
 
- 14:43:45.692 [main] INFO  org.mortbay.log - Started SelectChannelConnector@0.0.0.0:8888  
 
- 14:43:45.693 [main] DEBUG org.mortbay.log - started SelectChannelConnector@0.0.0.0:8888  
 
- 14:43:45.693 [main] DEBUG org.mortbay.log - started Server@4562e04d  
 
- 14:43:45.693 [main] INFO  c.i.rpc.container.HttpContainer - 容器启动~  
 
- 14:43:45.693 [main] INFO  org.mortbay.log - HelloInterface register  
 
 
然后执行服务消费者的测试方法,服务消费者控制台:
 
 
- 五月 01, 2017 2:44:31 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners  
 
- 信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.  
 
- 五月 01, 2017 2:44:31 下午 org.springframework.test.context.TestContextManager retrieveTestExecutionListeners  
 
- 信息: Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available.  
 
- 五月 01, 2017 2:44:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions  
 
- 信息: Loading XML bean definitions from file [E:\workspace\rpcworkspace\demo-comsumer\target\classes\spring-context.xml]  
 
- 五月 01, 2017 2:44:32 下午 org.springframework.context.support.GenericApplicationContext prepareRefresh  
 
- 信息: Refreshing org.springframework.context.support.GenericApplicationContext@7946e1f4: startup date [Mon May 01 14:44:32 CST 2017]; root of context hierarchy  
 
- 五月 01, 2017 2:44:32 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons  
 
- 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4f51b3e0: defining beans [refService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,consumerConfig,helloInterfaceInvoke,helloInterface,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy  
 
- Hello 张三  
 
- 五月 01, 2017 2:44:33 下午 org.springframework.context.support.GenericApplicationContext doClose  
 
- 信息: Closing org.springframework.context.support.GenericApplicationContext@7946e1f4: startup date [Mon May 01 14:44:32 CST 2017]; root of context hierarchy  
 
 
服务提供者这里输出了消费者请求的日志
 
 
- 14:44:33.117 [348984985@qtp-592983282-1 - /invoke] DEBUG org.mortbay.log - REQUEST /invoke on org.mortbay.jetty.HttpConnection@6e01b90  
 
- 14:44:33.213 [348984985@qtp-592983282-1 - /invoke] DEBUG org.mortbay.log - RESPONSE /invoke  200  
 
 
演示成功
 
 
注意
因为这里使用了fastjson,  而我们的Request里面有类信息,进行序列化和反序列的时候我们要在启动类增加参数
 -Dfastjson.parser.autoTypeSupport=true
其他解决方案看这里
https://github.com/alibaba/fastjson/wiki/enable_autotype
 

 
好了,这里的代码我会上传到我的github上面
简单Tomcat  HTTP RPC框架
原文:http://www.cnblogs.com/csguo/p/7572984.html