передайте объект другому JVM с помощью сериализации-той же версии Java и jars (оба работают с нашим приложением)
обновления: Пока что с помощью карты. Класс, который хочет отправить что-то другому экземпляру, отправляет объект, строку маршрутизации.
используйте поток объектов, используйте Java serializable для записи объекта в сервлет.
Сначала напишите строку, а затем объект.
получение сервлета обертывает входной поток вокруг ObjectInputStream. Читает первую строку и объект. Строка маршрутизации решает, что она идет.
более общий способ мог бы быть чтобы отправить имя класса и его объявленный метод или имя Spring bean, но этого было достаточно для нас.
исходный вопрос
знать основной способ, но хотите детали шагов. Также знайте, что я могу использовать Jaxb или RMI или EJB ... но хотел бы сделать это, используя чистую сериализацию в bytearray, а затем кодировать, который отправляет его из сервлета 1 в jvm 1 в сервлет 2 в jvm 2 (два экземпляра сервера приложений в той же локальной сети, те же версии java и банки, настроенные в обоих J2EE приложения)
основные шаги (Approcah 1): -
сериализуйте любой сериализуемый объект в массив байтов и создайте строку. Точный код см. ниже
выход в base64 на 1. Требуется ли база 64 или можно пропустить Шаг 2?
используйте java.утиль.Функция urlencode.encode для кодирования строки
используйте http-компоненты apache или класс URL для отправки из сервлета 1 в 2 после именования params
на сервлете 2 J2EE framework уже URLDecoced его, теперь просто сделайте обратные шаги и приведите к объекту в соответствии с именем param. Поскольку оба наши приложения, мы будем знать имя param для отображения типа / класса. В основном ищет самый быстрый и удобный способ отправки объектов между JVMs.
пример : 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;
}
}
* Utility*
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;
}
}
**** образец отправки сервлета ***
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);
4 ответов
вам не нужно преобразовать в строку. Вы можете опубликовать двоичные данные прямо в сервлет, например, создав ObjectOutputStream поверх HttpUrlConnectionС клиенту OutputStream. Задайте метод запроса для POST.
сервлет, обрабатывающий сообщение, может десериализоваться из ObjectStream, созданного из ServletInputStream.
Я бы рекомендовал JAXB в любое время по бинарной сериализации. Рамки не являются только отлично подходит для взаимодействия, они также ускоряют разработку и создают более надежные решения.
преимущества, которые я вижу, - это лучший инструмент, безопасность типов и генерация кода, сохраняя ваши параметры открытыми, чтобы вы могли вызвать свой код из другой версии или другого языка и упростить отладку. Не стоит недооценивать стоимость трудных для решения ошибок, вызванных случайной отправкой неправильного типа или дважды экранированных данных сервлету. Я ожидал бы, что преимущества производительности будут слишком малы чтобы компенсировать это.
сериализовать любой сериализуемый объект с массивом байтов
да.
и сделать строку.
нет.
точные утверждения см. ниже
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 должен использовать массив байтов в качестве входных данных, а не строку. Строка не является контейнером для двоичных данных. Исправленный код см. ниже.
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.утиль.Функция urlencode.кодирование для кодирования строка
это необходимо, только если вы отправляете его как параметр GET или POST.
используйте http-компоненты apache или класс URL для отправки из сервлета 1 в 2 после именования params
да.
на сервлете 2 J2EE framework уже URLDecoded его, теперь просто сделайте обратные шаги и приведите к объекту в соответствии с именем param.
да, но не забудьте перейти непосредственно из base64-encoded строка в массив байтов, без промежуточной строки.
в основном ищет самый быстрый и удобный способ отправки объектов между JVMs.
эти цели не всегда совместимы. Наиболее удобным в эти дни, вероятно, является XML или JSON, но я сомневаюсь, что они быстрее сериализации.
os = null;
установка ссылок, которые вот-вот выпадут из области null
is бессмысленный.
HttpParam p = новый 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"));
используйте тип param, чтобы сообщить получающему JVM, какой тип объекта я отправляю. Каждый сервлет / 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-MQ заботятся о сериализации.
Если вы хотите быстрый ответ от AMQ, используйте vm-transport
. Это минимизирует накладные расходы n/w.
Вы автоматически получите преимущества функций AMQ.
Я предполагая это, потому что
- у вас есть свои собственные приложения, работающие в сети.
- вам нужен механизм для передачи объектов.
- вам понадобится способ контролировать его, а также.
Если вы идете на собственное решение, возможно, придется решать все самим.