网站上的示例:
import vibe.d;
void login(HTTPServerRequest req, HTTPServerResponse res)
{
enforceHTTP("username" in req.form && "password" in req.form,
HTTPStatus.badRequest, "Missing username/password field.");
// todo: verify user/password here
auto session = res.startSession();
session["username"] = req.form["username"];
session["password"] = req.form["password"];
res.redirect("/home");
}
void logout(HTTPServerRequest req, HTTPServerResponse res)
{
res.terminateSession();
res.redirect("/");
}
void checkLogin(HTTPServerRequest req, HTTPServerResponse res)
{
// force a redirect to / for unauthenticated users
if( req.session is null )
res.redirect("/");
}
shared static this()
{
auto router = new URLRouter;
router.get("/", staticTemplate!"index.dl");
router.post("/login", &login);
router.post("/logout", &logout);
// restrict all following routes to authenticated users:
router.any("*", &checkLogin);
router.get("/home", staticTemplate!"home.dl");
auto settings = new HTTPServerSettings;
settings.sessionStore = new MemorySessionStore;
// ...
}
但是让我说我不想将整个程序中的ServerResponse传递给每个函数。例如,如果res.session存储当前用户的id,该怎么办?这经常使用,所以我不希望这通过每个函数。如何在全球范围内存储此会话信息?假设有多个用户使用该网站。
答案 0 :(得分:3)
虽然有点沮丧,但这是可能的。
<强>解决方案强>
您不能简单地将其全局存储,因为不存在“全局”会话 - 它始终特定于请求上下文。即使在D中默认使用全局线程本地也没有用,因为多个光纤共享相同的执行线程。
对于此类任务,vibe.d提供了TaskLocal模板,可以完全按照您的要求进行操作。我没有尝试过,但希望TaskLocal!Session session
“正常工作”。
请注意文档中的这两个警告:
但请注意,每个TaskLocal变量都会增加使用任务本地存储的任何任务的内存占用量。访问TaskLocal变量还有一个开销,高于线程局部变量,但通常仍然是O(1)
和
FiberLocal实例必须声明为静态/全局线程局部变量。将它们定义为临时/堆栈变量将导致崩溃或数据损坏!
<强>异议强>
然而,根据我的经验,尽管输入不便,但最好还是明确地传递所有这些背景。由于某种原因,不鼓励使用全局变量 - 随着程序大小的增加,难以跟踪模块之间的依赖关系并测试此类代码。现在可能会引起很多头痛,这可能会引起很多人的头痛。为了最大限度地减少额外的输入并简化代码维护,我建议改为定义struct Context { ...}
,它将包含请求/会话指针,并将定期传递。