`
longgangbai
  • 浏览: 7281506 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java 网络编程,RMI,EJB之间那些屁事(二)

阅读更多

        使用RMI和EJB的童鞋,都知道EJB有客户端存根,和服务端骨架的说法。客户端调用服务其实是调用客户端的存根,客户端的存根调用相关的代理,代理向服务端发送请求,服务端响应请求,并将请求信息发送给代理,代理将结果返回给存根的。

 

   封装请求信息的类:

package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.*;
/**
 * 关于远程访问协议的信息
 * 用于封装请求中各种信息
 * @author longgangbai
 *
 */
public class Call implements Serializable{
  private String className;  //表示类名
  private String methodName; //表示方法名
  private Class[] paramTypes; //表示方法参数类型
  private Object[] params; //表示方法参数值
  private Object result;  //表示方法的返回值或者方法抛出的异常
  
  public Call(){}
  public Call(String className,String methodName,Class[] paramTypes,
                            Object[] params){
    this.className=className;
    this.methodName=methodName;
    this.paramTypes=paramTypes;
    this.params=params;
  }
  
  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[] getParamTypes(){return paramTypes;}
  public void setParamTypes(Class[] paramTypes){this.paramTypes=paramTypes;}

  public Object[] getParams(){return params;}
  public void setParams(Object[] params){this.params=params;}

  public Object getResult(){return result;}
  public void setResult(Object result){this.result=result;}

  public String toString(){
    return "className="+className+" methodName="+methodName;
  }
} 

 

 

处理客户端的信息:

package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.*;
import java.net.*;
/**
 * 关于客户端的连接信息
 * 
 * 客户端的处理的信息
 * 
 * @author longgangbai
 *
 */
public class Connector {
	//客户端的主机ip
  private String host;
  //客户端的主机端口
  private int port;
  //客户端远程对象
  private Socket skt;
  //客户端读取对象
  private InputStream is;
  private ObjectInputStream ois;
  //客户端写入对象
  private OutputStream os;
  private ObjectOutputStream oos;

  public Connector(String host,int port)throws Exception{
     this.host=host;
     this.port=port;
     connect(host,port);
  }
  /**
   * 设置对象序列化对象
   * @param obj
   * @throws Exception
   */
  public void send(Object obj)throws Exception{
    oos.writeObject(obj);
  }
  /**
   * 获取序列化对象
   * @return
   * @throws Exception
   */
  public Object receive() throws Exception{
    return ois.readObject();
  }
  
  public void connect()throws Exception{
    connect(host,port);
  }
  
  /**
   * 连接客户端
   * @param host
   * @param port
   * @throws Exception
   */
  public void connect(String host,int port)throws Exception{
    skt=new Socket(host,port);
    os=skt.getOutputStream();
    oos=new ObjectOutputStream(os);
    is=skt.getInputStream();
    ois=new ObjectInputStream(is);
  }
  /**
   * 关闭客户端的资源的信息
   */
  public void close(){
    try{
    }finally{
      try{
        ois.close();
        oos.close();
        skt.close();
      }catch(Exception e){
        System.out.println("Connector.close: "+e);
      }
    }
  }
}



 

 远程访问的代理工厂 获取代理的对象

package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.lang.reflect.*;
/**
 * 远程访问的代理工厂
 * 
 * 获取代理的对象
 * @author longgangbai
 *
 */
public class ProxyFactory {
	/**
	 * 获取远程访问的bean 对象
	 * @param classType
	 * @param host
	 * @param port
	 * @return
	 */
	public static Object getProxy(final Class classType,final String host,final int port){
    InvocationHandler handler=new InvocationHandler(){
      public Object invoke(Object proxy,Method method,Object args[])
                                                       throws Exception{
    	//调用远程对象返回的结果信息
        Connector connector=null;
        try{
          //设置远程访问的客户端信息
          connector=new Connector(host,port);
          //构建远程访问的信息
          Call call=new Call(classType.getName(),
              method.getName(),method.getParameterTypes(),args); 
          //发送客户端请求的信息
          connector.send(call);
          //接受服务端发送的结果
          call=(Call)connector.receive();
          //获取结果信息
          Object result=call.getResult();
          if(result instanceof Throwable)
            throw new RemoteException((Throwable)result);
          else
            return result;
        }finally{
        	if(connector!=null)
        		connector.close();
        	}
      }
    };
    //客户端返回执行代理
    return Proxy.newProxyInstance(classType.getClassLoader(),
    		classType.getInterfaces(),handler);
  }
}

 

服务端代理工厂:

package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.InputStream;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import com.easyway.space.basic.patterns.proxys.HelloServiceImpl;
/**
 * 远程代理的服务处理类
 * @author Owner
 *
 */
public class ServiceProxyExporterServer {
	
  //用于缓存服务端的实例对象
  private Map<String,Object> remoteObjects=new HashMap<String,Object>();
  
  /**
   * 注册服务端的实例对象
   * @param className
   * @param remoteObject
   */
  public void register(String className,Object remoteObject){
    remoteObjects.put( className,remoteObject);
  } 
  /**
   * 处理相关的客户端请求的信息
   * @throws Exception
   */
  public void service()throws Exception{
	//服务端的网络的对象
    ServerSocket serverSocket = new ServerSocket(8000);
    System.out.println("服务器启动.");
    while(true){
    	//获取客户端的网络对象
      Socket socket=serverSocket.accept();
      //获取客户端的远程读写对象
      InputStream in=socket.getInputStream();
      ObjectInputStream ois=new ObjectInputStream(in);
      OutputStream out=socket.getOutputStream();
      ObjectOutputStream oos=new ObjectOutputStream(out);
      //获取远程执行的对象
      Call call=(Call)ois.readObject();
      System.out.println(call);
      //获取远程调用的方法
      call=invoke(call);
      //将执行结果写入到序列化对象中
      oos.writeObject(call);
      //关闭相关的资源
      ois.close();
      oos.close();
      socket.close();
    }
  }

   /**
    * 获取服务端响应的结果的信息,并封装返回结果
    * 
    * @param call
    * @return
    */
  public Call invoke(Call call){
    Object result=null;
    try{
     //获取执行的方法各种信息
      String className=call.getClassName();
      String methodName=call.getMethodName();
      Object[] params=call.getParams();
      Class classType=Class.forName(className); 
      Class[] paramTypes=call.getParamTypes();
      //获取远程访问方法
      Method method=classType.getMethod(methodName,paramTypes);  
      //获取执行执行对象
      Object remoteObject=remoteObjects.get(className);
      if(remoteObject==null){
        throw new Exception(className+"的远程对象不存在");
      }else{
    	//执行远程方法
        result=method.invoke(remoteObject,params);
      }
    }catch(Exception e){
    	result=e;
    }
    //设置远程方法的结果
    call.setResult(result);
    return call;
  }

  public static void main(String args[])throws Exception {
    ServiceProxyExporterServer server=new ServiceProxyExporterServer();
    server.register("com.easyway.space.basic.patterns.proxys.HelloService",new HelloServiceImpl());
    server.service();
  }
}

 

客户端调用:

package com.easyway.space.basic.network.sockets.remoting.proxy;
import com.easyway.space.basic.patterns.proxys.HelloService;

public class RemoteProxyClient {
  public static void main(String args[])throws Exception {
    //创建动态代理类实例
    HelloService helloService2=
         (HelloService)ProxyFactory.getProxy(HelloService.class,"localhost",8000);
    System.out.println(helloService2.getClass().getName());
    System.out.println(helloService2.echo("hello"));
    System.out.println(helloService2.getTime());
  }
}

 

 

分享到:
评论

相关推荐

    机械制造技术基础期末试题及答案.pdf

    机械制造技术基础期末试题及答案

    LCD1602的相关案例.txtLCD1602的相关案例.txt

    LCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1602的相关案例.txtLCD1

    接口知识点习题及参考答案

    接口知识点习题及参考答案

    第五节 极限运算法则.ppt

    第五节 极限运算法则

    第16章 滚动轴承-西科大.ppt

    第16章 滚动轴承-西科大

    20240705作业1

    20240705作业1

    第21章MyBatis-Plus多数据源支持

    第21章MyBatis-Plus多数据源支持

    大学物理期末复习试题附答案.pdf

    大学物理期末复习试题附答案

    10-3洛伦兹力与带电粒子在磁场中的运动.ppt

    10-3洛伦兹力与带电粒子在磁场中的运动

    现代机器人学:机构、规划与控制课后习题答案

    链接来源是reddit,用英文搜索书名加上solution,免费分析,便于大家寻找(如果被XX弄得收费了用梯子上reddit上应该能找到)来源:https://www.reddit.com/r/robotics/comments/dnsj7c/q_solution_manual_for_modern_robotics_mechanics/

    TCP协议三次握手和四次解手

    本资源使用绘画工具,用图形加文字共同讲解

    基于Python的MetaShape(photoscan)源代码(包含可视化窗体)

    本代码由CSDN用户CV_X.Wang提供,除非获得授权,任何人不得用于商业、教学、科研等。 本代码基于Python与MetaShape库文件,本人调用了MetaShape 的API接口,实现了相较于软件,更加快速处理操作。

    ZXM61N03FTA-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明

    SOT23;N—Channel沟道,30V;6.5A;RDS(ON)=30mΩ@VGS=10V,VGS=20V;Vth=1.2~2.2V;

    matlab画图案例.doc

    MATLAB画图案例详解 MATLAB是一款功能强大的数学计算与可视化软件,广泛应用于科学研究、工程设计等众多领域。其中,MATLAB的画图功能是其一大亮点,它提供了丰富的图形绘制函数,能够帮助用户直观地展示数据和分析结果。本文将通过一个详细的案例,深入解析MATLAB的画图功能。 一、案例背景 假设我们有一组实验数据,记录了在不同温度下某种材料的电阻值。现在,我们需要使用MATLAB来绘制这组数据的散点图,并通过拟合得到电阻与温度之间的关系曲线。最后,我们还需要对图形进行美化,使其更加符合学术报告的发表要求。 二、数据准备 首先,我们需要准备实验数据。在MATLAB中,我们可以使用数组来存储这些数据。为了简化案例,我们随机生成一组模拟数据来代表实验数据。

    MDM.02 主数据标准定义V1.0-模板

    MDM.02 主数据标准定义V1.0_模板

    数据库复习(2024).pdf

    数据库复习(2024).pdf

    Apple Swift编程语言入门教程

    Apple Swift编程语言入门教程

    stm32cubemx.docx

    STM32CubeMX 是一款由 STMicroelectronics 开发的图形化配置工具,用于生成 STM32 微控制器的初始化代码和配置文件。它主要用于帮助开发者快速配置 STM32 微控制器的引脚映射、时钟树、外设设置等,从而加快嵌入式项目的开发进程。 主要特点和功能: 图形化配置界面: STM32CubeMX 提供了一个直观的图形界面,用户可以通过拖拽和点击等操作来配置 STM32 微控制器的各种参数和外设。 自动代码生成: 根据用户在界面上的配置,STM32CubeMX 可以自动生成初始化代码和配置文件,包括初始化时钟设置、引脚映射、外设配置等。 支持多种STM32系列微控制器: STM32CubeMX 支持广泛的 STM32 系列微控制器,包括不同型号和不同系列,如STM32F0、STM32F1、STM32F4 等。 时钟树配置: 用户可以通过 STM32CubeMX 配置微控制器的时钟树,包括时钟源、分频器、PLL 设置等,以满足具体应用的时钟需求。 外设配置: 支持配置多种外设,如 USART、SPI、I2C、ADC、DMA 等,用户可以方便地配置这些外设

    VOLTE失败码速查表

    VoLTE语言通话服务时,我们可能会遇到各种失败情况。为了帮助大家快速定位和解决这些问题,我整理了一份详细的VoLTE失败码速查表,并分享给大家。这个速查表的主要功能包括快速诊断问题、提高解决效率、学习和培训以及提升用户体验。速查表列出了常见的VoLTE失败代码及其错误原因,技术人员可以通过查阅速查表迅速了解失败的具体原因,减少诊断时间。每个失败码都有详细的描述和解决建议,技术人员可以根据这些建议,快速采取措施,提高问题解决效率。对于新手工程师和自学者来说,速查表是一个很好的学习工具,通过研究每个失败码的原因和解决方案,可以加深对VoLTE技术的理解。通过快速定位和解决VoLTE问题,可以减少用户的等待时间,提升用户的使用体验和满意度。 使用速查表的方法非常简单。当VoLTE通话失败时,系统返回一个失败码。可以在速查表中找到对应的失败码,查看其描述和可能原因。根据速查表中的描述,分析失败的可能原因,考虑网络状态、设备配置等因素。根据速查表中提供的解决建议,采取相应措施进行处理,如检查网络连接、重启设备等。

Global site tag (gtag.js) - Google Analytics