Servlet API是Java EE标准的一部分,自1998年正式发布2.1规范以来,一直是基于Java的企业体系结构的重要组成部分。

它是一种自以为是的API,用于服务围绕一些基本概念构建的请求/响应协议:

  • 兼容的容器 ,这是一个专用的运行时,可以是独立服务器(过去更常见),也可以是基于库的嵌入式运行时(如今更常见)。 它可以支持一次托管多个Web应用程序,并在它们之间隔离类加载。 它还可以提供管理功能,例如应用程序部署,启动,停止,资源分配,JNDI命名上下文,带有连接池的JDBC数据源,HTTP适配器,线程池等。 它基本上是Java EE功能的集中管理软件包,可以删除兼容的应用程序。
  • 一个或多个servlet ,即实现Servlet接口的类,它不是特定于HTTP的,因为Servlet规范通常是为请求/响应协议设计的。 实现接口意味着处理大多数容器已经处理过的servlet配置信息,因此扩展作为规范一部分的抽象类(如GenericServlet甚至HttpServlet )更为普遍(方便)。 除了生命周期管理外,其余要实现的方法是请求处理程序 ,当请求进入时,容器将调用该请求处理程序 ,并应为它们提供服务。 他们将通过处理从容器本身作为参数接收的可变请求和响应对象(也包括标准接口)来实现此目的,或者通过在发生某些意外情况时引发异常来进行处理,容器将根据配置方式对其进行适当的管理,例如,通过重定向到JSP页面。 它们还可以包括处理并将处理(的一部分)委托给一个全新的处理链,该处理链通过RequestDispatcher映射到一些不同的URL。 这是作为链接servlet的一种机制,主要在2.3引入过滤器之前使用。
  • 一个或多个过滤器 ,扩展了Filter接口,并且与servlet类似,不同之处在于它们支持链接 ,即它们按顺序排列,可以将请求处理(的一部分)委托给链中的下一个过滤器,并执行发布-处理完成时。 Servlet始终位于过滤器链的末尾。
  • 设置信息 ,例如请求和过滤器到HTTP请求的映射,可以通过多种方式提供,从XML描述符到类注释再到实际的初始化代码。
  • 请求服务线程 :每个请求由一个专用线程服务,该线程将运行该请求本身已映射到的整个筛选器链,并阻塞与HTTP请求和响应相关的网络I / O操作以及任何其他线程完成请求处理所需的-blocking调用。

剖析Servlet API

如果我们试图表征长期存在的Servlet API,则可以将其限定为:

  • 绝对涉及对象,因为涉及的每个概念(无论多么抽象)都已被对象化并转换为接口或类。 “ Servlet”,“ Filter”,“ RequestDispatcher”都是这种建模风格的示例。 唯一的例外是容器本身,它是幕后的无处不在的参与者,但没有唯一的表示形式,可以通过显式参与者或诸如上下文之类的次要对象进行间接处理。
  • 它是基于(面向对象)模式的 ,我们可以识别其中的许多 模式
  • 它具有状态机语义 ,它是有状态的 ,并且是可变的,因为假设请求处理过程处于某种状态(这是所有API的对象化参与者的状态的总和,包括容器),那么会有一些操作将其转换为一种新的,可部分检查的不同状态,同时禁止其他转换(例如,在提交响应后转发请求)。
  • 它是基于处理程序的,因为您(开发人员)在感觉舒适时不会请求传入的请求,而是将它们推送到您的servlet上,您不得不将它们编码为目标化的请求处理程序。
  • 它是低级的,因为它不提供路由机制,也没有建立特定的范例,例如MVC。
  • 它最初是同步产生的,因为处理程序应该在调用计算上下文(堆栈)内完成请求处理,而根本不打算延迟请求。
  • 它明确地基于线程,因为规范指出处理程序的计算上下文是servlet容器线程。 同步和基于线程的结合在一起基本上意味着Servlet API最初被设计为线程阻塞的

总而言之,它是一个非常复杂且自以为是的API,尽管它基于非常普遍的观点并且具有很长的向后兼容历史。

顺便说一句:Clojure的戒指,HTTP服务器的全新明晰和简约视图

尽管Clojure社区非常多元化,并且在每个领域都有很多非常有趣的选择,但事实上的Clojure低级,基本的网络标准框架是Ring 。

鉴于HTTP几乎是一个无状态的请求-响应协议,HTTP请求服务自然是一个非常适合于功能性,输入-输出建模风格的领域。 实际上,Ring认为HTTP请求总共具有3个具有直接关系的功能实体:

  • 处理程序是一个函数,它接收唯一具有众所周知的键名和值类型的Clojure映射作为输入,表示HTTP请求,并生成另一个Clojure映射作为其输出,该Clojure映射必须具有表示HTTP响应的特定结构(这是不过,这过于简化了,因为Ring允许返回更简单的数据结构以方便使用)。
  • 中间件是一个接收处理程序功能并生成另一个处理程序功能的功能。 因此,中间件是一种高阶函数,旨在以某种特定方式丰富任何处理程序的逻辑,例如拦截和处理文件系统请求或使用多部分预处理信息来丰富请求本身,因此类似于Servlet过滤器,尽管通过一流的函数之类的函数式编程思想使其变得更加简单。 请注意,可以通过功能组合的直接方式将中间件按特定顺序链接 ,因为将中间件应用于处理程序所获得的是另一个处理程序,然后可以将多个中间件功能应用于该处理程序。
  • 适配器是一个函数,它接收处理程序函数作为其主要输入,并且不返回任何内容。 它的目的纯粹是产生一些HTTP服务器的副作用,该HTTP服务器将使用提供的处理程序来处理请求,因此实际上是某些先前存在的(或新的)HTTP服务器技术的适配器。 它的功能接口不是标准的,因为它可以接收的输入在很大程度上取决于技术,但是一个常见的模式是许多适配器将处理程序作为第一个参数来接收,然后将与实现相关的选项映射(或其他序列)作为第一个参数。第二个。 此外,最常用的选项(例如侦听接口和端口)在大多数适配器中往往具有相同的键名。

Ring也是一种自以为是的API,并且在某些方面它并不偏离流行的概念,例如,它仍然是基于处理程序的,尽管适配器只是功能的想法使得将其用作嵌入式HTTP非常简单。完全传统应用程序的边界”; 加上它是同步的, 这非常好,因为它使代码简单易维护。 仍然需要对主题保持一种新鲜,清晰和简约的观点,尝试完全消除偶发的复杂性,并提供最少数量的正交概念,以利用功能编程思想和动态语言灵活性来简洁有效地处理领域的内在复杂性。为了这个 这种方法非常符合Clojure语言本身的精神。

请注意,Ring对执行上下文一无所知:对于某人而言,基于轻量级光纤而不是重量级线程来为其阻塞API实现适配器是完全可以的:这正是Comsat提供的,Ring的清晰和极简性极大地简化了此类编写整合。

Servlet 3.0异步

Servlet规范的Async附加示例说明了以下事实:OOP不一定简化有状态API的复杂性。 有时相反,它只能通过在表中散布状态,将其拆分并放入对象中来提供这样做的危险幻觉。

这种错觉实际上会使情况变得更糟,因为它使我们认为,开发有状态API的看似非常简单的想法确实可以在没有意外后果的情况下工作。

Servlet 3.0中 Async功能背后的“简单”思想是一种新的请求模式,即异步请求模式 。 当通过startAsync方法调用将请求切换为异步时,我们“简单地”告诉容器,只要请求处理链(过滤器和Servlet)返回并且其关联的容器线程完成,我们就根本不意味着请求处理已经完成,因此不应将响应发送回HTTP客户端。 相反,应将其保留,直到其他执行上下文发出确实已完成请求处理的信号为止,并且它将通过对startAsync调用返回的AsyncContext对象的completedispatch方法调用来complete

不用说,异步模式与先前存在的Servlet API的有状态移动部分可能存在几种交互作用:接下来,我们将对其中的一些进行交互。

异步模式下的错误处理

AsyncContext提供了注册有关请求处理进度和异常情况的侦听器的功能,但是我们将在容器线程之外运行自管理执行上下文,因此容器无法为我们捕获和处理异常。

相反, AsyncContext确实提供了一种新的处理委托形式,它将控制权转移回容器管理的线程,这就是dispatch方法的目的。 通过在请求属性中设置错误条件(和任何其他相关信息)之后使用它,并检查请求的调度程序类型,我们可以验证我们确实在处理源自异步处理流程的异常条件,然后选择重新引发异常,这一次可以依靠容器的管理能力。

这种方法有点复杂,并且基本上需要使用经过改进的前向/调度功能,事实上,这些功能实际上已被过滤器弃用。 但是它可以工作,并且能够模仿在同步设置中发生的错误处理流程。 衡量它的效率当然很有趣。

Servlet API也一直提供sendError功能,但到目前为止, 尚不清楚它是否(以及如何)以异步模式工作,即使在大多数流行的servlet容器(如Jetty和Tomcat)中,这种情况也很容易导致开放问题 。

在异步模式下过滤

Servlet 3.0规范明确禁止在与容器线程不同的执行上下文中运行过滤器链接。 此限制意味着,在请求处理链末尾的唯一处理程序(即Servlet)可以将请求置于异步模式,而预处理过滤器逻辑只能在容器的线程中执行。

这是非常不幸的,因为自从引入过滤器以来,许多流行的框架和应用程序开发人员就使用了过滤器来执行大量的请求处理,而这些请求处理可以受益于在单独的执行上下文(例如光纤)中运行而不会阻塞昂贵的容器线程。

实际上,在流行的servlet容器中有一些关于此限制的未解决问题 。

Servlet 3.1:异步HTTP I / O

Servlet 3.0可以从请求处理完成中分离容器的线程和Servlet的处理代码,但是用于读取请求和写入响应的I / O仍然是线程阻塞的。

Servlet 3.1通过setReadListenersetWriteListener方法向请求添加了异步I / O功能 (如果它们已处于异步模式)。

这套新的API有一些缺点:

  • 最多可以注册一个读和一个写侦听器。
  • 将请求置于异步模式 ,API才会强制注册它们。
  • 侦听器接口是全新的,例如,与NIO API没有任何共同点。
  • 异步API允许更有效的实现,但是这样做的方式是错误的 ,即采用卷积编程模型,而不是提供比线程更有效的执行上下文,同时保持极其有用的“阻塞”抽象。 另一方面, 异步API可以很容易地转换为高效和富于表现力的光纤阻塞 API 。

“现状”和前进的方向

许多具有实质性结构的组织已经在基于Servlet的技术上投入了大量资金,因此改变方向是一项相关的成本,需要权衡具体的好处。

他们中的一些人对此感到满意,并且不受现有缺点的影响。 至于其他的可能性,并希望将来会发生,将来的servlet规范将解决这些问题,但是servlet API是一个庞大而复杂的规范。 它还需要保持一定程度的向后兼容性,因此发布规范审查可能要花费一些时间,更不用说servlet容器正确,有效和可靠地实现它们了。

当然,可以使用诸如Ring之类的servlet替代方案,并且某些组织可以决定使用它们来支付API的费用,以提高生产力并允许构建更多可维护的代码资产。 对于新的实现而言,此成本通常会更低,而不是移植现有的实现。

如果您的组织中基于servlet的API最明显的缺点是效率或异步编程模型的缺点,那么Comsat中存在一种非常可行且成本低廉的替代方案:它将使您仍然可以使用简单的阻塞抽象和熟悉的抽象Servlet API(以及Web和DB领域中的许多其他流行的和标准的API),但具有光纤提供的效率水平。

翻译自: https://www.javacodegeeks.com/2015/04/on-servlets-and-async-servlets.html

关于Servlet和异步Servlet相关推荐

  1. servlet异步_关于Servlet和异步Servlet

    servlet异步 Servlet API是Java EE标准的一部分,自1998年正式发布2.1规范以来,一直是基于Java的企业体系结构的重要组成部分. 它是一种自以为是的API,用于服务围绕一些 ...

  2. servlet3异步_Servlet 3的异步Servlet功能

    servlet3异步 在深入了解什么是异步Servlet之前,让我们尝试了解为什么需要它. 假设我们有一个Servlet,处理时间很长,如下所示. LongRunningServlet.java pa ...

  3. Servlet 3的异步Servlet功能

    在深入了解什么是异步Servlet之前,让我们尝试了解为什么需要它. 假设我们有一个Servlet,处理时间很长,如下所示. LongRunningServlet.java package com.j ...

  4. servlet异步_如何使用异步Servlet来提高性能

    servlet异步 这篇文章将描述一种性能优化技术,该技术适用于与现代Web应用程序相关的常见问题. 如今的应用程序不再只是被动地等待浏览器发起请求,而是希望自己开始通信. 一个典型的示例可能涉及聊天 ...

  5. 如何使用异步Servlet来提高性能

    这篇文章将描述一种性能优化技术,适用于与现代Web应用程序相关的常见问题. 如今的应用程序不再只是被动地等待浏览器发起请求,而是希望自己开始通信. 一个典型的示例可能涉及聊天应用程序,拍卖行等–共同点 ...

  6. servlet3异步 例子_异步Servlet示例

    servlet3异步 例子 Async servlet was introduced in Servlet 3. It's a great way to deal with thread starva ...

  7. servlet的异步和非阻塞原理

    之前研究了下servlet的异步和非阻塞原理,看到一篇文章,下面有两个问题,顺便解答了下 servlet3异步原理与实践 Danniel 3楼 2019.05.18 21:31 请问,AsyncLon ...

  8. servlet的异步处理机制

    servlet的异步处理机制 Java servlet是大家公认的服务器端web技术的标准,包括jsp,jsf,和大量的web框架,soap,RESTful web service api ,还有新闻 ...

  9. Servlet 3特性:异步Servlet

    本文由 ImportNew - 彭秦进 翻译自 journaldev.欢迎加入翻译小组.转载请见文末要求. 理解异步Servlet之前,让我们试着理解为什么需要它.假设我们有一个Servlet需要很多 ...

最新文章

  1. python3项目-30 个惊艳的Python开源项目
  2. oracle 获取当月的1号_ORACLE认证大师(OCM)
  3. java中接口适配器实现,12.1.8 Java中的应用-AWT事件适配器(接口的适配器模式)...
  4. springBoot中启用事务管理
  5. MyEclipse使用总结——设置MyEclipse使用的Tomcat服务器
  6. hdu 1006 Tick and Tick
  7. 9 10次c语言上机作业答案,C语言第五次上机作业参考答案
  8. js解析java对象数组_js接收并转化Java中的数组对象的方法
  9. 【玩转Golang】 自定义json序列化对象时,非法字符错误原因
  10. Nhibernate 3.0 Cookbook学习笔记 利用XML映射类
  11. cdn 内容分发 资源放在更接近用户的网络边缘
  12. 2022年电工杯B题参赛历程
  13. Android实战开发--三种地图类型的设计
  14. 依据余弦相似度查找常用汉字形似字
  15. 计算机组装教程 ppt,电脑组装教程完整.ppt
  16. 【2021年度总结】:23岁的流水账
  17. Scaled Agile Framework (SAFe) 和产品管理间到底有什么关系 ?
  18. GBASE斩获2022科技赋能金融业数字化转型突出贡献奖
  19. html readme
  20. js之得到地址栏地址

热门文章

  1. SpringMVC的运行原理
  2. python自动配置文件_【python接口自动化】- ConfigParser配置文件的使用
  3. 分类器评估参数——准确度和精度的区别(足球荔枝)
  4. 405: HTTP method GET is not supported by this URL
  5. nosql和rdnms_用于SaaS和NoSQL的Jdbi
  6. js内存泄露 垃圾回收_Java内存体系结构(模型),垃圾回收和内存泄漏
  7. junit测试类叫什么名字_使用Junit测试名称
  8. mongodb上限集合_用Java创建MongoDB上限集合
  9. lambda捕获this_非捕获Lambda的实例
  10. 艾伦图灵_Java英雄:丹·艾伦