[转]Servlet 3.0 新特性详解
原文地址:http://blog.csdn.net/xiazdong/article/details/7208316
Servlet 3.0 新特性概览
1.Servlet、Filter、Listener无需在web.xml中进行配置,可以通过Annotation进行配置;
2.模块化编程,即将各个Servlet模块化,将配置文件也分开配置。
3.Servlet异步处理,应对复杂业务处理;
4.异步Listener,对于异步处理的创建、完成等进行监听;
5. 文件上传API简化;
tomcat 7.0.X 支持Servlet 3.0
一、Annotation支持
1.Servlet
原本Servlet开发完后,必须在web.xml中配置如下代码:
- <servlet>
- <servlet-name></servlet-name>
- <servler-class></servlet-class>
- <load-on-startup></load-on-startup>
- <init-param>
- <param-name></param-name>
- <param-value></param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name></servlet-name>
- <url-pattern></url-pattern>
- </servlet-mapping>
现在只需要在java源文件的Servlet类前面加上:
@WebServlet(name="",urlPatterns={""},initParams={@WebInitParam(name="",value=""),loadOnStartup=1})
public class FirstServlet extends HttpServlet{}
代码示例:
实现一个最简单的Servlet。
- package org.servlet;
- import java.io.*;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import javax.servlet.annotation.*;
- /*
- name == <servlet-name>
- urlPatterns == <url-pattern>,
- loadOnStartup == <load-on-startup>
- initParam == <init-param>
- name == <param-name>
- value == <param-value>
- */
- @WebServlet(name="HelloServlet" ,urlPatterns={"/HelloServlet"},loadOnStartup=1,
- initParams={
- @WebInitParam(name="name",value="xiazdong"),
- @WebInitParam(name="age",value="20")
- })
- public class HelloServlet extends HttpServlet{
- public void init(ServletConfig config)throws ServletException{
- super.init(config);
- }
- public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
- request.setCharacterEncoding("GBK");
- ServletConfig config = getServletConfig();
- PrintWriter out = response.getWriter();
- out.println("<html>");
- out.println("<body>");
- out.println("Hello world"+"<br />");
- out.println(config.getInitParameter("name"));
- out.println("</body>");
- out.println("</html>");
- }
- }
这样的话只需要将class文件放入WEB-INF\classes 中,不需要再web.xml中作任何改动就完成部署;
2.Filter
原本Filter的配置如下:
- <filter>
- <filter-name></filter-name>
- <filter-class></filter-class>
- <filter>
- <filter-mapping>
- <filter-name></filter-name>
- <url-pattern></url-pattern>
- </filter-mapping>
现在只需要在java源文件的Filter类前面加上
@WebFilter(filterName="",urlPattern={"/"});
3.Listener
原本在web.xml中配置如下:
- <listener>
- <listener-class></listener-class>
- </listener>
现在只需要在java源文件的Listener类前面加上@WebListener即可;
二、web模块化
原本一个web应用的任何配置都需要在web.xml中进行,因此会使得web.xml变得很混乱,而且灵活性差,因此 Servlet 3.0可以将每个Servlet、Filter、Listener打成jar包,然后放在WEB-INF\lib中;注意各自的模块都有各自的配置文件, 这个配置文件的名称为 web-fragment.xml ;
制作一个Servlet模块的步骤:
1.编写Servlet,并编译;
2.将此编译class文件及所在包通过jar包命令打成jar包;
3.将此jar包用winrar打开,并将其中的META-INF中的manifest删除并添加 web-fragment.xml;
4.将此jar包放入WEB-INF\lib中即可;
web-fragment.xml注意点:
1.根元素为<web-fragment>;
2.<name></name>表示模块名称;
3.<ordering></ordering>是此模块的加载顺序;
4.<before><others/></before>表示第一个加载;
5.<after><name>A</name></after>表示比A后面加载;
6.可以在里面部署listener、filter、servlet
当然可以不设置任何的模块加载顺序;
代码示例:
配置两个listener模块;
FirstListener.java
- package org.listener;
- import javax.servlet.annotation.*;
- import javax.servlet.http.*;
- import javax.servlet.*;
- import java.util.*;
- import java.sql.*;
- import javax.naming.*;
- public class FirstListener implements ServletRequestListener{
- public void requestInitialized(ServletRequestEvent event){
- System.out.println("FirstListener created");
- }
- public void requestDestroyed(ServletRequestEvent event){
- System.out.println("FirstListener destroyed");
- }
- }
FirstListener 的 web-fragment.xml内容:
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- <A href="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"">http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
- <name>FirstListener</name>
- <listener>
- <listener-class>org.listener.FirstListener</listener-class>
- </listener>
- <ordering>
- <before>
- <others/>
- </before>
- </ordering>
- </web-fragment>
SecondListener.java
- package org.listener;
- import javax.servlet.annotation.*;
- import javax.servlet.http.*;
- import javax.servlet.*;
- import java.util.*;
- import java.sql.*;
- import javax.naming.*;
- public class SecondListener implements ServletRequestListener{
- public void requestInitialized(ServletRequestEvent event){
- System.out.println("SecondListener created");
- }
- public void requestDestroyed(ServletRequestEvent event){
- System.out.println("SecondListener destroyed");
- }
- }
SecondListener的 web-fragment.xml内容是:
- <?xml version="1.0" encoding="ISO-8859-1"?>
- <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- <A href="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"">http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
- <name>SecondListener</name>
- <listener>
- <listener-class>org.listener.SecondListener</listener-class>
- </listener>
- <ordering>
- <after>
- <name>FirstListener</name>
- </after>
- </ordering>
- b-fragment>
然后分别打成jar包,放入 WEB-INF\lib中即可;
随便访问一个web应用,然后发现 tomcat控制台输出:
看出先加载FirstListener,再加载SecondListener;
三、Servlet 异步处理
Servlet在MVC中作为控制器,控制器负责分发任务给MODEL完成,然后把结果交给JSP显示;
而如果有许多MODEL,其中有一个MODEL处理时间很长,则会导致整个页面的显示很慢;
异步处理关键点:将复杂业务处理另外开一个线程,而Servlet将执行好的业务先送往jsp输出,等到耗时业务做完后再送往JSP页面;
一句话:先显示一部分,再显示一部分;
异步处理Servlet的注意点是:
1.需要在Annotation中注明 asyncSupported=true;
- package org.sync;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import javax.servlet.annotation.*;
- import java.io.*;
- @WebServlet(name="AsyncServlet",urlPatterns={"/AsyncServlet"},asyncSupported=true)
- public class AsyncServlet extends HttpServlet{
- public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
- request.setCharacterEncoding("GBK");
- response.setContentType("text/html;charset=GBK");
- PrintWriter out = response.getWriter();
- out.println("<html>");
- out.println("<body>");
- out.println("====页面开始====<hr />");
- AsyncContext actx = request.startAsync();
- actx.setTimeout(30*3000);
- actx.start(new MyThread(actx));
- out.println("====页面结束====<hr />");
- out.println("</body>");
- out.println("</html>");
- out.flush();
- }
- }
- class MyThread implements Runnable{
- private AsyncContext actx;
- public MyThread(AsyncContext actx){
- this.actx = actx;
- }
- public void run(){
- try{
- Thread.sleep(5*1000); //消耗5秒
- actx.dispatch("/1.jsp");
- }
- catch(Exception e){}
- }
- }
1.jsp
- <%@ page contentType="text/html;charset=GBK" pageEncoding="GBK" session="false"%>
- <html>
- <body>
- <%
- out.println("======复杂业务方法====");
- %>
- </body>
- </html>
四、异步监听器
异步监听器用来监听异步处理事件;即“三”中讲到的知识点;
此监听器类似于ServletContextListener的机制;
只需要实现AsyncListener接口即可;
此接口有4个方法:
public void onStartAsync(AsyncEvent event)throws IOException;
public void onComplete(AsyncEvent event);
public void onTimeout(AsyncEvent event);
public void onError(AsyncEvent event);
以下是监听器实现的代码:
- package org.listener;
- import javax.servlet.annotation.*;
- import javax.servlet.http.*;
- import javax.servlet.*;
- import java.util.*;
- import java.sql.*;
- import javax.naming.*;
- import java.io.*;
- public class MyListener implements AsyncListener{
- public void onStartAsync(AsyncEvent event)throws IOException{}
- public void onComplete(AsyncEvent event){
- System.out.println("-----------------------Complete");
- }
- public void onTimeout(AsyncEvent event){
- }
- public void onError(AsyncEvent event){}
- }
在Servlet异步处理处添加:
actx.addListener(new MyListener());就可以添加监听器,每当异步处理完成时就会触发onComplete()事件,输出Complete;
五、文件上传改进API
原本文件上传时通过 common-fileupload或者SmartUpload,上传比较麻烦,在Servlet 3.0 中不需要导入任何第三方jar包,并且提供了很方便进行文件上传的功能;
注意点:
1. html中 <input type="file">表示文件上传控件;
2. form的 enctype="multipart/form-data";
3.在Servlet类前加上 @MultipartConfig
4.request.getPart()获得;
下面是一个文件上传的例子:
upload.html
- <html>
- <body>
- <form method="post" enctype="multipart/form-data" action="upload">
- <input type="file" id="file" name="file"/>
- <input type="text" id="name" name="name"/>
- <input type="submit" value="提交"/>
- </form>
- </body>
- </html>
UploadServlet.java
- package org.servlet;
- import java.io.*;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import javax.servlet.annotation.*;
- @WebServlet(name="UploadServlet" ,urlPatterns={"/upload"})
- @MultipartConfig
- public class UploadServlet extends HttpServlet{
- public void init(ServletConfig config)throws ServletException{
- super.init(config);
- }
- public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
- Part part = request.getPart("file");
- PrintWriter out = response.getWriter();
- out.println("此文件的大小:"+part.getSize()+"<br />");
- out.println("此文件类型:"+part.getContentType()+"<br />");
- out.println("文本框内容:"+request.getParameter("name")+"<br />");
- out.println(UploadUtil.getFileName(part)+"<br />");
- part.write("F:\\1."+UploadUtil.getFileType(part));
- }
- }
UploadUtil.java
由于在Servlet 3.0中很难获取上传文件的类型,因此我写了两个工具类,可以方便开发;
- /**
- * 此工具类只适用于Servlet 3.0
- * 为了弥补 Servlet 3.0 文件上传时获取文件类型的困难问题
- *
- * @author xiazdong
- */
- import javax.servlet.http.*;
- public class UploadUtil{
- public static String getFileType(Part p){
- String name = p.getHeader("content-disposition");
- String fileNameTmp = name.substring(name.indexOf("filename=")+10);
- String type = fileNameTmp.substring(fileNameTmp.indexOf(".")+1,fileNameTmp.indexOf("\""));
- return type;
- }
- public static String getFileName(Part p){
- String name = p.getHeader("content-disposition");
- String fileNameTmp = name.substring(name.indexOf("filename=")+10);
- String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("\""));
- return fileName;
- }
- }
[转]Servlet 3.0 新特性详解的更多相关文章
- Servlet 3.0 新特性详解
转自:http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/#major3 Servlet 是 Java EE 规范体系的重要组成部分,也是 ...
- 【转帖】Servlet 3.0 新特性详解
http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 ...
- Servlet 3.0 新特性详解 (转载)
原文地址:https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 新特性概述 Servlet 3.0 作为 Jav ...
- C#9.0新特性详解系列之六:增强的模式匹配
自C#7.0以来,模式匹配就作为C#的一项重要的新特性在不断地演化,这个借鉴于其小弟F#的函数式编程的概念,使得C#的本领越来越多,C#9.0就对模式匹配这一功能做了进一步的增强. 为了更为深入和全面 ...
- C# 9.0新特性详解系列之五:记录(record)和with表达式
1 背景与动机 传统面向对象编程的核心思想是一个对象有着唯一标识,表现为对象引用,封装着随时可变的属性状态,如果你改变了一个属性的状态,这个对象还是原来那个对象,就是对象引用没有因为状态的改变而改变, ...
- Android6.0 新特性详解
一 运行时权限 Android6.0 引入了一个新的应用权限模型,期望对用户更容易理解,更易用和更安全.该模型将标记为危险的权限从安装时权限(Install Time Permission)模型 移动 ...
- C# 9.0新特性详解系列之一:只初始化设置器(init only setter)
1.背景与动机 自C#1.0版本以来,我们要定义一个不可变数据类型的基本做法就是:先声明字段为readonly,再声明只包含get访问器的属性.例子如下: struct Point { public ...
- C# 9.0新特性详解系列之二:扩展方法GetEnumerator支持foreach循环
1.介绍 我们知道,我们要使一个类型支持foreach循环,就需要这个类型满足下面条件之一: 该类型实例如果实现了下列接口中的其中之一: System.Collections.IEnumerable ...
- C# 9.0新特性详解系列之三:模块初始化器
1 背景动机 关于模块或者程序集初始化工作一直是C#的一个痛点,微软内部外部都有大量的报告反应很多客户一直被这个问题困扰,这还不算没有统计上的客户.那么解决这个问题,还有基于什么样的考虑呢? 在库加载 ...
随机推荐
- MMORPG大型游戏设计与开发(part6 of net)
上一部分,讲述了一个服务器与服务器之间的通信实例,客户端其实原理大同小异.网络部分准备就暂时讲到这里,不过我们不妨再回头过来想想在这过程中有没有优化和改进的地方.这部分讲解的是以网络包代码作分析,实现 ...
- 【HTML5】嵌入另一张HTML文档、通过插件嵌入内容、嵌入数字表现形式
1.嵌入另一张HTML文档 iframe 元素允许在现有的HTML文档中嵌入另一张文档.下面代码展示了iframe元素的用法: <!DOCTYPE html> <html lang= ...
- Episode 388: Testing vs Monitoring
A user-facing bug causes search results to be unavailable for your service. Someone suggests adding ...
- hdu-5493 Queue(二分+树状数组)
题目链接: Queue Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- jmeter 函数助手里的P,property的使用
1.函数助手里的 p及property的使用 ${__P(init,2)} , ${__property(init,start,200)} 可以自行定义变量名称,及变量的默认值 P 变量名为init, ...
- eclipse 编译android程序 编译错误
windows->show view -> problems, 这个窗口的内容即为 编译错误的内容.
- Java Web开发Tomcat中三种部署项目的方法
第一种方法:在tomcat中的conf目录中,在server.xml中的,<host/>节点中添加: <Context path="/hello" docBase ...
- CastleActiveRecord在多线程 事务提交时数据库资源竞争导致更新失败的测试结果记录
CastleActiveRecord 经过测试,隔离级别: // 摘要: , , , , , , , ...
- LeetCode 01 Two Sum swift
class TwoSum { func sumTow(nums: [Int], target: Int)->[Int]{ ,]; ;x<nums.count;x++){ ;y<num ...
- 用C++和shell获取本机CPU、网卡IO、内存、磁盘等的基本信息
用C++和shell获取本机CPU.网卡.内存.磁盘等的基本信息: 由于对C++相关的函数没多少了解,但是觉得用shell反而相对简单一些: 一.shell脚本,用来辅助C++获取主机的资源使用信息 ...