Java Servlet异步处理、非阻塞I/O和文件上传
异步处理
应用服务器中的 web容器通常对各个客户端情求分别使用一个服务器线程。在工作负载很繁重的情况下,容器常要大量线程来为所有客户端请求服务。可扩展性限制包括内存用尽,或容器线程池耗尽。为了创建可扩展的 web应用,必须确保与请求关联的线程不会空闲, 使容器可以用它们处理新的请求。有时与请求关联的线程可能会空闲, 这有两种常见的情况:
- 线程需要等待一个资源可用,或者在建立响应之前处理数据。例如,应用在生成响应之前可能需要査询一个数据库, 或者要从一个远程 web服务访问数据。
- 线程生成响应之前需要等待一个事件。例如, 一个应用在生成响应之前可能必须等待一个 JMS消息、 来自另一个客户端的新信息, 或者队列中可用的一个新数据。
这些情況表示了限制 web应用可扩展性的一些阻塞操作。异步处理是指把这些阻塞操作分配给一个新线程, 而与请求美联的线程立即返回给容器 。
servlet中的异步处理
Java EE为 servlet和过滤器提供了异步处理支持。如果一个 servlet或过渡器在处理请求时达到一个可能的阻塞操作,它可以把这个操作分配到一个异步执行上下文,并将与请求联的线程立即返回到容器, 而不生成响应, 阻塞操作在异步执行上下文中的一个不同的线程中完成,这可能会生成一个响应,或者将请求分派给另一个servlet。
要在一个 servlet上启用异步处理.可以将@Webservlet注解的参数 asyncsupported设置为true,如下所示:
@WebServ1et(urlPatterns="/asynserv1et" , asyncSupported=true)
public class AsyncServlet extends HttpServlet{
..
}
javax. servlet.Asynccontext类提供了在服务方法中完成异步处理所需的功能为了得到 Asynccontext的一个实例,可以在服务方法的请求对象上调用startAsync()方法,例如:AsynoContext acontext = req. startAsync();
这个调用将请求置于异步模式. 并确保退出服务方法后不提交响应。 必须在异步上下文中完成阻塞操作之后或者将请求分派到另一个 servlel之后再生成响应。
@WebServ1et(urlPatterns={"/asyncservlet"}), asyncSupported=true)
public classe AsyncServlet extends HttpServlet {
public void doGetlHttpServletRequest request,
HttpServletResponse response) {
final AsyncContext acontext= request.startAsync();
acontext.start(new Runnable() {
public void run() {
HttpServletResponse response= acontext.getResponse();
response.getWriter().write("complete")
acontext.cmplete()
}
...
Asyncservlet在@Webservlet注解中增加了 asyncsupported=true。 另外只有服务方法有区别 。
- request.startAsync()使请求得到异步处理,响应不会在服务方法完成时发送到客户端。
- acontext.start(new Runnable() 1…}) 从容器得到一个新线程。
内部类 run()方法中的代码在这个新线程中执行,这个内部类可以访问异步上。
从请求读取参数.并写至响应,调用异步上下文的 complete()方法会提交响应并把它发送到客户端,Asyncservlet的服务方法立即返回,请求在异j步上下文中处理。
非阻塞I/O
应用服务器中的 Web容器通常对每个客户端请求分别使用一个线程。要开发可扩展的 web应用. 必须确保与客户端请求关联的线程不会会保持空闲吗来等持一个阻塞操作完成。异步处理提供了-种机制,在一个新线程中执行应用特定的阻塞操作,将与请求关联的线程立即返回到容器. 即使对服务方法中所有应用特定的阻塞操作都使用异步处理,但由于输入/输出同题,与客户端请求关联的线程偶尔也可能会空闲。
例如.如果客户端在一个很慢的网络连接上提交一个很大的 HTTP POST青求.服务器读取请求的速度可能比客户端提供请求的速度更快。 如果使用传统的 I/O。 与这个请求关联的容器线程有时就会空闲, 来等待请求的其余部分 。
Java EE采用异步模式处理清求时, 対 servlet和过滤器提供非阻塞I/O支持。下面的步骤总结了如何使用非阻塞 I/0在服务方法中处理清求和写入响应。
- 将请求置为异步模式.
- 在服务方法中从请求和响应对象得到一个输入流或一个输出流。
- 为输入流指定一个读监听器成为输出流提供一个写监听器。
- 在监听器的回调方法中处理请求和响应 。
@WebServlet(urlPatterns={"/asyncioservlet"},asyncSupported= true)
public class AsyncIOServlet extends HttpServlet{
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final AsyncContext context = request.startAsync();
final ServletInputStream input = request.getInputStream();
input.setReadListener(new ReadListener() {
byte buffer [] = new byte[4 * 1024];
StringBuilder sbuilder = new StringBuilder();
@Override
public void onError(Throwable arg0) {
// TODO Auto-generated method stub
}
@Override
public void onDataAvailable() throws IOException {
try {
do {
int length = input.read(buffer);
sbuilder.append(new String(buffer,0,length));
} while (input.isReady());
} catch (Exception e) {
// TODO: handle exception
}
}
@Override
public void onAllDataRead() throws IOException {
try {
context.getResponse().getWriter().write("the message");
} catch (Exception e) {
// TODO: handle exception
}
context.complete();
}
});
}
}
input.isReady()是非阻塞的方法,是否可读,立即返回true或false。
Servlet文件上传
对于很多 web应用来说. 支持文件上传是一个很基本也很常见的需求。 在Servlet规范中,实现文件上传需要使用外部库或者复杂的输入处理。现在 Java Servlet规范可以采用一种通用而且可移植的方式为这个问题提供一个可靠的解决方案。如今 Java Servlet技术可以直接支持文件上传, 实现 Java Servlet规范的所有 web容器都可以解析多部分请求,通过过HttpServletRequest对象提供 MIME附件。
另外有一个新注解 javax.servlet.annotation.Multipartconfig,用来指示声明该注解的servlet希望使用multipart/form-data MIME类型建立清求。有 @Multipartconfig 注解的servlet可以调用 request.getPart(String name)或 request.getParts()方法获取一个给定 multipart/form-data请求的 Part组件。
@Multipartconfig注解
@Multipartconfig注解支持以下可选的属性:
- location:这是一个绝对路径,指示文件系统上的一个目录。location属性不支持相对于应用上下文的路径。处理多部分成文件大小超出指定 filesizeThreshold设置时,会用这个位置临时地存储文件。默认位置为””
- filesizeThreshold:超过这个文件大小(字节数)的其余部分将临时存储在磁盘上。默认大小为 0字节。
- MaxFilesize:上传文件允许的最大大小(字节数)。如果任何一个上传文件的大小超过了这个大小, Web容器就会批出一个异常(IllegalstateException)。默认大小为无限制 。
- maxRequestSize:対于一个multipart/form-clata请求,所允许的最大大小(字节数)。如果所有上传文件的总大小超过这个固值, Web容器会抛出一个异常。默认大小为无限制 。
getParts和 getPart 方法
Servlet规范还支持另外两个 HttpservletRequest方法:
- Collection getParts()
- Part getPart(String namee)
request.getParts()方法返回所有 Part对象的集合。如果有多个输入文件类型,就会返回多个 Part对象,由于 Part对象是命名对象,可以用 getPart(string name)方法访问一个特定的 Part,或者.可以用返回Iterable的 getparts()方法得
到所有 Part对象上的一个Iterator。
javax.servlet.http.Part接口是一个简单的接口, 提供了一些允许各个 part自省的方法, 这些方法完成以下工作:
- 获取Part的名字、大小和内容类型,,
- 查询带 part提交的头部,,
- 删除一个Part,,
- 将一个 part写到磁盘上
例如, Part接口提供了write(string filename)方法来写指定名的文件,这个文件保存在@MultipartConfig注解location属性指定的目录中,或者对于fileupload示例,它保存在表单Destination域指定的位置上。
参考资料
- 《Java EE 7权威指南》
Java Servlet异步处理、非阻塞I/O和文件上传的更多相关文章
- java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多
java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 也仿照着 netty处理了NIO的空轮询BUG 本项目并不复杂 代码不多 ...
- java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息
1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...
- Android(java)学习笔记214:开源框架的文件上传(只能使用Post)
1.文件上传给服务器,服务器端必然要写代码进行支持,如下: 我们新建一个FileUpload.jsp的动态网页,同时我们上传文件只能使用post方式(不可能将上传数据拼凑在url路径下),上传数据Ap ...
- java 网络编程之TCP通信和简单的文件上传功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- Android(java)学习笔记157:开源框架的文件上传(只能使用Post)
1.文件上传给服务器,服务器端必然要写代码进行支持,如下: 我们新建一个FileUpload.jsp的动态网页,同时我们上传文件只能使用post方式(不可能将上传数据拼凑在url路径下),上传数据Ap ...
- Servlet 过滤器、拦截器、监听器以及文件上传下载
在学习之初,总是对过滤器.拦截器.监听器这三个搞不清楚,现在进行一些记录,方便大家交流,也为了提高自身的学习能力! 如果想要了解这三个的作用,首先对servlet流程进行熟悉了解,servlet是客户 ...
- java中TCP两个例子大写服务器和文件上传
大写服务器的实例: package com.core.net; import java.io.BufferedReader; import java.io.BufferedWriter; import ...
- socket编程 —— 非阻塞socket (转)---例子已上传至文件中
在上一篇文章 <socket编程——一个简单的例子> http://blog.csdn.net/wind19/archive/2011/01/21/6156339.aspx 中写了一个简单 ...
- wordpress非弹窗表单多文件上传插件
插件名:Drag and Drop Multiple File Upload - Contact Form 7 (ps:如果是弹窗表单,不要使用这个插件Drag and Drop Multiple F ...
随机推荐
- 20155336虎光元实验四 Android开发基础
20155336虎光元实验四 Android开发基础 实验内容 1:完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学号 2:创建 ThirdActivi ...
- stardict词库
http://download.huzheng.org/zh_CN/ sudo tar -jxvf * -C /usr/share/stardict/dic
- WPF 带刻度的滑动条实现
原文:WPF 带刻度的滑动条实现 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83507170 ...
- tkinter界面卡死的解决办法
0.如果点击按钮,运行了一个比较耗时的操作,那么界面会卡死 import tkinter as tk import time def onclick(text, i): time.sleep(3) t ...
- STM32运行FreeRTOS出现prvTaskExitError错误死机
文件port.c prvTaskExitError();任务退出错误,一个可能在任务里面写了return,另一个可能任务切换退出问题,入栈和出栈的时候出了问题. static void prvTask ...
- PHP 中的mktime()函数本周时间
上周写一个接口,用到了本周的开始时间和结束时间作为筛选条件去筛选数据,我只记得有mktime()这个函数,具体怎么用的不太清楚,于是百度之,找到了这个: 本周开始时间:date("Y-m-d ...
- ffmpeg 压缩H265 Windows 硬件编码
硬件NVIDIA:ffmpeg.exe -i input.avi -c:v hevc_nvenc -preset:v fast output.mp4 软件 :ffmpeg.exe - ...
- 阿里云服务器Centos上Apache安装SSL证书配置Https
首先我们先去阿里云申请一个免费的SSL证书(https://common-buy.aliyun.com/?spm=5176.7968328.1266638..5e971232BzMSp5&co ...
- IDEA 破解图文教程 - 2018.9 更
你好!这里是你要找的 IDEA 破解方法 目录 一.前言 二.IDEA 安装 2.1 下载IDEA 旗舰版 2.2 开始安装 2.3 自定 ...
- ES6的新特性(7)——函数的扩展
函数的扩展 函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console ...