我们在 java web-app 中有任务需要很长时间才能完成,并且在任务完成之前请求超时并且页面无法显示。我们正在考虑设置一个异步重定向 servlet,它充当前端控制器,将请求重定向到适当的操作类,并且在为请求提供服务时,servlet 每隔一分钟左右就会不断发送一个心跳,直到相应的请求完成动作类。有没有人使用异步 servlet 3.0 实现了类似的东西?这也可能吗?我知道这类似于服务器推送。谢谢指导。
问问题
1135 次
1 回答
1
是的,您可以通过使用异步 servlet 3.0 来实现这种功能。它基本上像推送通知一样工作,并且还可以让您在不发出请求的情况下持续响应我有一个与此代码共享的代码可能有助于您发出异步请求.
this example check live users
@WebServlet(urlPatterns = { "/checkliveuser" }, asyncSupported = true)
public class CheckLiveUser extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Queue<AsyncContext> queue = new ConcurrentLinkedQueue();
private static final BlockingQueue<String> messageQueue = new LinkedBlockingQueue();
private static final String BEGIN_SCRIPT_TAG = "<script type='text/javascript'>\n";
private static final String END_SCRIPT_TAG = "</script>\n";
private Thread notifierThread = null;
@Override
public void init(ServletConfig config) throws ServletException {
ServletContext context = config.getServletContext();
Set<String> users = new HashSet<String>();
Map<String, String> page = new HashMap<String, String>();
context.setAttribute("page", page);
context.setAttribute("messageQueue", messageQueue);
Runnable notifierRunnable = new Runnable() {
public void run() {
boolean done = false;
while (!done) {
System.out.println("in thread");
String cMessage = null;
try {
cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", messageQueue.take())
+ END_SCRIPT_TAG;
for (AsyncContext ac : queue) {
try {
PrintWriter acWriter = ac.getResponse()
.getWriter();
acWriter.println(cMessage);
acWriter.flush();
} catch (IOException ex) {
System.out.println(ex);
queue.remove(ac);
}
}
} catch (InterruptedException iex) {
done = true;
System.out.println(iex);
}
}
}
};
notifierThread = new Thread(notifierRunnable);
notifierThread.start();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
final AsyncContext ac = request.startAsync();
ac.setTimeout(10 * 60 * 1000 * 1000);
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on complete");
}
public void onTimeout(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on timeout");
}
public void onError(AsyncEvent event) throws IOException {
queue.remove(ac);
System.out.println("on error");
}
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("on startup");
}
});
queue.add(ac);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
ServletContext context = request.getServletContext();
HttpSession session = request.getSession();
Map<String, String> logins = (Map<String, String>) context
.getAttribute("page");
if (request.getParameter("action") != null
&& !request.getParameter("action").isEmpty()) {
if (request.getParameter("action").equalsIgnoreCase("logout")) {
logins.remove(request.getSession().getId());
request.getSession().invalidate();
}
}
String name = request.getParameter("loginID");
if (name != null) {
session.setAttribute("user", name);
session.setAttribute("jsessionId", session.getId());
logins.put(session.getId(), name);
}
String html = "";
for (Map.Entry<String, String> entry : logins.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "
+ entry.getValue());
html += entry.getValue() + "<br>";
}
String cMessage = BEGIN_SCRIPT_TAG + toJsonp("<b>Live User:", html)
+ END_SCRIPT_TAG;
notify(cMessage);
response.getWriter().println("success");
if (request.getParameter("action") != null
&& !request.getParameter("action").isEmpty()) {
if (request.getParameter("action").equalsIgnoreCase("logout"))
response.sendRedirect("login.jsp");
} else {
response.sendRedirect("welcome.jsp");
}
}
@Override
public void destroy() {
queue.clear();
notifierThread.interrupt();
}
private void notify(String cMessage) throws IOException {
try {
messageQueue.put(cMessage);
} catch (Exception ex) {
IOException t = new IOException();
t.initCause(ex);
throw t;
}
}
private String escape(String orig) {
StringBuffer buffer = new StringBuffer(orig.length());
for (int i = 0; i < orig.length(); i++) {
char c = orig.charAt(i);
switch (c) {
case '\b':
buffer.append("\\b");
break;
case '\f':
buffer.append("\\f");
break;
case '\n':
buffer.append("<br />");
break;
case '\r':
// ignore
break;
case '\t':
buffer.append("\\t");
break;
case '\'':
buffer.append("\\'");
break;
case '\"':
buffer.append("\\\"");
break;
case '\\':
buffer.append("\\\\");
break;
case '<':
buffer.append("<");
break;
case '>':
buffer.append(">");
break;
case '&':
buffer.append("&");
break;
default:
buffer.append(c);
}
}
return buffer.toString();
}
private String toJsonp(String name, String message) {
return "window.parent.app.update({ name: \"" + escape(name)
+ "\", message: \"" + escape(message) + "\" });\n";
}
于 2014-05-31T09:24:53.013 回答