Java™ Servlet API 是主流服务器端 Java 的基本构建块,也是 Java EE 技术的一部分,例如,用于 Web 服务的 JAX - RS、JSF (JavaServer Faces) 和 JSP (JavaServer Pages)。Java servlet 也独立存在,提供一系列支持动态 Web 内容的功能。其中包括过滤器、Web 安全性以及用于处理 HTTP 请求和响应的功能。css
Servlet 4.0 是 API 的最新版本,也是 Java EE 8 规范的核心更新。正如您将在本教程中了解到的,Servlet 4.0 已为 HTTP/2 准备就绪,彻底包含服务器推送,同时还将其扩展到基于 servlet 的技术,如 JSF 2.3。本教程还介绍了新型 HttpServletMapping
接口, 它支持运行时发现 servlet 的映射 URL。html
Java servlet 是一项基于 HTTP 协议运行的服务器端技术。Servlet 等待客户端向服务器发送请求消息,而后向客户端返回响应消息。请求和响应消息由两部分组成:github
在传统交换中,客户端经过从浏览器或 curl
等另外一个 HTTP 客户端请求特定的 URL 来调用 servlet。web
在清单 1 中,请求 servlet 路径时,会激活该 servlet 。请求会被委派给相应的方法,这由 HTTP 方法来肯定。在这种状况下,因为请求是 GET
方法请求,所以经过 Java servlet 的 doGet()
方法来处理该请求。浏览器
如下交换的 servlet 路径是:http://hostname/applicationroot/showlogoservlet.缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@WebServlet("/showlogoservlet")
public class SimpleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
getServletContext()
.getRequestDispatcher("/showlogo.jsp")
.forward(request, response);
}
}
|
Servlet 4.0 的主要新功能为服务器推送和全新 API,该 API 可在运行时发现 servlet 的 URL 映射。安全
服务器推送是最直观的 HTTP/2 强化功能,经过 PushBuilder
接口在 servlet 中公开。服务器推送功能还在 JavaServer Faces API 中实现,并在 RenderResponsePhase
生命周期内调用,以便 JSF 页面能够利用其加强性能。服务器
全新 servlet 映射发现接口 HttpServletMapping
使框架可以获取有关激活给定 servlet 请求的 URL 信息。这可能对框架尤其有用,这些框架须要这一信息来运行内部工做。
在接下来的部分,我将概述服务器推送及其如何在 Java servlet 中运行,包括 JSF 2.3 中的服务器推送。我还将展现一个交换示例,重点介绍全新 servlet 映射发现功能。
服务器推送使服务器能预测客户端请求的资源需求。而后,在完成请求处理以前,它能够将这些资源发送到客户端。
要了解服务器推送的好处,能够考虑一个包含图像和其余依赖项(好比 CSS 和 JavaScript 文件)的网页。客户端发出一个针对该网页的请求。服务器而后分析所请求的页面,肯定呈现它所需的资源,并主动将这些资源发送到客户端的缓存。
在执行全部这些操做的同时,服务器仍在处理原始网页请求。客户端收到响应时,它须要的资源已经位于缓存中。
Servlet 4.0 经过 PushBuilder
接口公开服务器推送。为了可以进行访问,您须要经过调用newPushBuilder()
方法,从 HttpServletRequest
获取 PushBuilder
实例。清单 2 展现了如何获取 PushBuilder
实例。
1
2
3
4
5
6
7
8
|
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PushBuilder pushBuilder = request.newPushBuilder();
}
|
每次调用 newPushBuilder()
方法时,都将返回 PushBuilder
的新实例。若是服务器推送不可用,newPushBuilder()
将返回 null
。在某些状况下,客户端可能会为请求事务拒绝服务器推送。若是客户端没有使用安全链接,服务器推送也不会起做用。所以,务必要在对 PushBuilder
实例调用方法以前,针对 null
返回值进行测试。
顾名思义,PushBuilder
实现 Builder 模式。在这一实现过程当中,经过连接赋值方法构建推送请求。这些赋值方法经过设置 HTTP 标头、方法类型(GET
是惟一的可接受值)、查询字符串、会话 ID 和资源路径(即,将要推出资源的路径),来配置 PushBuilder
实例。
大多数来自原始 HttpServletRequest
实例的请求标头,只添加到 PushBuilder
实例中。因为正确运行服务器推送并不须要某些标头,所以不包括如下标头:
如今,让咱们看看如何构造和引起服务器推送操做。
这一路径是在向客户端推送资源以前必须设置的惟一配置。设置路径须要调用 path()
方法。该方法只能被调用一次,由于它会改变 PushBuilder
对象的路径值。该路径可能会以正斜杠(“/”)开头,指示资源路径是绝对路径;不然,该资源会被认为是相对于关联请求的上下文路径。该路径能够包含一个查询字符串,该查询字符串将与 queryString()
方法设置的任何字符串合并。
接下来,您将调用 push()
方法, 将资源推送到客户端。push()
方法用于发起与客户端的推送“对话”。在后台,会向客户端发送一个 PUSH_PROMISE
帧,相似于发送资源的意图通知。客户端能够经过发回 RST_STREAM
来拒绝资源。这种机制容许客户端保留对接收到的资源的控制。所以,客户端不会因不须要的资源或已经在缓存中的资源而过载。
如清单 3 所示,一旦得到了 PushBuilder
的实例,就能够屡次重复使用。路径和条件标头都为 null,可是全部其余字段都原样保留。这些能够在另外一个服务器推送中重复使用。
1
2
3
4
5
6
7
|
PushBuilder pushBuilder = request.newPushBuilder();
if (pushBuilder != null) {
pushBuilder.path("images/hero-banner.jpg").push();
pushBuilder.path("css/menu.css").push();
pushBuilder.path("js/marquee.js").push();
}
|
在清单 3 中,hero-banner.jpg 的路径是经过 path()
方法在 PushBuilder
实例上设置的,并经过调用 push()
推送到客户端。push()
方法是非阻塞的,且当即返回,以便后续可推送更多资源(本例中为menu.css 和 marquee.js)。
JavaServer Faces 已经将每一个页面的资源需求标识为页面呈现生命周期的一部分,因此它很是适合用于服务器推送。就开发人员而言,比较好的一方面是,您没必要为了激活此功能而煞费苦心。您能够免费升级到 JSF 2.3。
清单 4 展现了JSF 和服务器推送的集成状况。
1
2
3
4
5
6
7
8
9
10
11
|
<
h:head
>
<
h:outputStylesheet
library
=
"css"
name
=
"logo.css"
/>
<
h:outputScript
library
=
"js"
name
=
"logo.js"
/>
<
title
>JSF 2.3 ServerPush Example</
title
>
</
h:head
>
<
h:body
>
<
h:form
>
<
h:graphicImage
library
=
"images"
name
=
"logo.jpg"
/>
</
h:form
>
</
h:body
>
</
html
>
|
清单 4 中的 JSF 页面须要如下三种资源:
当 JSF 引擎正在处理和呈现页面时,这些资源将被逐个推送到客户端。这发生在 JSF 的呈现响应阶段。而后,会为每一个资源调用 ExternalContextImpl.encodeResourceURL()
方法,并向其传递资源的新 URL。从与 ExternalContext
相关联的 HttpServletRequest
实例获取新的 PushBuilder
对象。若是支持服务器推送,那么会在向客户端呈现页面以前将资源推送到客户端。
Servlet 4.0 的全新 servlet 映射发现 API 使服务器可以对 URL(可调用 servlet)执行运行时检查。例如,对 file.ext, /path
和 /path/file.ext
的请求将经过 URL 模式 /path/*
和 *.ext
激活 servlet。
HttpServletMapping
接口支持运行时发现 servlet 的映射 URL。您能够在 HttpServletRequest
实例上调用 getHttpServletMapping()
,获取接口的实例。您可使用如下方法获取有关 servlet 映射 URL 的信息:
getMatchValue()
返回部分 URI 路径,该路径会致使请求匹配。getPattern()
返回 URL 模式的 String
表示形式。getServletName()
返回 servlet 名称的 String
表示形式。getMappingMatch()
返回匹配的类型,表示为 MappingMatch
枚举值,该枚举值将为如下值之一:CONTEXT_ROOT
、DEFAULT
、EXACT
、EXTENSION
或 PATH
。清单 5 展现了四种 API 方法的实际应用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@WebServlet({"/path/*", "*.ext"})
public class ServletMapping extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
HttpServletMapping mapping = request.getHttpServletMapping();
String mapping = mapping.getMappingMatch().name();
String value = mapping.getMatchValue();
String pattern = mapping.getPattern();
String servletName = mapping.getServletName();
}
}
|
除了服务器推送和全新 HttpServletMapping
接口,Servlet 4.0 还包括少许值得注意的新增功能和变动。
Trailer
响应标头支持发送方在分块消息的末尾包含额外字段。这用于提供在发送消息主体时可能会动态生成的元数据,例如,消息完整性检查、数字签名或后期处理状态。GenericFilter
和 HttpFilter
抽象类,这些抽象类经过最低限度地实现生命周期方法 init()
和 destroy()
,简化了编写过滤器。HTTP Trailer
,支持发送方在分块消息的末尾包含额外的字段。ServletContext
接口采用了一些新方法:
addJspFile()
可将带有给定 JSP 文件的 servlet 添加到 servlet 上下文中。getSessionTimeout()
和 setSessionTimeout()
可提供对会话超时的访问权限。getRequestCharacterEncoding()
和 setRequestCharacterEncoding()
可为当前的 servlet 上下文提供访问权限,并改变默认的请求字符编码。HttpServletRequest
接口上的 isRequestedSessionIdFromUrl()
方法已被弃用。Servlet 4.0 已经发布,主要用于整合全新 HTTP/2 协议及其众多性能加强功能。PushBuilder
接口对推送到客户端的资源提供细粒度控制,使交叉实现生动有趣。例如,Jetty 9 在 PushCacheFilter
Web 过滤器中使用 PushBuilder
API 实现了服务器推送功能。此过滤器在首次请求时缓存了资源。即便仍在服务器端处理请求,它也可以将后续请求推送到客户端。
虽然 JSF 2.3 内置了服务器推送功能,但 JavaServer Pages 并无此功能。JSF 与服务器推送的集成十分有用,开发人员于是可减小对性能问题的关注,而更加着力于设计动态网页。对于想要在 JSP 中实现类似功能的开发人员,就须要使用 Web 过滤器这样的定制解决方案,例如 Jetty 9 中的 PushCacheFilter
Web 过滤器。
Alex Theedom,Servlet 4.0 入门,https://www.ibm.com/developerworks/cn/java/j-javaee8-servlet4/index.html?ca=drs-&utm_source=tuicool&utm_medium=referral