问题描述
我试图做到的是不是太复杂,但我有一点麻烦,因为我不精通AJAX。
What I am trying to accomplish is not too complex, but I am having a bit of trouble as I am not well versed in AJAX.
当它被实现,我将有一个JSP,有一个按钮,这将调用一个异步的Servlet。小服务程序将运行一个长运行的任务和通过增加行向表当任务的部分完成提供动态反馈给用户。
When it is implemented, I will have a JSP that has a button which invokes an Asynchronous Servlet. The servlet will run a long running task and provide dynamic feedback to the user by adding rows to a table when parts of the task are completed.
在我试图写的最终版本,我做概念证明以获得如何将工作的理解。然而,我遇到了一个障碍。当我在点击一个按钮,使用AJAX调用的函数工作正常时调用的是一个定时同步的servlet。但是,只要我做的servlet异步的,不显示更新。
Before I attempt to write the final version, I am doing a proof of concept to get an understanding of how this will work. However, I'm running into a snag. When I use an AJAX call upon clicking a button, the function works as expected when the call is to a regular synchronous servlet. However, as soon as I make the servlet asynchronous, the updates are not displayed.
会有人能提供一些见识到了什么地方出了错?
Would anybody be able to provide some insight into what's going wrong?
我的JSP是这样的:
<html>
<body>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$('#mybutton').click(function() {
$.get('someservlet', function(responseJson) {
$.each(responseJson, function(index, item) {
$('<ul>').appendTo('#somediv');
$('<li>').text(item.row1).appendTo('#somediv');
$('<li>').text(item.row2).appendTo('#somediv');
$('<li>').text(item.row3).appendTo('#somediv');
$('<li>').text(item.row4).appendTo('#somediv');
});
});
});
});
</script>
<p><button id="mybutton">Click to add things</button></p>
<div id="somediv"></div>
</body>
</html>
我的异步Servlet的的doGet()
的方法是这样的:
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
final AsyncContext asyncContext = request.startAsync();
final PrintWriter writer = response.getWriter();
asyncContext.setTimeout(10000);
asyncContext.start(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
List<Row> rows = new ArrayList<Row>();
rows.add(new Row(i, i + 1, i + 2, i + 3));
String json = new Gson().toJson(rows);
writer.write(json);
writer.flush();
log.info("Wrote to JSON: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
asyncContext.complete();
}
});
有什么想法?好像当我按一下按钮只接受来自主servlet线程响应,出现我的AJAX调用。也许我需要调用JavaScript函数从异步的write()
电话?我只是不知道如何做到这一点,或者这将是正确的执行方法。
Any thoughts? It seems like my AJAX call that occurs when I click the button only accepts a response from the main servlet thread. Perhaps I need to call a JavaScript function from the asynchronous write()
calls? I'm just not sure how to do this or if this would be the correct method of execution.
推荐答案
OK!
所以,我想它了。这是不是很花哨,因为我本来希望它是,但它的作品。而且,它的概念只是为了实现我所工作的一个证明。如果任何人都可以提供进一步的深入了解,我爱能够实现这一点使用服务器推送,而不是投票。
So, I figured it out. It's not quite as fancy as I would have liked it to be, but it works. And, it's just a proof of concept for implementing what I am working on. If anyone can provide further insight, I've love to be able to implement this using server push instead of polling.
思考?
我的JSP是这样的:
<html>
<head>
<script src="jquery-1.7.1.min.js" type="text/javascript" ></script>
<script>
$(document).ready(function() {
var prevDataLength;
var nextLine = 0;
var pollTimer;
$('#abutton').click(function() {
$(function(){
var x = new $.ajaxSettings.xhr();
x.open("POST", "someservlet");
handleResponseCallback = function(){
handleResponse(x);
};
x.onreadystatechange = handleResponseCallback;
pollTimer = setInterval(handleResponseCallback, 100);
x.send(null);
});
});
function handleResponse(http) {
if (http.readyState != 4 && http.readyState != 3)
return;
if (http.readyState == 3 && http.status != 200)
return;
if (http.readyState == 4 && http.status != 200) {
clearInterval(pollTimer);
}
while (prevDataLength != http.responseText.length) {
if (http.readyState == 4 && prevDataLength == http.responseText.length)
break;
prevDataLength = http.responseText.length;
var response = http.responseText.substring(nextLine);
var lines = response.split('\n');
nextLine = nextLine + response.lastIndexOf(']') + 1;
if (response[response.length-1] != ']')
lines.pop();
for (var i = 0; i < lines.length; i++) {
var line = $.parseJSON(lines[i]);
addToTable(line);
}
}
if (http.readyState == 4 && prevDataLength == http.responseText.length)
clearInterval(pollTimer);
}
function addToTable(JSONitem) {
$.each(JSONitem, function(index, item) {
$('<tr>').appendTo('#sometablebody')
.append($('<td>').text(item.name))
.append($('<td>').text(item.message))
.append($('<td>').text(item.number))
.append($('<td>').append($('<a>').attr('href', item.link).text('link')));
});
}
});
</script>
<title>Async Test</title>
</head>
<body>
<p><button id="abutton">Click to add things</button></p>
<div id="somediv">
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>Message</td>
<td>Number</td>
<td>Link</td>
</tr>
</thead>
<tbody id="sometablebody"></tbody>
</table>
</div>
</body>
</html>
我的异步Servlet的的doGet()
的方法是这样的:
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
final AsyncContext asyncContext = request.startAsync();
final PrintWriter writer = response.getWriter();
asyncContext.setTimeout(60000);
asyncContext.start(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
List<Row> list = new ArrayList<Row>();
list.add(new Row("First", "This is the first", String.valueOf(i), "link" + i));
list.add(new Row("Second", "This is the second", String.valueOf(i), "link" + i));
list.add(new Row("Third", "This is the third", String.valueOf(i), "link" + i));
String json = new Gson().toJson(list);
asyncContext.getResponse().setContentType("application/json");
asyncContext.getResponse().setCharacterEncoding("UTF-8");
try {
asyncContext.getResponse().getWriter().write(json);
asyncContext.getResponse().getWriter().flush();
} catch (IOException ex) {
System.out.println("fail");
}
Thread.sleep(250);
} catch (InterruptedException ex) {
break;
}
}
asyncContext.complete();
}
});
此外,对于这一切工作,我实现了一个简单的行
类:
Additionally, for this all to work, I implemented a simple Row
class:
public class Row {
private String name;
private String message;
private String number;
private String link;
public Row(String name, String message, String number, String link) {
setName(name);
setMessage(message);
setNumber(number);
setLink(link);
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
这篇关于异步调用Servlet的从阿贾克斯的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!