servlet3.0
Servlet3.0
一、要求
1. MyEclipse10.0或以上版本!
2. 发布到Tomcat7.0或以上版本!
二、步骤
1. 创建JavaEE6.0应用!
-----------------------------
三、概述
* 注解代替web.xml配置文件
* 异步处理
* 对上传的支持
Servlet3.0在市场上没有应用!
-----------------------------
四、注解代替配置文件
1. 删除web.xml
2. 在Servlet类上添加@WebServlet(urlPatterns={"/AServlet"})
总结:
* 注解好处:配置信息少!
* 注解缺点:不方便修改!
3. 在Filter类上添加@WebFilter(urlPatterns="/AFilter")
4. 在Listener类上添加@WebListener
-----------------------------
五、异步处理
1. 什么是异步处理
原来,在服务器没有结束响应之前,浏览器是看不到响应内容的!只有响应结束时,浏览器才能显示结果!
现在异步处理的作用:在服务器开始响应后,浏览器就可以看到响应内容,不用等待服务器响应结束!
2. 实现异步的步骤
* 得到AsyncContext,它异步上下文对象
AsyncContext ac = request.startAsync(request,response);
* 给上下文一个Runnable对象,启动它!(给上下文一个任务,让它完成!)
ac.start(new Runnable() {
public void run() {
...
}
});
* @WebServlet(urlPatterns="/AServlet", asyncSupported=true)
* resp.setContentType("text/html;charset=utf-8");
* IE如果不能正常输出,这说明响应体大小不足512B,那你需要多输出点废话!
* AsyncContext#complete():通知Tomcat我们异步线程已经执行结束了!这让Tomcat才会及时的断开与浏览器的连接!
-----------------------------
六、上传支持
1. 上传
* 上传对表单的要求:
> method="post"
> enctype="multipart/form-data",它的默认值是:application/x-www-form-urlencoded
> <input type="file" name="必须给"/>
* 上传Servlet的使用:
> request.getParameter()不能再用
> request.getInputStream()使用它来获取整个表单的数据!
* commons-fileupload
> 创建工厂
> 解析器
> 使用解析器来解析request对象,得到List<FileItem>
==============
Servlet3.0对上传提供了支持:
* 表单不变
* 在Servlet中不需要再使用commons-fileupload,而是使用Servlet3.0提供的上传组件接口!
==============
上传的步骤:
* 使用request.getPart("字段名"),得到Part实例,
* Part:
> String getContentType():获取上传文件的MIME类型
> String getName():获取表单项的名称,不是文件名称
> String getHeader(String header):获取指定头的值
> long getSize():获取上传文件的大小
> InputStream getInputStream():获取上传文件的内容
> void write(String fileName):把上传文件保存到指定路径下
* 默认Servlet是不支持使用上传组件:需要给Servlet添加一个注解: @MultipartConfig
它没有提供获取上传文件名称的方法:
* 这需要我们自己从Content-Disposition头中截取!
Servlet3.0新特性
1 Servlet3.0新特性概述
Servlete3.0的主要新特性如下三部分:
使用@WebServlet、@WebFilter、@WebListener三个注解来替代web.xml文件中的Servlet、Filter、Listener的配置;
Servlet异步处理:当Servlet处理比较费时的问题时,这会让客户感觉到很卡。当使用异常处理时可以把已经处理好的内容先一步响应给客户端浏览器,然后使用另一个线程来完成费时的操作,也就是把内容一部分一部分的显示出来;
上传组件:不用再使用fileupload等第三方的上传组件,使用Servlet3.0的上传组件会更方便。
2 @WebServlet、@WebFilter、@WebListener
@WebServlet(
urlPatterns={"/AServlet"},
initParams={@WebInitParam(name="paramName",value="paramValue")},
loadOnStartup=1
)
public class AServlet extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
System.out.println(config.getInitParameter("paramName"));
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("Hello World!");
}
}
@WebFilter(urlPatterns={"/*"},
dispatcherTypes={DispatcherType.REQUEST, DispatcherType.FORWARD})
public class AFilter implements Filter {
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("start filter");
chain.doFilter(request, response);
System.out.println("end filter");
}
public void init(FilterConfig fConfig) throws ServletException {}
}
@WebListener()
public class AListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("服务器关闭了");
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("服务器启动了");
}
}
3 Servlet异步处理
Servlet异步处理就是让Servlet在处理费时的请求时不要阻塞,而是一部分一部分的显示。
也就是说,在使用Servlet异步处理之后,页面可以一部分一部分的显示数据,而不是一直卡,等到请求响应结束后一起显示。
在使用异步处理之前,一定要在@WebServlet注解中给出asyncSupported=true,不然默认Servlet是不支持异步处理的。如果存在过滤器,也要设置@WebFilter的asyncSupportedt=true。
@WebServlet(urlPatterns = {"/MyServlet"}, asyncSupported=true)
public class MyServlet extends HttpServlet {…}
注意,响应类型必须是text/html,所以:response.setContentType(“text/html;charset=utf-8”);
使用异步处理大致可以分为两步:
Servlet正常响应数据;
Servlet异常响应数据。
在Servlet正常响应数据时,没什么可说的,可通知response.getWriter().print()来向客户端输出,但输出后要使用response.getWriter().flush()刷新,不然数据只是在缓冲区中,不能向客户端发送数据的。
异步响应数据需要使用request.startAsync()方法获取AsyncContext对象。然后调用AsyncContext对象的start()方法启动异步响应,start()方法需要一个Runnable类型的参数。在Runnable的run()方法中给出异步响应的代码。
AsyncContext ac = request.startAsyncContext(request, response);
ac.start(new Runnable() {…});
注意在异步处理线程中使用response做响应后,要使用response.getWriter().flush()来刷新流,不然数据是不能响应到客户端浏览器的。
asyncContext.start(new Runnable() {
public void run() {
for(char i = 'a'; i <= 'z'; i++) {
try {
Thread.sleep(100);
asyncContext.getResponse().getWriter().print(i + " ");
asyncContext.getResponse().getWriter().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
asyncContext.complete();
}
});
Tomcat需要知道异步响应是否结束,如果响应不结束,虽然客户端浏览器会看到响应的数据,但是鼠标上只是有个圈圈的不行的转啊转的,表示还没有结束响应。Tomcat会等待到超时为止,这个超时的时间可以通过AsyncContext类的getTimeout()方法获取,Tomcat默认为20000毫秒。当然也可以通过setTimeOut()方法设置,以毫秒为单位。ac.setTimeout(1000*10)。
如果异步线程已经结束了响应,那么可以在异步线程中调用AsyncContext.complete()方法,这样Tomcat就知道异步线程已经完成了工作了。
@WebServlet(urlPatterns = {"/AServlet"}, asyncSupported=true)
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.println("Servlet begin <br>");
out.flush();
final AsyncContext asyncContext = request.startAsync(request, response);
asyncContext.setTimeout(1000 * 20);
asyncContext.start(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
asyncContext.getResponse().getWriter().print("马上开始" + "<br/>");
asyncContext.getResponse().getWriter().flush();
Thread.sleep(2000);
} catch (Exception e1) {
}
for(char i = 'a'; i <= 'z'; i++) {
try {
Thread.sleep(100);
asyncContext.getResponse().getWriter().print(i + " ");
asyncContext.getResponse().getWriter().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
asyncContext.complete();
}
});
// asyncContext.start(businessHandleThread);
// 也可以用这种方法启动异步线程
out.println("Servlet end <br>");
}
}
4 文件上传
Servlet3.0提供了文件上传的处理方案。只需要在Servlet上添加@MultipartConfig注解即可。
@WebServlet(urlPatterns={"/UploadServlet"})
@MultipartConfig(maxFileSize=1024)
public class UploadServlet extends HttpServlet { … }
当然也可以为@MultipartConfig注解指定属性值,它有四个属性:
int filesizeThreshold:指定缓存的大小,当超出这个大小后,文件会保存到磁盘上;
String location:指定临时文件的目录;
long maxFilesize:指定上传单个文件的大小限制,如果上传的谁的超出了这个大小,那么就会抛出异常;
long maxRequestSize:指定整个表单的大小限制。
当在Servlet上使用了@MultipartConfig注解后,那么就可以使用request.getPart(“fieldName”)来获取<input:file>的内容,其中Part表示一个文件表单项。
<form action="/a1/UploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br/>
照 片:<input type="file" name="file1" /><br/>
<input type="submit" value="提交"/>
</form>
@WebServlet(urlPatterns={"/UploadServlet"})
@MultipartConfig(maxFileSize=1024 * 1024)
public class UploadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
response.getWriter().print("size: " + username + "<br/>");
Part part = request.getPart("file1");
response.getWriter().print("size: " + part.getSize() + "<br/>");
response.getWriter().print("type: " + part.getContentType() + "<br/>");
response.getWriter().print("name: " + part.getName() + "<br/>");
String name = part.getHeader("content-disposition");
String fileNameTmp = name.substring(name.indexOf("filename=")+10);
String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("\""));
System.out.println("fileName: " + fileName);
String savepath = this.getServletContext().getRealPath("/uploads");
part.write(savepath + "/" + fileName);
}
}