Java Servlet 中静态变量的使用(例如在 AppEngine 中)
我有一个应用程序,其中 Servlet 有一个名为 Update(ReqIn, ReqOut)
的方法。我从 doGet
& 调用它doPost
并传递 Request 和 Response 变量,然后由 Update(...)
填写以下静态变量:
...
public class Server extends HttpServlet {
public static HttpServletRequest In = null;
public static HttpServletResponse Out = null;
public static boolean isDebug = true;
public static boolean isPost = false;
public static String URL = "";
public static String IP = "0.0.0.0";
public static Cookie[] Cookies = null;
public static UserClass User = null;
public static boolean isLoggedIn = false;
...
}
基本上抽象最常用的东西和内容。根据每个请求更新它。这也允许我访问 IP 地址和网站中任何位置的当前用户数据,只需编写 Server.User.getUsername();
而不是每次加载页面时创建一个新的 Class 实例并使用更长的访问代码:Server .getUser().getUsername();
现在的问题是:在多用户环境(AppEngine 上的 Jetty)中,这会带来任何问题吗?例如,一些线程/竞赛问题导致用户看到不正确的 IP 地址,或者在极端情况下突然以不同用户身份登录?
或者我应该重写代码并将其更改为 Public UserClass User
而不是 Public static UserClass User
等?
I have an application where Servlet has a method called Update(ReqIn, ReqOut)
. I call it from doGet
& doPost
and pass the Request and Response variables, and it is then up to Update(...)
to fill out the following static variables:
...
public class Server extends HttpServlet {
public static HttpServletRequest In = null;
public static HttpServletResponse Out = null;
public static boolean isDebug = true;
public static boolean isPost = false;
public static String URL = "";
public static String IP = "0.0.0.0";
public static Cookie[] Cookies = null;
public static UserClass User = null;
public static boolean isLoggedIn = false;
...
}
Basically Abstracting most used stuff & updating it on every request. This also allows me to access IP address & current user data from anywhere in the website, by writting just Server.User.getUsername();
insead of making a new Class instance everytime a page is loaded and using much longer access code: Server.getUser().getUsername();
Now the question is: When in multi user environment (Jetty on AppEngine), can this introduce any problems? E.g. some threading/racing issues making user see incorrect IP address or in extreme case suddenly being logged in as different user?
Or should I rewrite code and change it to Public UserClass User
instead of Public static UserClass User
, etc?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用静态是一个非常糟糕的主意,因为如果您同时收到两个请求,那么它们将互相覆盖。通过这个简单的例子来看看可能会出现什么问题:
现在想象一下以下时间线:
请求 1 进入,并处理到第 5 行(包括第 5 行)。
请求 2 进入并完成处理。
请求 1 继续处理。
两个请求都将获得文本“2”,而不是一个获得“1”,一个获得“2”。这是国家被践踏的一个简单例子。
现在,回答你问题的第二部分;
不,这还不够好,因为 J2EE 规范允许 servlet 容器使用类的一个实例来服务该 servlet 映射的所有请求,也就是说,实例级变量将具有与静态数据,它们在所有请求之间共享。
这只剩下三个真正的选择:
Using statics is a hugely bad idea, since if you get two requests come in at the same time then they will write over each other. Take this trivial example to see what can go wrong:
Now imagine the following timeline:
Request 1 comes in, and processes up to, and including, line 5.
Request 2 comes in, and processes completely.
Request 1 continues processing.
Both requests will get the text "2", instead of one getting "1" and one getting "2". This is a simple example of the state being stomped on.
Now, to answer the second part of your question;
No, that is also not good enough, since the J2EE spec allows the servlet container to use one instance of a class to service all of the requests for that servlet mapping, that is, the instance level variables will have exactly the same effect as being statics, they are shared between all requests.
This leaves only three real options:
是的,这是一个非常糟糕的主意!
如果您同时收到两个请求,您期望会发生什么?每个静态变量只能保存一个值,因此您将丢失数据。
您可以使用
ThreadLocal
这样每个线程只能访问它正在处理的当前请求/用户/等 - 但这基本上仍然是一个坏主意。它很脆弱,并且隐藏了较低层需要信息的事实。将状态传递给需要它的代码。Yes, this is a hugely bad idea!
What would you expect to happen if you got two requests at the same time? Each static variable can only hold one value, so you're going to lose data.
You could use
ThreadLocal
so that each thread only had access to the current request/user/etc that it was dealing with - but that's still basically a bad idea. It's brittle, and hides the fact that lower layers need the information. Pass the state down to the code that needs it instead.