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

使用序列化将对象传递给另一个JVM-相同的Java版本和JAR(都运行我们的应用程序),java,http,jakarta-ee,serialization,Java,Http,Jakarta Ee,Serialization,更新: 现在使用地图。希望向其他实例发送内容的类发送对象,即路由字符串 使用对象流,使用Java serializable将对象写入servlet 首先写入字符串,然后写入对象 接收servlet围绕ObjectInputStream包装输入流。首先读取字符串,然后读取对象。路由字符串决定它是否运行 更通用的方法可能是发送类名及其声明的方法或Springbean名称,但这对我们来说已经足够了 原始问题 了解基本方法,但需要步骤的详细信息。还知道我可以使用Jaxb、RMI或EJB。。。但是我想使

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

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

首先写入字符串,然后写入对象

接收servlet围绕ObjectInputStream包装输入流。首先读取字符串,然后读取对象。路由字符串决定它是否运行

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


原始问题

了解基本方法,但需要步骤的详细信息。还知道我可以使用Jaxb、RMI或EJB。。。但是我想使用对字节数组的纯序列化来实现这一点,然后进行编码,将其从jvm 1中的servlet 1发送到jvm 2中的servlet 2(同一LAN中的两个应用程序服务器实例,两个J2EE应用程序中设置的java版本和JAR相同)

基本步骤为(近似1):-

  • 将任何可序列化对象序列化为字节数组并生成字符串。具体代码见下文

  • Base64 1的输出。是需要以64为基数还是可以跳过步骤2

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

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

  • 在Servlet 2上,J2EE框架可能已经对其进行了URLDescocked,现在只需执行相反的步骤,并根据参数名称将其转换为对象。 因为这两个都是我们的应用程序,所以我们知道类型/类映射的参数名。基本上是寻找在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
    
        String s = request.getParameter("bean1");
        Bean1 b1 = (Beean1)SerUtl.deserialize(s);
    
    ****示例接收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
    
        String s = request.getParameter("bean1");
        Bean1 b1 = (Beean1)SerUtl.deserialize(s);
    
    将任何可序列化对象序列化为字节数组

    然后做一根绳子

    没有

    具体说明见下文

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

    Base64 1的输出

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

    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

    如果你想要一个字符串,你必须以某种方式对它进行编码

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

    仅当您将其作为GET或POST参数发送时,才需要此选项

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

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


    是的,但请记住直接从base64编码字符串转到字节数组,而不是中间字符串

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

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

    os=null

    将即将超出范围的引用设置为
    null
    是毫无意义的

    HttpParam p=新的HttpParam(“bean1”,s)

    HttpParam
    可能为您执行URL编码。检查此项。

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

      /**
     * @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;
    }
    
    我的观点是,如果可以避免的话,不要为序列化编写自定义代码

    当您使用AMQ时,您所需要做的就是使POJO可序列化。 活动MQ函数负责序列化

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

    我建议这样做是因为

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

    若您选择自定义解决方案,您可能需要自己解决上述问题。

    发现这个Base64 impl为我带来了很多麻烦:

    具有实用方法:

     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"));
    
    使用type参数告诉接收JVM我正在发送什么类型的对象。每个servlet/JSP最多接收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,您不需要转换为字符串。您可以直接将二进制数据发布到servlet,例如,通过在a的outputstream上创建ObjectOutputStream。将请求方法设置为POST

    处理post的servlet可以从HttpServletRequest创建的ObjectStream进行反序列化

    不过,我建议您随时使用JAXB而不是二进制序列化。这些框架不仅具有很好的互操作性,还可以加速开发并创建更健壮的解决方案


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

    所有bean及其成员都实现SerializableThank。我在没有测试的情况下生成了示例代码