在 Qt 应用程序中共享 cookie 的最佳方式
Best way to share cookies within Qt application
我可以使用 QNetworkCookieJar
检索、存储和重新发送 QNetworkManager
的 cookie。多个 QNetworkAccessManager
个实例可以共享一个 QNetworkCookieJar
.
到目前为止,我已经使用了多个 QNetworkAccessManager
个实例,每个 class 个实例(我需要阅读的地方):
- 所以我可以在 1..n
QNetworkAccessManager
个实例之间共享一个单例 QNetworkCookieJar
- 或者只有一个单例
QNetworkAccessManager
和一个 Jar 在所有 QNetworkRequest
之间共享是否更好。 QNetworkAccessManager
作为单个对象是可行的方法吗?文档说应该只有一个实例。那么我最好使用单例 QNetworkAccessManager
?
最合适的方式是什么?
------ 编辑 ------
据我所知, 是正确的。这也是文档所说的。但是,在尝试这种方法时,我注意到了两个问题:
- 虽然我们现在每个 Web 服务有一个
QNetworkAccessManager
,但更改为一个实例意味着我需要始终区分我刚刚在“完成”槽中收到的内容类型(从 QNetworkAccessManager::finished
).可行,但不方便。
- 我们 运行 我们的读者在不同的线程中 - 不幸的是我忘了在问题中提到这一点。这使得几乎不可能使用
QNetworkAccessManager
的单个实例,因为成员函数是 reentrant, but not thread safe. ( QNetworkAccessManager from ThreadPool )
相关:
我假设您指的是 QNetworkAccessManager
,而不是 QNetworkManager
。
您应该更喜欢在您的应用程序中使用一个 QNetworkAccessManager
。这不仅消除了同步 QNetworkCookieJar
的任何需要,而且确保网络得到最佳利用,并且缓存内容等得到共享。
正如您自己注意到的,QtNetworkAccessManager 中也暗示了这一点 documentation:
One QNetworkAccessManager should be enough for the whole Qt
application.
这是我所做的(并且似乎有效):
- 当我们在线程中阅读时,我无法使用单个
QNetworkAccessManager
。
- 共享
QNetworkCookieJar
不是一个选项,因为它不是线程安全的
但是创建我自己的微型线程安全 - 源自 QNetworkCookieJar
- class 很容易。我只需要担心 5 个虚函数。我可以在 QNetworkAccessManager
之间共享这个线程安全的 cookie 罐。
我 运行 这里有一定的风险,因为 QObject
的其他 public 成员函数不是线程安全的,可能会崩溃,但这些似乎并没有在那个用途中被利用案例.
请求的示例代码:
/*!
* Cookie manager, which allows thread safe sharing of cookies
*/
class BLACKCORE_EXPORT CCookieManager : public QNetworkCookieJar
{
Q_OBJECT
public:
//! Constructor, only allowed from BlackCore::CApplication
CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent = nullptr);
//! \copydoc QNetworkCookieJar::setCookiesFromUrl
//! \threadsafe
virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url) override;
//! \copydoc QNetworkCookieJar::cookiesForUrl
//! \threadsafe
virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override;
//! Cookies for request
//! \threadsafe
QList<QNetworkCookie> cookiesForRequest(const QNetworkRequest &request) const;
//! \copydoc QNetworkCookieJar::deleteCookie
//! \threadsafe
virtual bool deleteCookie(const QNetworkCookie &cookie) override;
//! Delete all cookies
//! \threadsafe
void deleteAllCookies();
//! \copydoc QNetworkCookieJar::insertCookie
//! \threadsafe
virtual bool insertCookie(const QNetworkCookie &cookie) override;
//! \copydoc QNetworkCookieJar::updateCookie
//! \threadsafe
virtual bool updateCookie(const QNetworkCookie &cookie) override;
private:
mutable QReadWriteLock m_lock { QReadWriteLock::Recursive };
};
CCookieManager::CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent) : QNetworkCookieJar(parent)
{
// code
}
bool CCookieManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
}
QList<QNetworkCookie> CCookieManager::cookiesForUrl(const QUrl &url) const
{
QReadLocker l(&m_lock);
const QList<QNetworkCookie> cookies(QNetworkCookieJar::cookiesForUrl(url));
return cookies;
}
QList<QNetworkCookie> CCookieManager::cookiesForRequest(const QNetworkRequest &request) const
{
return cookiesForUrl(request.url());
}
bool CCookieManager::deleteCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::deleteCookie(cookie);
}
bool CCookieManager::insertCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::insertCookie(cookie);
}
bool CCookieManager::updateCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::updateCookie(cookie);
}
void CCookieManager::deleteAllCookies()
{
QWriteLocker l(&m_lock);
this->setAllCookies(QList<QNetworkCookie>());
}
我可以使用 QNetworkCookieJar
检索、存储和重新发送 QNetworkManager
的 cookie。多个 QNetworkAccessManager
个实例可以共享一个 QNetworkCookieJar
.
到目前为止,我已经使用了多个 QNetworkAccessManager
个实例,每个 class 个实例(我需要阅读的地方):
- 所以我可以在 1..n
QNetworkAccessManager
个实例之间共享一个单例QNetworkCookieJar
- 或者只有一个单例
QNetworkAccessManager
和一个 Jar 在所有QNetworkRequest
之间共享是否更好。QNetworkAccessManager
作为单个对象是可行的方法吗?文档说应该只有一个实例。那么我最好使用单例QNetworkAccessManager
?
最合适的方式是什么?
------ 编辑 ------
据我所知,- 虽然我们现在每个 Web 服务有一个
QNetworkAccessManager
,但更改为一个实例意味着我需要始终区分我刚刚在“完成”槽中收到的内容类型(从QNetworkAccessManager::finished
).可行,但不方便。 - 我们 运行 我们的读者在不同的线程中 - 不幸的是我忘了在问题中提到这一点。这使得几乎不可能使用
QNetworkAccessManager
的单个实例,因为成员函数是 reentrant, but not thread safe. ( QNetworkAccessManager from ThreadPool )
相关:
我假设您指的是 QNetworkAccessManager
,而不是 QNetworkManager
。
您应该更喜欢在您的应用程序中使用一个 QNetworkAccessManager
。这不仅消除了同步 QNetworkCookieJar
的任何需要,而且确保网络得到最佳利用,并且缓存内容等得到共享。
正如您自己注意到的,QtNetworkAccessManager 中也暗示了这一点 documentation:
One QNetworkAccessManager should be enough for the whole Qt application.
这是我所做的(并且似乎有效):
- 当我们在线程中阅读时,我无法使用单个
QNetworkAccessManager
。 - 共享
QNetworkCookieJar
不是一个选项,因为它不是线程安全的
但是创建我自己的微型线程安全 - 源自 QNetworkCookieJar
- class 很容易。我只需要担心 5 个虚函数。我可以在 QNetworkAccessManager
之间共享这个线程安全的 cookie 罐。
我 运行 这里有一定的风险,因为 QObject
的其他 public 成员函数不是线程安全的,可能会崩溃,但这些似乎并没有在那个用途中被利用案例.
请求的示例代码:
/*!
* Cookie manager, which allows thread safe sharing of cookies
*/
class BLACKCORE_EXPORT CCookieManager : public QNetworkCookieJar
{
Q_OBJECT
public:
//! Constructor, only allowed from BlackCore::CApplication
CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent = nullptr);
//! \copydoc QNetworkCookieJar::setCookiesFromUrl
//! \threadsafe
virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url) override;
//! \copydoc QNetworkCookieJar::cookiesForUrl
//! \threadsafe
virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override;
//! Cookies for request
//! \threadsafe
QList<QNetworkCookie> cookiesForRequest(const QNetworkRequest &request) const;
//! \copydoc QNetworkCookieJar::deleteCookie
//! \threadsafe
virtual bool deleteCookie(const QNetworkCookie &cookie) override;
//! Delete all cookies
//! \threadsafe
void deleteAllCookies();
//! \copydoc QNetworkCookieJar::insertCookie
//! \threadsafe
virtual bool insertCookie(const QNetworkCookie &cookie) override;
//! \copydoc QNetworkCookieJar::updateCookie
//! \threadsafe
virtual bool updateCookie(const QNetworkCookie &cookie) override;
private:
mutable QReadWriteLock m_lock { QReadWriteLock::Recursive };
};
CCookieManager::CCookieManager(BlackMisc::Restricted<CApplication>, QObject *parent) : QNetworkCookieJar(parent)
{
// code
}
bool CCookieManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookies, const QUrl &url)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
}
QList<QNetworkCookie> CCookieManager::cookiesForUrl(const QUrl &url) const
{
QReadLocker l(&m_lock);
const QList<QNetworkCookie> cookies(QNetworkCookieJar::cookiesForUrl(url));
return cookies;
}
QList<QNetworkCookie> CCookieManager::cookiesForRequest(const QNetworkRequest &request) const
{
return cookiesForUrl(request.url());
}
bool CCookieManager::deleteCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::deleteCookie(cookie);
}
bool CCookieManager::insertCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::insertCookie(cookie);
}
bool CCookieManager::updateCookie(const QNetworkCookie &cookie)
{
QWriteLocker l(&m_lock);
return QNetworkCookieJar::updateCookie(cookie);
}
void CCookieManager::deleteAllCookies()
{
QWriteLocker l(&m_lock);
this->setAllCookies(QList<QNetworkCookie>());
}