Как обеспечить создание только одного XMPPConnection? Использовать синглтоны? - PullRequest
1 голос
/ 28 сентября 2011

Я занимаюсь созданием веб-сервиса, который будет получать запросы на отправку сообщений через XMPP. Однако все сообщения будут отправляться с одной учетной записи (сервер входит в систему и отправляет уведомления пользователям).

Здесь возникает проблема - как это реализовать? Я пытался реализовать класс XMPPConnection как одиночный, но я застрял при передаче аргументов конструкторам, содержащим имя хоста, порт, JID и т. Д.

Как я прочитал здесь , синглтон с параметрами не является синглтоном ... Следовательно, я подумал о его решении следующим образом (это какая-то фабрика? ):

public class XMPPConnectionSingleton
{
    private volatile static XMPPConnectionSingleton anInstance;
    private volatile static XMPPConnection connection;

    public static XMPPConnectionSingleton getInstance() {
        if(anInstance == null) {
            synchronized (XMPPConnectionSingleton.class) {
                if(anInstance == null)
                    anInstance = new XMPPConnectionSingleton();
            }
        }
        return anInstance;
    }

    public void init(String server, int port, String jid, String password, String resource)
    {
        ConnectionConfiguration conf = new ConnectionConfiguration(server, port);
        connection = new XMPPConnection(conf);
        // logging in, etc.
    }
}

Это хороший путь? Или, может быть, лучше создать класс-оболочку для XMPPConnection, принимая конструктор без параметров?

Ответы [ 2 ]

0 голосов
/ 29 сентября 2011

Для меня это звучит как неправильный подход.Почему бы просто не поместить запросы WS в очередь, и один поток не может прочитать запросы и записать сообщения через xmpp.Будет только одно соединение, но нет необходимости создавать какой-либо специальный код для создания одноэлементного соединения.

0 голосов
/ 29 сентября 2011

Вы можете использовать ~ синглтон, прочитайте этот вопрос и соответствующие страницы здесь и здесь .Самым чистым является инициализация в статическом блоке, но это не всегда возможно.

Простой и понятный подход заключается в синхронизации одного экземпляра и ожидании всех вызовов WS.Это отлично подойдет для малой мощности.Использование ReentrantLock может несколько улучшить эту логику - например, отправка тайм-аута WS-ответа, а не весь HTTP-вызов.

Если вам нужно много одновременных сеансов, рассмотрите возможность проверки того, может ли сервер войти в систему с несколькими клиентами, изатем инициализируйте столько клиентов, сколько хотите, - затем используйте ReentrantLock каким-либо образом, чтобы определить, какой из них в настоящее время свободен.

В зависимости от логики в ваших вызовах WS (требуется ли подтверждение того, что сообщение отправлено в XMPP?), Вы можете рассмотреть вопрос об организации очереди вызовов и их обслуживании из другого потока, возвращая вызов WS до того, как фактическое сообщение будетотправлено (время удержания http обычно составляет 30 секунд, но его можно изменить).

Возможно даже позволить каждому сеансу WS подключаться и иметь собственный сеанс на время вызова.

Редактировать: Я предлагаю вам пойти с

// Correct lazy initialization in Java 
@ThreadSafe
class Foo {
    private static class HelperHolder {
       public static Helper helper = new Helper();
    }

    public static Helper getHelper() {
        return HelperHolder.helper;
    }
}

, где Helper

  1. вспомогательный класс, который извлекает логининформация откуда-то, оборачивает клиентский класс XMPP или
  2. сам клиентский класс XMPP с жестко запрограммированной информацией для входа в систему.

Затем просто используйте синхронизированный оператор для возвращаемого объекта.

...