文档章节

Servlet Specification V2.4——SRV.2 The Servlet Interface

悟空太多啦
 悟空太多啦
发布于 2015/12/20 23:53
字数 2623
阅读 8
收藏 0

SRV.2 The Servlet Interface

        Servlet接口是Java Servlet API的核心抽象。所有servlet都直接或者间接地实现了这个接口,更为普遍的是,继承自一个实现了此接口的类。在Java Servlet API中有两个类,GenericServlet和HttpServlet,它们继承了Servlet接口。通常,开发者会继承HttpServlet来实现他们的servlet。

 

SRV.2.1 Request Handling Methods

        基础的Servlet接口定义了一个service方法来处理客户端的request。Service方法在container把每个request路由至某个servlet实例时被调用。
        对于web应用程序来说,并发request的处理通常需要web container开发者设计的serlvet可以在某个特定时刻于service方法内处理多线程的执行。
        一般来说,web container对于同一个servlet处理并发requests,是通过在不同线程中同时执行service方法来实现的。

 

SRV.2.1.1 HTTP Specific Request Handling Method

HttpServlet的抽象子类与它相比,增加了额外的方法,这些方法会自动被service方法调用,如:

  • doGet用来处理HTTP GET request

  • doPost用来处理HTTP POST request

 

SRV.2.2 Number of Instances

        作为servlet container的web application的deployment descriptor的一部分,servlet声明控制着container怎样提供servlet的实例。关于servlet declaration的详细信息,参见Chapter SRV.13 Deployment Descriptor。
        在非分布式环境下,servlet container对于每个servlet declaration一定只对应一个实例。然而,当servlet实现了SingleThreadModel接口,container会创建多个实例来处理重量级的request访问,并且序列化request给某个实例。
        在分布式环境下,container会为每一个JVM的每一个servlet declaration创建唯一实例。不过,如果在分布式应用中的servlet实现了SingleThreadModel接口,container会在一个JVM中创建一个servlet的多个实例。

SRV.2.2.1 Note About The Single Thread Model

        SingleThreadModel接口保证了在同一时间内只有一个县城会执行给定servlet实例的service方法。需要特别注意的是这个保证值作用于每一个servlet实例,因为container可以选择将对象保存在池中,这些对象在同一时间内可以访问多个servlet实例,比如HttpSession的实例,可以在任何时间访问多个servlet,包括哪些实现了SingleThreadModel的servlet。
        推荐开发者选择其他方式去解决这些问题而不是去实现这个接口,比如避免实例变量的使用或对存取资源的代码使用同步代码块。SingleThreadModel接口在这个版本的规范中是不被推荐使用的。

 

 

SRV.2.3 Servlet Life Cycle

        Servlet通过完整生命周期定义被管理起来,这个生命周期定义了它如何被加载和创建、被初始化,如何处理来自client的请求,如何消亡。整个生命周期可以通过javax.servlet.Servlet接口API提供的方法init,service,destroy来表示,所有Servlet都必须直接或者间接通过GenerricServlet、HttpServlet抽象类来实现javax.servlet.Servlet。

 

SRV.2.3.1 Loading and Instantiation

        Container负责装在和实例化servlet。装载和实例化的时机,有可能是在container启动时,或者直到container确定有request需要这个servlet的服务的时候。
        当servlet引擎启动后,必要的servlet类一定会被servlet container加载。Servlet容器使用普通的java类加载设备加载servlet。加载可以来自本地文件系统,远程文件系统,或者其他网络服务。
        在载入Servlet类之后,container会实例化servlet以备使用。

 

SRV2.3.2 Initialization

        在servlet对象被实例化以后,container必须在它处理来自client的request之前做好它的初始化工作。在初始化时,servlet可以读取持久化配置数据,初始化昂贵的(costly)资源(比如基于JDBC的connection),并且执行其他一次性的动作。Container初始化servlet实例,通过调用Servlet接口的init方法,这个方法以唯一的(每个servlet声明一个)ServletConfig对象为参数。这个配置对象允许servlet从web application的配置中读取name-value的初始化参数信息。此配置对象使得servlet可以访问描述了servlet runtime environment的对象(实现了ServletContext接口的)。参见SRV.3 Servlet Context获得更多关于ServletContext的信息。

SRV.2.3.2.1 Error Conditions on Initialization

        在初始化的过程中,servlet实例有可能抛出UnavailableException或者ServletException。在这种情况下,servlet一定不会被置为有效的服务,并且一定会被container释放掉。在container认为初始化工作不成功的情况下,destroy方法不会被调用。
        在初始化失败后,container可以创建一个新的实例并且对它进行初始化。异常抛出的规则是:当UnavailableException抛出的次数达到不可用次数的下限,并且container处在等待创建并初始化一个新servlet实例的时刻。

SRV.2.3.2.2 Tool Considerations

        当工具加载并且introspect web application时,静态初始化方法的触发不同于init方法的调用。开发者应该知道servlet在init方法被调用之前是不会处于有效的container runtime中的。比如:当只有静态初始化方法被调用时,servlet不应试图建立数据库连接或者EJB container。

 

SRV.2.3.3 Request Handling

        在servlet被正确地初始化后,container就可以使用它来处理客户端request了。ServletRequest类型的对象用来表示request,ServletResponse类型的对象用来表示response。它们作为参数传递给Servlet接口的service方法。
        在HTTP request的情况下,container提供的对象的类型为HttpServletRequest和HttpServletResponse。
        需要注意的是,被servlet container放置到服务中的servlet实例有可能在他的生命周期里一个request都没处理。

SRV.2.3.3.1 Multithreading Issues

        Container可以向servlet的service方法发送并发的request,为了处理这些request,servlet开发者必须为service方法中的多线程并发处理做好充分的准备。
        尽管不是推荐的,但对于开发者来说,通过实现SingleThreadModel接口来要求container保证统一时刻内只有一个reqeust线程作用于service方法,仍然是一种选择。Servlet container可以满足这种要求,通过序列化访问servlet的request,或者通过维护一个servlet实例的对象池来实现。如果web应用程序已经被标记为分布式的,而servlet又是web应用程序的一部分,那么container可以在每一个JVM(JVM that the application is distributed across)上维护一个servlet的对象池。
        对于那些没有实现SingleThreadModel接口的,如果service方法(或doGet, doPost之类那些被dispatch到HttpServlet抽象类的service方法的方法)已经使用synchronized关键字定义,container就无法使用对象池的方法,但是一定会序列化request传入service。在这种情况下,强烈建议开发者不要synchronize service方法(或dispatch到它的方法),因为这对性能有不利的影响。

SRV.2.3.3.2 Exception During Request Handling

        在处理request的过程中,Servlet有可能会抛出ServletException或者UnavailableException。
ServletException被抛出说明在处理request的过程中出现了一些错误,并且container应该采取适当的措施来清理request。
        UnavailableException意味着servlet暂时或者永久性的无法处理request。
如果UnavailableException指出的是永久性不可用,container就会把servlet从service中移除,调用它的destroy方法并且释放这个servlet实例。由于这个原因导致被container拒绝的任何request,都会返回一个SC_NOT_FOUND(404) response。
        如果UnavailableException指出的是暂时性的不可用,container会选择在这个暂时无效的时期内不给servlet发送任何request。由于这个原因导致被container拒绝的任何request,都会返回一个SC_SERVICE_UNAVAILABLE(503) response,并附带一个在无效时间结束后重试的指示标题。
        Container有可能会选择忽略暂时性无效和永久性无效的区别,并且对待所有UnavailableException作为永久性无效,因此remove servlet并且抛出UnavailableException。

SRV.2.3.3.3 Thread Safety

        Request和Response对象的实现并不被保证是线程安全的。这意味着它们只应该在request处理线程内被使用(This means that they should only be used within the scope of the request handling thread)。
        Request对象和Response对象的引用不应该交给那些在其他线程里运行的对象,因为resulting behavior有可能是非确定的。如果应用程序创建的线程使用了container管理的对象,比如request对象或者response对象,那些必须只能在servlet的service方法生命周期中使用的对象,并且这样的线程本身的生命周期存在于serlvet的service方法之内,因为在service方法结束之后访问这些对象有可能导致某些不确定的问题。请注意request对象和response对象是非线程安全的。如果那些对象被使用在多线程中,操作应当被同步或者通过包装再使用来达到线程安全。例如,同步存取request attribute的方法的调用,或者在一个线程中给response使用本地输出流。

 

SRV.2.3.4 End of Service

        Servlet container并不用在任何特定的时间段保持一个servlet处于被加载的状态。在container中,一个servlet实例的生命周期 有可能只有几毫秒,也可能 和container的生命周期一样长,或者在这之间的某个时间段。
        当container确定一个servlet应该从service中被remove掉,它就会调用Servlet接口的destroy方法来使servlet释放它用到的任何资源,并保存所有持久化状态。比如,当container想要保存内存资源,或者被停掉的时候,container就可以这么做。
        在servlet container 调用destroy方法之前,它必须使这个servlet的service方法中所有当前在运行的线程都执行完毕,或在在server限定的时间内提前完成。
        一旦servlet实例的destroy方法被调用,container就不会再把其他的request转交给servlet实例了。如果container需要再次使用这个servlet,它必须重新new一个此servlet的实例。
        在destroy方法执行完毕后,container一定会释放这个servlet实例,以使垃圾回收能够顺利执行。

© 著作权归作者所有

共有 人打赏支持
悟空太多啦
粉丝 20
博文 85
码字总数 70979
作品 1
南京
项目经理
私信 提问
spring mvc 访问静态文件的问题!请指教!

这是web—xml的配置 TalentCloud index.jsp default *.js default *.css default *.png default *.jpg default *.gif spring3mvc org.springframework.web.servlet.DispatcherServlet 1 spri......

Ales_小溪
2013/07/22
805
1
web 基础巩固——JSP基础

本文按照官网文档总结,但是有可能会理解错误,学习时尽量和其他网站进行对比,同时也欢迎指出错误,好让我及时改正 什么是JSP页面? JSP页面是一个文本文档,包含两种类型的文本:静态数据,...

SXJR
2018/11/26
0
0
servlet和filter的异同

以前总以为filter就是一种特殊servlet,所以他们在web.xml中配置因该是一样的,但是事实并非如此! 请看下文: 看Servelt规范: 引用 A filter is a reusable piece of code that can transf...

dengzhangtao
2010/12/06
0
1
web.xml中load-on-startup的作用

如下一段配置,熟悉DWR的再熟悉不过了: dwr-invoker org.directwebremoting.servlet.DwrServlet debug true 1 dwr-invoker /dwr/* 我们注意到它里面包含了这段配置:1,那么这个配置有什么作...

长平狐
2012/11/28
76
0
tomcat 5.5 部署项目报错 关于Filter的错误。。

我在tomcat7.0部署没不报错,但是再tomcat5.5就会报错。。 listener.ContextListener UrlRewriteFilter org.tuckey.web.filters.urlrewrite.UrlRewriteFilter logLevel WARN UrlRewriteFilte......

庄泽锐
2014/03/06
1K
5

没有更多内容

加载失败,请刷新页面

加载更多

Flink 幕后之内存管理

Flink 幕后之内存管理 引言 目前很多大数据处理框架,例如Hadoop、Spark、Storm、Flink等。它们都基于JVM语言开发(java or scala),运行在JVM上。为了加速合并或者排序(基于磁盘的方式通常...

moyiguke
20分钟前
2
0
风起云涌,看云计算如何赋能媒体行业?

在媒体行业的转型升级中,云计算的出现多维度促进了媒体融合,打破传统媒体行业与新媒体的界限和竞争格局,在媒体素材管理、移动端功能演进的过程中扮演着重要角色,颠覆了传统媒体新闻采编、...

七牛云
23分钟前
1
0
Mybatis开发遇到问题汇总

mybatis 中![CDATA[...]] 在今天使用Mybatis的xml文件中写sql语句时写入了一些特殊字符 如 < > & 等,但解析xml文件的时候会被转义,事实上并不希望它被转义,可以使用<![CDATA[ ]]>. 这是XML...

wangwei2134
31分钟前
1
0
参数验证 @Validated 和 @Valid 的区别

来源:blog.csdn.net/qq_27680317/article/details/79970590 整编:Java技术栈(公众号ID:javastack) Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303 规范......

Java技术栈
33分钟前
1
0
JS实现继承的几种方式

前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一。那么如何在JS中实现继承呢?让我们拭目以待。 JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如下: ...

不负好时光
37分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部