使用序列化将对象传递给另一个JVM – 相同的Java版本和jar(都运行我们的应用程序)

更新:现在使用地图。 想要向其他实例发送内容的类发送对象即路由字符串。

使用对象流,使用Java serializable将对象写入servlet。

先写字符串然后再写对象。

接收servlet将输入流包装在ObjectInputStream周围。 首先读取字符串然后读取Object。 路由字符串决定它去了。

更通用的方法可能是发送类名及其声明的方法或Spring bean名称,但这对我们来说已经足够了。


原始问题

了解基本方法,但需要步骤的详细信息。 还知道我可以使用Jaxb或RMI或EJB …但是想使用纯序列化到bytearray然后进行编码,将它从jvm 1中的servlet 1发送到jvm 2中的servlet 2(同一个中的两个app server实例)局域网,在两个J2EE应用程序中设置相同的Java版本和jar)

基本步骤是(Approcah 1): –

  1. 将任何Serializable对象序列化为字节数组并生成一个字符串。 确切的代码见下文

  2. Base64输出1.是否需要基于64或可以跳过第2步?

  3. 使用java.util.URLEncode.encode对字符串进行编码

  4. 命名参数后,使用apache http组件或URL类从servlet 1发送到2

  5. 在Servlet 2 J2EE框架上已经有URLDecoced它,现在只需执行反向步骤并根据param名称转换为对象。 既然两者都是我们的应用程序,我们就会知道类型/类映射的param名称。 基本上寻找在JVM之间发送对象的最快和最方便的方法。

示例:要发送的POJO类

package tst.ser; import java.io.Serializable; public class Bean1 implements Serializable { /** * make it 2 if add something without default handling */ private static final long serialVersionUID = 1L; private String s; public String getS() { return s; } public void setS(String s) { this.s = s; } } 

* 效用 *

 package tst.ser; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.URLEncoder; public class SerUtl { public static String serialize(Object o) { String s = null; ObjectOutputStream os = null; try { os = new ObjectOutputStream(new ByteArrayOutputStream()); os.writeObject(o); s = BAse64.encode(os.toByeArray()); //s = URLEncoder.encode(s, "UTF-8");//keep this for sending part } catch (Exception e) { // TODO: logger e.printStackTrace(); return null; } finally { // close OS but is in RAM try { os.close();// not required in RAM } catch (Exception e2) {// TODO: handle exception logger } os = null; } return s; } public static Object deserialize(String s) { Object o = null; ObjectInputStream is = null; try { // do base 64 decode if done in serialize is = new ObjectInputStream(new ByteArrayInputStream( Base64.decode(s))); o = is.readObject(); } catch (Exception e) { // TODO: logger e.printStackTrace(); return null; } finally { // close OS but is in RAM try { is.close();// not required in RAM } catch (Exception e2) {// TODO: handle exception logger } is = null; } return o; } } 

****样本发送servlet ***

  Bean1 b = new Bean1(); b.setS("asdd"); String s = SerUtl.serialize(b); //do UrlEncode.encode here if sending lib does not. HttpParam p = new HttpParam ("bean1", s); //http components send obj 

****样品接收servlet ***

  String s = request.getParameter("bean1"); Bean1 b1 = (Beean1)SerUtl.deserialize(s); 

您无需转换为字符串。 您可以将二进制数据直接发布到servlet,例如通过在HttpUrlConnection的输出流之上创建ObjectOutputStream。 将请求方法设置为POST。

处理post的servlet可以从HttpServletRequest的ServletInputStream创建的ObjectStream中反序列化 。

不过,我建议JAXB随时使用二进制序列化。 这些框架不仅非常适合互操作性,还可加快开发速度并创建更强大的解决方案。

我看到的优点是更好的工具,类型安全和代码生成,保持您的选项打开,以便您可以从其他版本或其他语言调用您的代码,并更容易调试。 不要低估难以解决因意外地将错误类型或双重转义数据发送到servlet而导致的错误的成本。 我希望性能优势太小,无法弥补这一点。

将任何Serializable对象序列化为字节数组

是。

并制作一个字符串。

没有。

确切的陈述见下文

 os = new ObjectOutputStream(new ByteArrayOutputStream()); os.writeObject(o); s = os.toString(); // s = Base64.encode(s);//Need this some base 64 impl like Apache ? s = URLEncoder.encode(s, "UTF-8"); 

这些陈述甚至没有做你所描述的,在任何情况下都是不正确的。 OutputStream.toString()不会将任何字节转换为字符串,它只返回唯一的对象标识符。

Base64输出为1。

base64输出应该使用字节数组作为输入,而不是String。 String不是二进制数据的容器。 请参阅下面的更正代码。

 ByteArrayOutputStream baos = new ByteArrayOutputStream(); os = new ObjectOutputStream(baos); os.writeObject(o); os.close(); s = Base64.encode(baos.toByeArray()); // adjust to suit your API s = URLEncoder.encode(s, "UTF-8"); 

这至少可以实现你的目标。

它需要基于64还是可以跳过第2步?

如果你想要一个String,你必须以某种方式编码它。

使用java.util.URLEncode.encode对字符串进行编码

只有在将其作为GET或POST参数发送时才需要这样做。

命名参数后,使用apache http组件或URL类从servlet 1发送到2

是。

在Servlet 2上,J2EE框架已经对URL进行了解码,现在只需执行反向步骤并根据参数名称转换为对象。

是的,但记得直接从base64编码的字符串转到字节数组,没有中间字符串。

基本上寻找在JVM之间发送对象的最快和最方便的方法。

这些目标不一定是可以协调的。 这些天最方便的可能是XML或JSON,但我怀疑它们比序列化更快。

os = null;

将即将超出范围的引用设置为null是没有意义的。

HttpParam p = new HttpParam(“bean1”,s);

HttpParam有可能为你做URLEncoding。 检查一下。

发现这个Base64 impl对我来说很重要: http : //iharder.net/base64

有实用方法:

  String encodeObject(java.io.Serializable serializableObject, int options ) Object decodeToObject(String encodedObject, int options, final ClassLoader loader ) 

使用:

 try { String dat = Base64.encodeObject(srlzblObj, options); StringBuilder data = new StringBuilder().append("type="); data.append(appObjTyp).append("&obj=").append(java.net.URLEncoder.encode(dat, "UTF-8")); 

使用类型参数告诉接收JVM我正在发送什么类型的对象。 每个servlet / jsps最多接收4种类型,通常是1.再次,因为我们自己的应用程序和类我们发送它很快(如通过网络发送)和简单。

在另一端打开它:

  String objData = request.getParameter("obj"); Object obj = Base64.decodeToObject(objData, options, null); 

处理它,编码结果,发回结果:

  reply = Base64.encodeObject(result, options); out.print("rsp=" + reply); 

调用servlet / jsp得到结果:

  if (reply != null && reply.length() > 4) { String objDataFromServletParam = reply.substring(4); Object obj = Base64.decodeToObject(objDataFromServletParam, options, null); 

选项可以是0或Base64.GZIP

您也可以使用JMS。 Apache Active-MQ是一个很好的解决方案。 您不必为所有这些转换而烦恼。

  /** * @param objectToQueue * @throws JMSException */ public void sendMessage(Serializable objectToQueue) throws JMSException { ObjectMessage message = session.createObjectMessage(); message.setObject(objectToQueue); producerForQueue.send(message); } /** * @param objectToQueue * @throws JMSException */ public Serializable receiveMessage() throws JMSException { Message message = consumerForQueue.receive(timeout); if (message instanceof ObjectMessage) { ObjectMessage objMsg = (ObjectMessage) message; Serializable sobject = objMsg.getObject(); return sobject; } return null; } 

我的观点是do not write custom code for Serialization, iff it can be avoided

当您使用AMQ时,您需要做的就是使您的POJO可序列化。 Active-MQfunction负责序列化。

如果您想从AMQ快速响应,请使用vm-transport 。 它将最小化n / w开销。 您将自动获得AMQfunction的好处。

我建议这是因为

  • 您在网络上运行自己的应用程序。
  • 您需要一种机制来传输对象。
  • 您还需要一种方法来监控它。

如果您选择自定义解决方案,您可能必须自己解决上述问题。