Servlet 是Java Web开发的规范,作为后台开发人员有必要好好理解。
Servlet是什么?
servlet是基于JavaTM技术的Web组件,由容器管理,可以生成动态内容。与其他基于Java技术的组件一样,servlets是独立于平台的Java类,它们被编译成平台无关的字节码,可以动态地加载到支持Java技术的Web服务器中并由其运行。容器,有时称为servlet引擎,是提供servlet功能的Web服务器扩展。servlet通过servlet容器实现的请求/响应范式与Web客户机交互。
Servlet 容器是什么?
servlet容器是Web服务器或应用程序服务器的一部分,它提供网络服务,通过这些服务发送请求和响应,解码基于MIME的请求,并格式化基于MIME的响应。servlet容器还包含并管理servlet的整个生命周期。
servlet容器支持安装到服务器上,也支持构建到应用程序中。
所有servlet容器都必须支持HTTP作为请求和响应的协议,但可能支持基于请求/响应的其他协议,如HTTPS(HTTP over SSL)。
JavaSE8是底层Java平台的最低版本,必须用它来构建servlet容器。
servlet与其他技术的比较?
在功能上,servlet提供了比公共网关接口(Common Gateway Interface,CGI)程序更高级别的抽象,但比JavaServer Faces等web框架提供的抽象级别更低。
与其他服务器扩展机制相比,servlet具有以下优势:
1、它们通常比CGI脚本快得多,因为使用了不同的处理模型。
2、它们使用许多Web服务器支持的标准API。
3、它们具有Java编程语言的所有优点,包括易用性开发和平台独立性。
4、他们可以访问Java平台上可用的大量api。
Servlet接口
Servlet接口是JavaServletAPI的中心抽象。所有servlet要么直接实现该接口,要么更常见地通过扩展实现该接口的类来实现。JavaServletAPI中实现Servlet接口的两个类是GenericServlet和HttpServlet。大多数情况下,开发人员都会扩展HttpServlet来实现他们的servlet。
Servlet请求处理方法
基本Servlet接口定义了一个用于处理客户机请求的服务(service)方法。对于servlet容器路由到servlet实例的每个请求,都会调用此方法。
处理对Web应用程序的并发请求通常要求Web开发人员设计servlet来处理在特定时间在服务(service)方法中执行的多个线程。
通常,Web容器通过在不同线程上并发执行服务方法来处理对同一servlet的并发请求。
HttpServlet抽象子类在基本Servlet接口之外添加了其他方法,这些方法由HttpServlet类中的服务方法自动调用,以帮助处理基于HTTP的请求。这些方法包括:
• doGet doPost doPut doDelete doHead doOptions
通常在开发基于HTTP的Servlet时,Servlet开发人员只关心doGet和doPost方法。其他方法被认为是非常熟悉HTTP编程的程序员使用的方法。
HttpServlet接口定义getLastModified方法以支持条件GET操作。条件GET操作仅当资源在指定时间后被修改时才请求发送该资源。在适当的情况下,这种方法的实现可以帮助有效地利用网络资源。
Servlet生命周期
通过Servlet接口可知,Servlet包含初始化,提供服务,摧毁等过程,如下代码所示:
javax.servlet.Servlet#initjavax.servlet.Servlet#servicejavax.servlet.Servlet#destroy
提供服务service方法其实有两种情况,一种是同步处理,另外一种是异步处理,本文将讲解同步处理请求的生命周期,异步情况下文再进行分析:
1、Servlet容器实例化Servlet对象(可能是容器启动就实例化,也可能是延迟到需要处理对应请求的时候实例化)
2、初始化servlet javax.servlet.Servlet#init ServletConfig参数,允许访问系统环境配置,和ServletContext对象
特殊情况:可能存在初始化失败的情况,抛出UnavailableException ServletException,在这种情况下,servlet不能放在活动服务中,必须由servlet容器释放。不调用destroy方法,因为它被视为初始化不成功。
初始化失败后,容器可能会实例化和初始化新实例。此规则的例外情况是,当不可用异常指示不可用的最短时间时,容器必须等待该时间段过去,然后才能创建和初始化新的servlet实例。
注意事项:当工具加载和内省Web应用程序时,静态初始化方法的触发与init方法的调用是不同的。在调用servlet接口的init方法之前,开发人员不应假定servlet在活动容器运行时中。例如,当只调用静态(类)初始化方法时,servlet不应尝试建立到数据库或企业JavaBeansTM容器的连接。
3、处理请求 在正确初始化servlet之后,servlet容器可以使用它来处理客户机请求,请求由ServletRequest类型的请求对象表示。servlet通过调用ServletResponse类型的提供对象的方法来填写对请求的响应。这些对象作为参数传递给Servlet接口的服务(service)方法。对于HTTP请求,容器提供的对象属于HttpServletRequest和HttpServletResponse类型。
3.1 多线程问题:一个servlet容器可能并发调用servlet的service方法
为了处理请求,Servlet开发人员必须为服务方法中的多个线程的并发处理做好充分的准备。
尽管不建议这样做,但开发人员的另一种选择是实现SingleThreadModel接口,该接口要求容器保证在服务方法中一次只有一个请求线程。servlet容器可以通过序列化servlet上的请求或维护servlet实例池来满足此需求。如果servlet是已标记为可分发的Web应用程序的一部分,那么容器可以在应用程序分布的每个JVM中维护一个servlet实例池。
对于没有实现SingleThreadModel接口的servlet,如果服务方法(或HttpServlet抽象类的服务方法被分派到的doGet或doPost等方法)已用synchronized关键字定义,则servlet容器不能使用实例池方法,而必须通过实例池方法序列化请求。强烈建议开发人员在这些情况下不要同步服务方法(或分派给它的方法),因为这会对性能产生不利影响。
3.2 处理过程中异常:ServletException 或者 UnavailableException
UnavailableException分为临时和永久性不可用:
如果不可用异常指示永久不可用,则servlet容器必须从服务中删除servlet,调用其destroy方法,然后释放servlet实例。容器因该原因拒绝的任何请求都必须返回SC_NOT_FOUND(404)响应。
如果不可用异常指示临时不可用,容器可以选择在临时不可用期间不通过servlet路由任何请求。任何服务请求都必须在服务不可用的情况下被拒绝,并在服务期间返回一个服务不可用的服务(SC_SERVICE_UNAVAILABLE 503)。
容器可以选择忽略永久性不可用性和临时性不可用性之间的区别,并将所有不可用性异常视为永久性的,从而移除从服务抛出任何不可用异常的servlet。
javax.servlet.Servlet#service
Servlet服务完成,实例销毁。
javax.servlet.Servlet#destroy
到此,本篇Servlet规范理解就到这了,本文介绍了Servlet和Servlet容器,介绍了Servlet的接口,分析了Servlet异步处理请求的生命周期等内容,但是Servlet规范还有很多内容,后面将陆续更新。