передайте объект другому JVM с помощью сериализации-той же версии Java и jars (оба работают с нашим приложением)

обновления: Пока что с помощью карты. Класс, который хочет отправить что-то другому экземпляру, отправляет объект, строку маршрутизации.

используйте поток объектов, используйте Java serializable для записи объекта в сервлет.

Сначала напишите строку, а затем объект.

получение сервлета обертывает входной поток вокруг ObjectInputStream. Читает первую строку и объект. Строка маршрутизации решает, что она идет.

более общий способ мог бы быть чтобы отправить имя класса и его объявленный метод или имя Spring bean, но этого было достаточно для нас.


исходный вопрос

знать основной способ, но хотите детали шагов. Также знайте, что я могу использовать Jaxb или RMI или EJB ... но хотел бы сделать это, используя чистую сериализацию в bytearray, а затем кодировать, который отправляет его из сервлета 1 в jvm 1 в сервлет 2 в jvm 2 (два экземпляра сервера приложений в той же локальной сети, те же версии java и банки, настроенные в обоих J2EE приложения)

основные шаги (Approcah 1): -

  1. сериализуйте любой сериализуемый объект в массив байтов и создайте строку. Точный код см. ниже

  2. выход в base64 на 1. Требуется ли база 64 или можно пропустить Шаг 2?

  3. используйте java.утиль.Функция urlencode.encode для кодирования строки

  4. используйте http-компоненты apache или класс URL для отправки из сервлета 1 в 2 после именования params

  5. на сервлете 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.

Я предполагая это, потому что

  • у вас есть свои собственные приложения, работающие в сети.
  • вам нужен механизм для передачи объектов.
  • вам понадобится способ контролировать его, а также.

Если вы идете на собственное решение, возможно, придется решать все самим.