Servlete3.0的主要新特性如下三部分:
● 使用@WebServlet、@WebFilter、@WebListener三个注解来替代web.xml文件中的Servlet、Filter、Listener的配置;
● Servlet异步处理:当Servlet处理比较费时的问题时,这会让客户感觉到很卡。当使用异常处理时可以把已经处理好的内容先一步响应给客户端浏览器,然后使用另一个线程来完成费时的操作,也就是把内容一部分一部分的显示出来;
● 上传组件:不用再使用fileupload等第三方的上传组件,使用Servlet3.0的上传组件会更方便。
<span style="font-size:18px;">@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!"); } }</span>
<span style="font-size:18px;">@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 {} }</span>
<span style="font-size:18px;">@WebListener() public class AListener implements ServletContextListener { public void contextDestroyed(ServletContextEvent arg0) { System.out.println("服务器关闭了"); } public void contextInitialized(ServletContextEvent arg0) { System.out.println("服务器启动了"); } }</span>
Servlet异步处理就是让Servlet在处理费时的请求时不要阻塞,而是一部分一部分的显示。也就是说,页面不会等到请求响应结束后一起显示。
在使用异步处理之前,一定要在@WebServlet注解中给出asyncSupported=true,不然默认Servlet是不支持异步处理的。如果存在过滤器,也要设置@WebFilter的asyncSupportedt=true。
<span style="font-size:18px;">@WebServlet(urlPatterns = {"/MyServlet"}, asyncSupported=true) //开启异步处理 public class MyServlet extends HttpServlet {…}</span>
在Servlet正常响应数据时,没什么可说的,可通知response.getWriter().print()来向客户端输出,但输出后要使用response.getWriter().flush()刷新,不然数据只是在缓冲区中,不能向客户端发送数据的。
异步响应数据需要使用request.startAsyncContext()方法获取AsyncContext对象。然后调用AsyncContext对象的start()方法启动异步响应,start()方法需要一个Runnable类型的参数。在Runnable的run()方法中给出异步响应的代码。
<span style="font-size:18px;">AsyncContext ac = request.startAsyncContext(request, response); //获取异步处理上下文对象,传递request和response对象给异步上下文,可以使用///异步上下文对象的getResponse和getRequest方法来获取request和response对象。 ac.start(new Runnable() {…}); //启动异步处理线程</span>
注意在异步处理线程中使用response做响应后,要使用response.getWriter().flush()来刷新流,不然数据是不能响应到客户端浏览器的。
<span style="font-size:18px;"> 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(); } }); //实现结果:字母会一个一个的出现,而不是一次全部出现</span>
Tomcat需要知道异步响应是否结束,如果响应不结束,虽然客户端浏览器会看到响应的数据,但是鼠标上的圈圈会不停地转,表示服务器响应还未结束。Tomcat会等待到超时为止,这个超时的时间可以通过AsyncContext类的getTimeout()方法获取,Tomcat默认为20000毫秒。当然也可以通过setTimeOut()方法设置,以毫秒为单位。
<span style="font-size:18px;">ac.setTimeout(1000*10)。</span>
如果异步线程已经结束了响应,那么可以在异步线程中调用AsyncContext.complete()方法,这样Tomcat就知道异步线程已经完成了工作了。
Servlet3.0提供了文件上传的处理方案。只需要在Servlet上添加@MultipartConfig注解即可:
<span style="font-size:18px;">@WebServlet(urlPatterns={"/UploadServlet"}) @MultipartConfig(maxFileSize=1024) public class UploadServlet extends HttpServlet { … }</span>
当然也可以为@MultipartConfig注解指定属性值,它有四个属性:
● int filesizeThreshold:指定缓存的大小,当超出这个大小后,文件会保存到磁盘上;
● String location:指定临时文件的目录;
● long maxFilesize:指定上传单个文件的大小限制,如果上传的谁的超出了这个大小,那么就会抛出异常;
● long maxRequestSize:指定整个表单的大小限制。
当在Servlet上使用了@MultipartConfig注解后,那么就可以使用request.getPart(“fieldName”)来获取<input:file>的内容,其中Part表示一个文件表单项。
<span style="font-size:18px;"><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></span>
<span style="font-size:18px;">@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"); //获取表单项内容 Part part = request.getPart("file1"); //获取表单项内容,返回值为Part 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); //把文件保存到指定路径 } }</span>