gpt4 book ai didi

java - 响应何时以异步 Servlet 传递给客户端?

转载 作者:行者123 更新时间:2023-11-30 08:27:32 25 4
gpt4 key购买 nike

我无法理解异步 servlet 的工作原理,以及 servlet 通常如何将它们的响应传递给客户端。
我想要做的是通过 ajax 将视频上传到 servlet。我认为使用异步 servlet,我会立即在我的浏览器中获得响应,然后在另一个线程中完成长任务。

我在这里发布我的初始代码,在为文件处理编写任何代码之前,只是一个测试异步的初始 servlet。

@WebServlet(name = "VideoUploader", urlPatterns = {"/VideoUploader"}, 
asyncSupported = true)

@MultipartConfig
public class VideoUploader extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

final PrintWriter pw = response.getWriter();

final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);

ac.addListener(new AsyncListener() {
@Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}

@Override
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}

@Override
public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");
}

@Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");
}
});

ac.start(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 10; i++) {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
ac.complete();
}
});

pw.write("end");
pw.close();
}
}

然后,客户端部分是:

<form id="formVideo">
<label for="videoFile">Vídeo:</label>
<input id="videoFile" name="videoFile" type="file" /> <br/>
<input id="uploadVideoBtn" type="button" value="Subir" onClick="uploadVideo();"/>
</form>

<div id="notificaciones"/>

<script type="text/javascript">
function uploadVideo() {
var file = document.getElementById("videoFile").files[0];

var formdata = new FormData();
formdata.append("file", file);

var xhr = new XMLHttpRequest();

xhr.open("POST","/webapp/VideoUploader", true);
xhr.send(formdata);

xhr.onload = function(e) {
if (this.status == 200) {
alert(this.responseText);
}
};
}
</script>

当我没有将视频附加到文件输入时,该过程按我预期的方式完成,响应立即在浏览器中收到。但是当我附加任何大小的文件时,我的浏览器在另一个线程结束之前不会收到响应。

我正在研究非阻塞 IO,但我不确定它是否与此行为有关。

虽然我会听取任何建议,但我仍然不确定我要如何实现它,但我想了解这个异步 servlet 的行为。

最佳答案

很明显,您的浏览器将等待另一个线程完成。

下面涉及的步骤

  1. 客户端向服务器发送请求
  2. Server从ThreadPool中分配Thread(Servlet Container)
  3. Servlet 容器创建 Servlet 实例/重用现有的 Servlet 实例并调用(Servlet 线程)中的 Servcie 方法
  4. 在 Service 方法中调用 startAsync() 将启动新线程并将请求、响应实例传递给新线程以处理请求
    注意** 新线程不会阻塞 http 连接,它只是jvm 中的一个线程,此时不阻塞任何 IO
  5. Servlet线程存在服务方法并返回线程池
    注意**这里Response还没有发送到客户端/浏览器
  6. 一旦进程在步骤 4 中启动完成,该线程将请求 Servlet 容器分配给新的 Servlet 线程,以将响应发送回客户端。

只有在第 6 步,响应才会返回给客户端。因此,从客户端的角度来看,正常请求与“asyncSupported = true”请求之间没有区别。

Servlet 3.0 通过使用“asyncSupported = true”而不是每个连接的线程来支持每个请求的线程。
每个连接的线程将导致线程饥饿。

@WebServlet(name = "VideoUploader", urlPatterns = { "/VideoUploader" }, asyncSupported = true)
@MultipartConfig
public class VideoUploader extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}

@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);

ac.addListener(new AsyncListener() {

public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}

public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}

public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");

}

public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");

}

});

ac.start(new Runnable() {

public void run() {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
for (Part part : ((HttpServletRequest) ac.getRequest())
.getParts()) {
System.out.println("File received"); // You Should write
// file here
// like
// part.write("fileName");
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (ServletException e1) {
e1.printStackTrace();
}
ac.complete();
PrintWriter pw = null;
try {
pw = ac.getResponse().getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.write("end");
pw.close();
}

});

}
}

关于java - 响应何时以异步 Servlet 传递给客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20801529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com