本节书摘来异步社区《java ee 7精粹》一书中的第2章,第2.1节,作者:【美】arun gupta,更多章节内容可以访问云栖社区“异步社区”公众号查看。
servlet是一种托管在servlet容器的web组件,可以生成动态内容。web客户端使用请求/响应模式与servlet交互。servlet容器负责servlet的生命周期,接收请求和发送响应,并执行这一过程中所需的编码/解码。
servlet类是使用@webservlet注解并继承javax.servlet.http.httpservlet类的pojo。
下面是一个servlet定义的示例:

默认的servlet名是完全限定的类名,可使用注解的name属性覆盖。servlet可以部署在多个url:
@webinitparam可以用于指定servlet的初始化参数:
httpservlet接口为每个http请求:get、post、put、delete、head、options和trace的处理,提供了一个doxxx方法。通常情况下,开发人员只关注覆盖doget和dopost方法。下面的代码显示了处理get请求的servlet。
在这段代码中:
httpservletrequest和httpservletresponse捕获web客户端的请求/响应。
可以从httpservletrequest中获取请求参数,http头,请求路径的不同部分如主机名称、端口和上下文,以及更多的信息。
同时,可以发送和检索http cookie。开发人员负责填充httpservletresponse,然后容器将捕获的http头信息或体消息发送给客户端。
这段代码显示了servlet接收的http get请求是如何显示一个简单的响应给客户端的。
请求参数可以由get和post请求传递。在一个get请求中,这些参数通过键/值对形式的查询字符串来传递。下面是一个使用请求参数调用前述servlet的url示例:
在一个post请求中,请求参数也可以通过编码在请求体的post数据中来传递。get和post的请求参数都可以从httpservletrequest中获得:
每次请求的请求参数可以不同。
初始化参数也被称为init params,可以在servlet上定义来存储启动和配置信息。如前所述,@webinitparam用于为一个servlet指定初始化参数:
可以通过覆盖javax.servlet.servlet接口的生命周期调用方法init、service和destroy来操控servlet的默认行为。通常情况下,数据库连接的初始化发生在init方法中,数据库连接的释放发生在destroy方法中。
还可以使用web应用程序的部署描述文件web.xml中的servlet和servlet-mapping元素定义servlet。如下,在web.xml中定义了一个account servlet:
注解配置的方式覆盖了大部分的常见用例,因此web.xml不是必需的。但某些情况下web.xml是必需的,例如指定servlet的顺序只能使用web.xml中完成。
如果web.xml中的metadata-complete元素的值设置为true,那么类中定义的注解将不被处理:
在部署描述文件web.xml中定义的值会覆盖使用注解定义的值。
servlet被打包在一个以.war文件形式存在的web应用程序中。多个servlet可以被打包在一起,他们共享一个servlet上下文。servlet上下文类servletcontext中提供了有关servlet运行环境的详细信息,用于与容器通信。例如,读取封装在web应用程序中的资源、写入日志文件或者分派一个请求。
可以从httpservletrequest中获得servletcontext实例:
为实现session跟踪,servlet可以发送一个名为jsessionid的http cookie到客户端。这个cookie可以标记为httponly,从而确保cookie不会暴露给客户端的脚本代码,因此有助于减轻多种跨站脚本的攻击:
此外,servlet可以使用url rewriting作为session跟踪的基础。servletcontext. getsessioncookieconfig方法返回一个sessioncookieconfig实例,该实例可以用于配置cookie的不同属性。
httpsession接口用于查看和操控有关session的信息,比如session标识符和创建时间,并且可以将对象绑定到session中。如下,创建了一个新的session对象:
<code>session.setattribute</code>和<code>session.getattribute</code>方法用于将对象绑定到session中。
如果需要进一步处理一个请求,<code>servlet</code>可以将该请求转发(forward)到另一个<code>servlet</code>中。使用<code>requestdispatcher</code>可以将请求分派到不同的资源中,<code>requestdispatcher</code>实例可以从<code>httpservletrequest.getrequestdispatcher</code>方法或者<code>servletcontext. getrequestdispatcher</code>方法中获得。前者可以接受相对路径,而后者可以接受当前上下文的相对路径:
在这段代码中,bank代指部署在相同上下文中另一个<code>servlet</code>。
<code>servletcontext.getcontext</code>方法可以获得不同上下文的<code>servletcontext</code>实例。从中可以获得<code>requestdispatcher</code>实例来分派该上下文的请求。
可以通过调用<code>httpservletresponse.sendredirect</code>方法重定向(redirect)一个<code>servlet</code>响应到另一个资源。这个临时的重定向响应到客户端,然后客户端发出一个新的请求到指定的url。注意,在本例中,原始请求的对象在重定向的url中不可用。重定向可能会稍微慢一些,因为它需要客户端发送两次请求,而转发(forward)是在容器内进行的:
在这里,响应重定向到<code>http://example.com/someotherservlet</code>。注意,这个url可以是不同的主机/端口,并且可以向容器发送相对或绝对路径。
除了使用<code>@webservlet</code>和<code>web.xml</code>声明<code>servlet</code>,也可以使用<code>servletcontext.addservlet</code>方法以编程方式来定义。该方法可以编码在<code>servletcontainerinitializer.onstartup</code>方法或者<code>servletcontextlistener.contextinitialized</code>方法中。event listeners一节有更多的描述。
当应用程序启动时,使用给定的<code>servletcontext</code>调用<code>servletcontainerinitializer. onstartup</code>方法。<code>addservlet</code>方法返回<code>servletregistration.dynamic</code>,用于创建url映射、设置安全角色、设置初始化参数和管理其他配置项: