我正在编写一个Spring Web应用程序,我将“/ do”URL路径映射到以下Controller的方法
@Controller
public class MyController
{
@RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
while (!f.exists())
{
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
// ok, let's continue
}
}
otherMethodEnded.tmp
文件是由另一个Controller的方法写的,所以当客户端调用第二个URL时,我希望第一个方法退出while循环。
一切正常,除非客户端调用“/ do”URL,然后在收到响应之前关闭连接。问题是即使客户端关闭,服务器仍然在while (!f.exists())
循环中,并且无法调用第二个URL来解锁while循环。
我会尝试检索“/ do”URL的连接状态,并在客户端关闭连接时退出循环,但我找不到任何方法。
我尝试使用HttpServletRequest.getSession(false)
方法,但返回的HttpSession
对象始终不为空,因此在客户端连接关闭的情况下,HttpServletRequest
对象不会更新。
如何检查客户端是否仍在等待响应?
答案 0 :(得分:1)
验证某些东西的最简单方法是定义一个超时值,然后在循环测试期间,等待等待的时间是否超过了超时。
类似的东西:
@Controller
public class MyController
{
private static final long MAX_LOOP_TIME = 1000 * 60 * 5; // 5 minutes? choose a value
@RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
long startedAt = System.currentTimeMillis()
boolean forcedExit = false;
while (!forcedExit && !f.exists())
{
try {
Thread.sleep(5000);
if (System.currentTimeMillis() - startedAt > MAX_LOOP_TIME) {
forcedExit = true;
}
} catch (InterruptedException e) {
forcedExit = true;
}
}
// ok, let's continue
// if forcedExit , handle error scenario?
}
}
此外:InterruptedException不是盲目捕获和忽略的东西。见this discussion
在你的情况下,如果你被中断,我真的会退出while循环。
当您注意到您写入的输出流(response.outputstream)已关闭时,您只知道客户端是否不再等待您的连接。但是没有办法检测它。 (有关详细信息,请参阅this question)
看到您已经表明您的客户偶尔会进行回调,您可以在客户端轮询中查看其他呼叫是否已完成。如果此其他呼叫已完成,请执行操作,否则直接返回并让客户端再次进行呼叫。 (假设您发送json,但根据需要进行调整)
类似
public class MyController
{
@RequestMapping(value="/do", method=RequestMethod.GET)
public String do()
{
File f = new File("otherMethodEnded.tmp");
if (f.exists()) {
// do what you set out to do
// ok, let's continue
// and return with a response that indicates the call did what it did
// view that returns json { "result" : "success" }
return "viewThatSIgnalsToClientThatOperationSucceeded";
} else {
// view that returns json: { "result" : "retry" }
return "viewThatSignalsToClientToRetryIn5Seconds";
}
}
}
然后客户端会运行类似:(伪javascript,因为它已经有一段时间了)
val callinterval = setInterval(function() { checkServer() }, 5000);
function checkServer() {
$.ajax({
// ...
success: successFunction
});
}
function successFunction(response) {
// connection succeeded
var json = $.parseJSON(response);
if (json.result === "retry") {
// interval will call this again
} else {
clearInterval(callinterval);
if (json.result === "success") {
// do the good stuff
} else if (json.result === "failure") {
// report that the server reported an error
}
}
}
当然,这只是半严肃的代码,但它大致是我如何尝试它,如果我有依赖。如果这是关于文件上传,请记住,此文件可能还不包含所有字节。文件存在!=文件=完全上传,除非您使用移动它。 cp / scp /等不是原子的。