一、要求
1. 发布到Tomcat7.0或以上版本!
二、概述
Servlete3.0的主要新特性如下三部分:
- 使用@WebServlet、@WebFilter、@WebListener三个注解来替代web.xml文件中的Servlet、Filter、Listener的配置;
- Servlet异步处理:当Servlet处理比较费时的问题时,这会让客户感觉到很卡。当使用异常处理时可以把已经处理好的内容先一步响应给客户端浏览器,然后使用另一个线程来完成费时的操作,也就是把内容一部分一部分的显示出来;
- 上传组件:不用再使用fileupload等第三方的上传组件,使用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 @WebServlet(name = "BServlet",urlPatterns = "/BServlet",asyncSupported = true)
2 public class BServlet extends HttpServlet {
3 public void doGet(final HttpServletRequest req, final HttpServletResponse resp)
4 throws ServletException, IOException {
5 resp.setContentType("text/html;charset=utf-8");
6
7 // 支持IE!如果输出不足512B,没有异步效果!
8 for(int i = 0; i <= 512; i++) {
9 resp.getWriter().print("a");
10 }
11 resp.getWriter().flush();
12
13 //1. 得到异步上下文对象
14 final AsyncContext ac = req.startAsync(req, resp);
15
16 //2. 给上下文对象一个Runnable对象,让它执行这个任务
17 ac.start(new Runnable() {
18 public void run() {
19 println("现在马上开始<br/>", resp);
20 sleep(2000);
21 for(char c = 'A'; c <= 'Z'; c++) {
22 println(c+"", resp);
23 sleep(250);
24 }
25 // 通知Tomcat我们已经执行结束了!
26 ac.complete();
27 }
28 });
29 }
30 public void println(String text, HttpServletResponse resp) {
31 try {
32 resp.getWriter().print(text);
33 resp.getWriter().flush();
34 } catch (IOException e) { }
35 }
36 public void sleep(long ms) {
37 try {
38 Thread.sleep(ms);
39 } catch (InterruptedException e) {
40 }
41 }
42 }
五、上传支持
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>
2、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头中截取!
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 <html> 4 <head> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>注册</h1> 9 <form action="<c:url value='/AServlet'/>" method="post" enctype="multipart/form-data"> 10 用户名:<input type="text" name="username"/><br/> 11 简 历:<input type="file" name="resume"/><br/> 12 <input type="submit" value="提交"/> 13 </form> 14 </body> 15 </html>
1 package web.servlet;
2
3 import javax.servlet.ServletException;
4 import javax.servlet.annotation.MultipartConfig;
5 import javax.servlet.annotation.WebServlet;
6 import javax.servlet.http.HttpServlet;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9 import javax.servlet.http.Part;
10 import java.io.IOException;
11
12 @WebServlet(name = "AServlet",urlPatterns = "/AServlet")
13 @MultipartConfig
14 public class AServlet extends HttpServlet {
15 protected void doPost(HttpServletRequest request, HttpServletResponse response)
16 throws ServletException, IOException {
17 request.setCharacterEncoding("utf-8");
18 //1、getParameter()方法可以使用了
19 String username = request.getParameter("username");//可以使用了
20 //2、获取文件表单字段,对应的Part对象
21 Part part = request.getPart("resume");
22 //3、从Part中获取需要的数据
23 //获取上传文件的MIME类型
24 System.out.println(part.getContentType());//image/jpeg
25 //获取上传文件的字节数
26 System.out.println(part.getSize());//163302
27 //获取上传文件字段名称
28 System.out.println(part.getName());//resume
29 //获取头,这个头中包含了上传文件的名称
30 System.out.println(part.getHeader("Content-Disposition"));//form-data; name="resume"; filename="WechatIMG2.jpeg"
31
32
33 //截取上传文件名称
34 String filename = part.getHeader("Content-Disposition");
35 int start = filename.lastIndexOf("filename="") + 10;
36 int end = filename.length()-1;
37 filename = filename.substring(start,end);
38 System.out.println(filename);
39 //保存上传文件
40 part.write("/Users/Shared/"+filename);
41 }
42 }