使用序列化将对象传递给另一个JVM-相同的Java版本和JAR(都运行我们的应用程序)
更新: 现在使用地图。希望向其他实例发送内容的类发送对象,即路由字符串 使用对象流,使用Java serializable将对象写入servlet 首先写入字符串,然后写入对象 接收servlet围绕ObjectInputStream包装输入流。首先读取字符串,然后读取对象。路由字符串决定它是否运行 更通用的方法可能是发送类名及其声明的方法或Springbean名称,但这对我们来说已经足够了使用序列化将对象传递给另一个JVM-相同的Java版本和JAR(都运行我们的应用程序),java,http,jakarta-ee,serialization,Java,Http,Jakarta Ee,Serialization,更新: 现在使用地图。希望向其他实例发送内容的类发送对象,即路由字符串 使用对象流,使用Java serializable将对象写入servlet 首先写入字符串,然后写入对象 接收servlet围绕ObjectInputStream包装输入流。首先读取字符串,然后读取对象。路由字符串决定它是否运行 更通用的方法可能是发送类名及其声明的方法或Springbean名称,但这对我们来说已经足够了 原始问题 了解基本方法,但需要步骤的详细信息。还知道我可以使用Jaxb、RMI或EJB。。。但是我想使
原始问题 了解基本方法,但需要步骤的详细信息。还知道我可以使用Jaxb、RMI或EJB。。。但是我想使用对字节数组的纯序列化来实现这一点,然后进行编码,将其从jvm 1中的servlet 1发送到jvm 2中的servlet 2(同一LAN中的两个应用程序服务器实例,两个J2EE应用程序中设置的java版本和JAR相同) 基本步骤为(近似1):-
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。我在没有测试的情况下生成了示例代码