Servlet3.0新特性详解

23 篇文章 0 订阅
15 篇文章 0 订阅

Servlet3.0 新特性概述

Servlet 3.0 随着 Java EE 6 规范一起发布。Servlet3.0在Servlet2.5的基础上提供了若干新特性,能够简化 Web 应用的开发和部署。以下几个新特性比较值得称赞:

  1. 异步处理支持
    异步处理,使得servlet线程不在需要一直阻塞直到业务处理完成才能输出响应再关闭Servlet线程。异步处理在接收到请求后,Servlet线程可以将耗时的操作委派给另外一个线程来处理,自己在不生成响应的情况下返回至容器。针对业务处理比较耗时的场景,这将大大减少服务器资源的占用并且提高并发处理的速度。
  2. 新增注解支持
    Servlet3.0 新增了若干注解,简化了Servlet、过滤器、监听器的声明。 这使得web.xml部署文件不再是必选。
  3. 可插性支持
    开发者可以通过插件的方式很方便的扩充已有的web应用功能,而不需要修改原有的应用。

异步处理支持

在Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:

  1. 接收到请求,可能需要对请求携带的数据进行一些预处理;
  2. 调用业务接口的某些方法,以完成业务处理;
  3. 根据处理结果返回响应;
  4. 结束Servlet线程。
    在第二步业务处理通常是最为耗时的,业务处理一般包含各种逻辑运算、数据库操作、以及其它跨网络调用等,在此过程中,Servlet一直保持阻塞状态,直到业务方法执行完毕。在整个业务处理过程中,Servlet资源一直被占用,对于高并发的应用,这很有可能造成瓶颈。以前我们通常采用提前kill掉Servlet线程的方案来及时释放资源。

Servlet 3.0 采用异步处理支持之后的流程如下:

  1. 接收到请求,可能需要对请求携带的数据进行一些预处理;
  2. Servlet线程将请求转交给一个异步线程来执行业务,线程本身返回容器,此时Servlet还没有生产相应数据,异步线程处理完业务以后可以直接生产响应数据(异步线程拥有ServletRequest和ServletResponse对象的引用)或者将请求转发给其它的Servlet;

异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用:

web.xml启用

对于使用web.xml文件部署的项目,Servlet3.0在和标签增加了的子标签,该标签默认取值为false。如果需要启用异步处理,那么将这个标签的值设置为true即可。代码示例如下:

<servlet> 
    <servlet-name>MyServlet</servlet-name> 
    <servlet-class>com.lfa.servlet.MyServlet</servlet-class> 
    <async-supported>true</async-supported> 
</servlet>

注解方式

对于使用@WebServlet 和@WebFilter 注解的的场景,Selvlet3.0 提供了asyncSupported 属性,该属性默认值为false,如要启用异步处理支持,需要将该属性设置为true。代码示例如下:

@WebFilter(urlPatterns = "/test",asyncSupported = true) 
public class TestFilter implements Filter{...}

以下是一个简单的模拟异步处理demo

@WebServlet(urlPatterns = "/demo", asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws IOException, ServletException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        //Servlet 接收服务
        out.flush();
        //在子线程中执行业务调用,并由其负责输出响应,主线程退出
        AsyncContext ctx = req.startAsync();
        new Thread(new Executor(ctx)).start();
       //Servlet 结束
        out.flush();
    }
}
 //定义一个子线程来处理请求业务
public class Executor implements Runnable {
    private AsyncContext ctx = null;
    public Executor(AsyncContext ctx){
        this.ctx = ctx;
    }
    public void run(){
        try {
            //等待十秒钟,以模拟业务方法的执行
            Thread.sleep(10000);
            PrintWriter out = ctx.getResponse().getWriter();
            //业务处理模块
            out.flush();
            ctx.complete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Servlet3.0 还提供了一个异步监听器(SyncListenner),它可以监听四种事件:

异步线程开始
调用AsyncListener的onStartAsync(AsyncEvent event) 方法。

异步线程出错
调用 AsyncListener 的 onError(AsyncEvent event) 方法。

异步线程执行超时
调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法。

异步线程执行完毕
调用 AsyncListener 的 onComplete(AsyncEvent event) 方法。

注册 AsyncListener只需将需要注册的 AsyncListener 对象传递给 AsyncContext 对象的 addListener() 方法即可,如下所示:

AsyncContext ctx = req.startAsync(); 
ctx.addListener(new AsyncListener() { 
    public void onComplete(AsyncEvent asyncEvent) throws IOException { 
        // 做一些清理工作或者其他
    } 
    ... 
});

新增注解支持

对于Servlet 3.0 的部署描述文件 web.xml ,顶层标签 有一个 metadata-complete 属性,该属性指定当前的部署描述文件是否是完全的。如果设置为 true,则容器在部署时将只依赖部署web.xml描述文件,忽略所有的注解(同时也会跳过 web-fragment.xml 的扫描,即禁用可插性支持);如果不配置该属性,或者将其设置为 false,则表示启用注解支持(和可插性支持)。

@WebServlet

@WebServlet 将一个类声明为 Servlet,在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值):

表 1. @WebServlet 主要属性列表

属性名类型描述
nameString制定servlet的name,如果没有指定,默认使用类的名字
valueString[]等价于urlPatterns,两个属性不能同时公用
urlPatternsString[]指定Servlet对url的匹配模式,相当于<url-pattern>标签
loadOnStartupint指定Servlet的加载顺序, 相当于 <lonad-on-startup>标签
initParamsWebInitParam[]Servlet初始化参数,相当于<init-param>标签
descriptionStringservlet描述信息,相当于<description>标签
displayNameStringservlet显示名称 ,相当于<init-param>标签
asyncSupportedboolean声明是否支持异步模式,相当于<async-supported>标签

举个栗子

@WebServlet(urlPatterns = {"/demo"}, asyncSupported = true, 
loadOnStartup = -1, name = "demoServlet", displayName = "demo", 
initParams = {@WebInitParam(name = "name", value = "Linfa")} 
) 
public class SimpleServlet extends HttpServlet{}

使用注解方式声明的servlet不需要再web.xml文件中再次声明。

@WebInitParam

为servlet或者filter声明初始化参数,该注解不能单独使用,一般与@Webfilter 或 @WebFilter 一起使用。他的属性如下表所示:

nameStringN指定参数的名字,相当于 <param-name>
valueStringN指定参数的值,相当于 <param-value>
descritptionStringN指定参数的值,相当于<description>

@WebListener

声明该类为一个监听器,需要改声明的对象必须实现以下至少一个接口
ServletContextListener
ServletContextAttributeListener
ServletRequestListener
ServletRequestAttributeListener
HttpSessionListener
HttpSessionAttributeListener
webListener属相如下所示:

属性类型是否必须描述
valueStringY

举个栗子

@WebListener("这是一个简单的监听") 
public class SimpleListener implements ServletContextListener{...}

@MultipartConfig

声明Servlet对文件上传的支持,表示该Sevlet可以处理MIME类型为multipart/form-data的数据。它还提供了一些属性用于简化上传文件请求的处理,具体属性如下表所示:

属性名类型是否必须描述
fileSizeThresholdintY当数量大于该值是,内容将被写入文件。
locationStringY存放上传文件的路径
maxFileSizelongY允许上传文件的大小,默认值是-1,表示没有限制
maxRequestSizelongY针对multipart/form-data请求的最大数量,默认值是-1,表示没有限制

@WebFilter

声明一个过滤器,该注解在服务部署时被容器处理。该注解常用的属性如下表所示

属性类别是否必须描述
filterNameStringN指定过滤器的name,<filter-name>
valueString[]N相当于<urlPattems >标签,两个不能同时使用
urlPatternsString[]Y指定一组过滤器的url匹配规则 ,相当于<url-pattern>标签
servletNamesString[]N指定过滤器将应用于那些servlet,取值对应@WebServletz中的name
dispatcherTypesDispatcherTypeN指定过滤器的转发方式,具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
intiParamsWebInitParam[]N指定一组过滤器的初始化参数,相当于<init-param>标签
asyncSupportedbooleanN明过滤器是否支持异步操作模式,相当于 标签
descriptionStringN相当价于 标签
displayNameStromgN该过滤器的显示名,通常配合工具使用,相当于 标签

举个栗子

@WebFilter(servletNames = {"SimpleServlet"},filterName="SimpleFilter") 
public class LessThanSixFilter implements Filter{...}

可插性支持

Servlet3.0 可以再不修改已有的web应用的条件下,实现web应用新功能的扩充。实现方式是按照一定的规则打包成jar包,并将jar包放到 WEB-INF/lib目录下即可。

ServletContext性能增强

ServletContext对象在Servlet3.0得到了增强。现在该对象支持运行时动态部署Servlet、过滤器、监听器,以及为servlet和过滤器增加url映射配置。

HttpServletRequest 对文件上传的支持

在Servlet3.0之前,实现一个上传文件的servlet是一件非常头疼的事情。因为servlet本身并不提供这一支持,需要依赖第三方框架来实现,使用起来不是很方便。Servlet3.0 已经提供了文件上传的支持,使用方式相当简单。HttpServletRequest中提供了两个操作文件上传参数的方法:
Part getPart(String name) :获取给定name的文件
Collection <Part> getParts() :获取全部上传的文件

每一个文件用一个Part对象来表示,该接口提供了几个简单的文件处理方法,如 write() 和 delete() 等。
举个栗子

request.getPart("photo").write("/mnt/images/photo.jpg")

我们只用一行代码就实现了上传文件的保存功能,是不是棒棒的?

总结

Servlet3.0 的出现使的web开发变得更简单。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值