这是我的servlet的代码。
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
Map m=request.getParameterMap();
Set s = m.entrySet();
Iterator it = s.iterator();
int index=0;
while (it.hasNext()) {
Map.Entry<String,String[]> entry = (Map.Entry<String,String[]>) it.next();
String key = entry.getKey();
String[] value = entry.getValue();
System.out.println("Value is " + value[0].toString());
switch(key) {
case "RegId":
RegId = value[0].toString();
break;
case "isTrackingRequested":
isTrackingRequested = Boolean.valueOf(value[0]);
break;
}
}
// Create a session object if it is already not created.
HttpSession session = request.getSession(true);
if (session.isNew()) {
session.setAttribute("id",isTrackingRequested);
}
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
boolean isTrackingRequestednew = (boolean) session.getAttribute("id");
// code to run
if (isTrackingRequestednew) {
try {
System.out.println("===========================================================================");
System.out.println("new track status is " + isTrackingRequestednew);
System.out.println("===========================================================================");
} catch (Exception e) {
}
} else {
ses.shutdown();
}
}
}, 0, 1, TimeUnit.SECONDS);
}
我正在尝试使用ScheduledExcecutorService
跟踪车辆。我使用标记isTrackingRequested
来检查用户是否已请求跟踪。所以我在会话中保存了值,但每当我请求跟踪停止时,先前设置的会话属性都会显示null
值。
简而言之,我正在尝试访问以前设置的会话变量,但我最终得到null
。我尝试过的解决方案似乎无法解决。
答案 0 :(得分:1)
每当我请求跟踪停止时,先前设置的会话属性显示空值。
一个合理可能的解释是请求不在同一个会话中。维持会话需要客户的合作,不保证给予。将请求与会话相关联的最常见机制是cookie和URL重写。如果客户拒绝cookie并且正在向静态URL发出请求,则每个请求都可能在其自己的会话中。
然而,这是你的问题中较小的一个。你也有这些:
在每个POST请求中,您创建一个新的ScheduledExecutorService
和一个要管理的新任务。当然,这不是你想要的。
已添加:您不会使用属于这些会话的请求所承载的跟踪状态更新现有会话。仅当为要处理的请求新创建会话时,才设置会话属性。
此外,当我上次研究JavaEE规范(一个版本之前)时,不允许JavaEE组件(如servlet)启动自己的线程,但是你的许多组件 - 其中很多 - 都在{{1 }}秒。这并不意味着启动新线程(或创建 ScheduledExecutorService
)必然会失败,但违反规范 意味着您不能依赖JavaEE API来表现记录在案。
此外,您的代码未正确同步。您在没有正确同步的情况下访问共享状态(ScheduledExecutorService
)。
此外,您似乎没有机制在会话过期或手动终止时关闭跟踪。
要正确执行此操作,应在servlet容器外部运行的单独服务中执行跟踪。或者,您可以将其与仅在容器外部运行的调度程序本身以及生活在内部的所有跟踪状态一起破解。然后,调度程序只需要通过向同一容器中的不同servlet发送定期请求来充当时钟。
您最好将任务与会话分离。不要让它从会话中获取跟踪状态,而是为其提供成员变量,并在会话中存储对任务本身的引用。直接修改任务的状态以响应请求,而不是通过会话间接传递该信息。并确保对该对象的共享状态的所有访问都正确同步!
补充:此外,我建议您创建任务实现Session
,以便当它从会话中解除绑定时 - 手动或由于会话达到其生命周期而结束 - 它可以自行取消。
已添加:此外,请注意,现代JavaEE要求容器为企业组件提供HttpSessionBindingListener
。您应该能够通过JNDI名称ScheduledExecutorService
获取对它的引用(参见the Java EE 7 platform specification中的EE.5.21节)。使用这个容器提供的服务而不是尝试设置自己的服务是明智的。
答案 1 :(得分:0)
您提供的代码中存在一些错误。每次都应检查isTrackingRequested
的值,因为请求者可以发送值false
来停止跟踪。此外,还应考虑null
isTrackingRequested
的值protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String RegId = String.valueOf(request.getParameter("RegId"));
// Create a session object if it is already not created.
final HttpSession session = request.getSession(true);
String trackingRequestParam = request.getParameter("isTrackingRequested");
boolean isTrackingRequested = false;
if(trackingRequestParam != null) {
isTrackingRequested = Boolean.valueOf(trackingRequestParam);
session.setAttribute("id", isTrackingRequested);
}
if(trackingRequestParam != null && isTrackingRequested) {
final ScheduledExecutorService ses = Executors
.newSingleThreadScheduledExecutor();
session.setAttribute("isRunning", true);
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
boolean isTrackingRequestednew = Boolean.valueOf(String.valueOf(session.getAttribute("id") ));
System.out.println("inside repeater : " + session.getAttribute("id") + " : " + isTrackingRequestednew);
// code to run
if (isTrackingRequestednew) {
try {
System.out.println("===========================================================================");
System.out.println("new track status is " + isTrackingRequestednew);
System.out.println("===========================================================================");
} catch (Exception e) {
}
} else {
ses.shutdown();
}
}
}, 0, 1, TimeUnit.SECONDS);
}
}
。如果它为null,则可能意味着用户希望继续执行先前的决定。
这些已在下面的代码中得到纠正,现在应该可以使用了。
package test;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
Boolean isLogout = Boolean.valueOf(String.valueOf(request.getParameter("logout")));
String RegId = String.valueOf(request.getParameter("RegId"));
// Create a session object if it is already not created.
final HttpSession session = request.getSession(true);
String trackingRequestParam = request.getParameter("isTrackingRequested");
boolean isTrackingRequested = false;
if(trackingRequestParam != null) {
isTrackingRequested = Boolean.valueOf(trackingRequestParam);
session.setAttribute("id", isTrackingRequested);
}
if(isLogout) {
session.invalidate();
}
if(trackingRequestParam != null && isTrackingRequested) {
final ScheduledExecutorService ses = Executors
.newSingleThreadScheduledExecutor();
session.setAttribute("isRunning", true);
ses.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
boolean isTrackingRequestednew = Boolean.valueOf(String.valueOf(session.getAttribute("id") ));
System.out.println("inside repeater : " + session.getAttribute("id") + " : " + isTrackingRequestednew);
// code to run
if (isTrackingRequestednew) {
try {
System.out.println("===========================================================================");
System.out.println("new track status is " + isTrackingRequestednew);
System.out.println("===========================================================================");
} catch (Exception e) {
}
} else {
ses.shutdown();
}
} catch (Exception ex) {
ex.printStackTrace();
ses.shutdown();
}
}
}, 0, 1, TimeUnit.SECONDS);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
}
编辑 *****
我正在添加我在这里使用的整个TestServlet代码。我已经将POST方法转换为GET方法以便于测试。
的TestServlet
http://localhost:8080/TestWeb/TestServlet?isTrackingRequested=true<br>
//then after a few seconds<br>
http://localhost:8080/TestWeb/TestServlet?isTrackingRequested=false
整个TestServlet
<强>测试强>
点击以下网址(TestWeb在我的情况下是上下文名称,用你的替换)
http://localhost:8080/TestWeb/TestServlet?logout=true
输出(测试在Tomcat 7.0.59上完成)
内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内转发器:true:true ================================================== ========================= 新的赛道状态是真的 ================================================== ========================= 内部转发器:false:false
跟踪设置为false后,它会在执行程序关闭时停止打印。
注意:清除Cookie以开始新会话。
Edit2 *** 添加了代码以支持下面的手动注销调用URL以注销。
String