更新: 现在使用地图。想要向其他实例发送内容的类发送对象即路由字符串。
使用对象流,使用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): -
将任何Serializable对象序列化为字节数组并生成一个字符串。确切的代码见下文
Base64输出1.是否需要基于64或可以跳过第2步?
使用java.util.URLEncode.encode对字符串进行编码
在命名参数后使用apache http组件或URL类从servlet 1发送到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);
答案 0 :(得分:7)
将任何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步?
如果你想要一个字符串,你必须以某种方式对其进行编码。
使用java.util.URLEncode.encode对字符串
进行编码
仅当您将其作为GET或POST参数发送时,才需要这样做。
在命名params后,使用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。检查一下。
答案 1 :(得分:3)
您无需转换为字符串。您可以将二进制数据直接发布到servlet,例如通过在HttpUrlConnection的输出流之上创建ObjectOutputStream。将请求方法设置为POST。
处理post的servlet可以从HttpServletRequest的ServletInputStream创建的ObjectStream中反序列化。
不过,我建议JAXB随时使用二进制序列化。这些框架不仅非常适合互操作性,还可加快开发速度并创建更强大的解决方案。
我看到的优点是更好的工具,类型安全和代码生成,保持您的选项打开,以便您可以从其他版本或其他语言调用您的代码,并更容易调试。不要低估难以解决因意外地将错误类型或双重转义数据发送到servlet而导致的错误的成本。我希望性能优势太小,无法弥补这一点。
答案 2 :(得分:2)
发现这个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
答案 3 :(得分:1)
您也可以使用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-MQ功能负责序列化。
如果您想从AMQ快速响应,请使用vm-transport
。它将最小化n / w开销。
您将自动获得AMQ功能的好处。
我建议这是因为
如果你选择自定义解决方案,你可能需要自己解决上述问题。