如何保证只创建一个XMPPConnection?使用单例?

发布于 2024-12-07 04:34:17 字数 1132 浏览 1 评论 0原文

我正在创建一个 Web 服务,它将接收通过 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 创建一个包装类,接受不带参数的构造函数?

I'm dealing with creating a web service which will receive requests to send messages via XMPP. However, all messages will be sent from one account (the server logs in and sends notifications to users).

Here comes the problem - how to implement it? I was trying to implement the XMPPConnection class as a singleton, but I got stuck at passing arguments to constructors containing the hostname, port, JID etc

As I've read here, a singleton with parameters is not a singleton... Hence, I thought about solving it as follows (is it some kind of factory?):

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.
    }
}

Is it a good way to go? Or maybe it is better to make a wrapping class for XMPPConnection, accepting a constructor with no parameters?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的鱼塘能养鲲 2024-12-14 04:34:17

您可以使用 ~singleton,阅读此 问题 和相关页面此处此处。最干净的方法是在静态块中初始化,但这显然并不总是可能的。

最明显、简单的方法是在单个实例上进行同步,并且所有 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 客户端类本身。

然后只需在返回的对象上使用同步运算符即可。

You can use a ~singleton, read this question and the related pages here and here. The cleanest is to initialize in a static block, but that is obiously not always possible.

The obious, simple, approach is to synchronize on a single instance and all WS calls wait. This will work great for low capacity. Using ReentrantLock might enhance that logic somewhat - for example sending a timeout WS reponse rather than having the whole HTTP call out.

If you need many concurrent sessions, consider checking out whether the server can log in with multiple clients and then initialize as many clients as you want - then use the ReentrantLock in some way to determine which is currently free.

Depending on the logic in your WS calls (does it need confirmation that message is sent to XMPP?) you might consider queueing up the calls and serving them from another thread, returning the WS call before the actual message is sent (http hold time is normally 30 second, but can be changed).

Might even be possible to let each WS session connect and have its own session for the duration of the call.

Edit:I suggest you go with

// 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;
    }
}

where Helper is

  1. a helper class which pull the login info from somewhere, wraps the XMPP client class, or
  2. the XMPP client class itself with hardcoded login info.

Then simply use synchronized operator on the returned object.

叹沉浮 2024-12-14 04:34:17

在我看来,这完全是错误的做法。为什么不简单地将 WS 请求放入队列中,并让单个线程通过 xmpp 读取请求并写入消息。只会有一个连接,但根本不需要创建任何自定义代码来创建单例连接。

It sounds to me like the wrong approach altogether. Why not simply have the WS requests put in a queue and have a single thread read the requests and write the messages via xmpp. There would only be a single connection, but there is no need to create any custom code to create a singleton connection at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文