1.11 使用部署描述符
1.11 使用部署描述符
如在前面的例子中所见,编写和部署Servlet
都是很容易的事情。部署的一个方面是用一个路径配置Servlet
的映射。在这些范例中,是利用WebServlet
注解来将一个URL
路径映射了一个Servlet
,如下所示:
1 | @WebServlet( |
利用部署描述符是配置Servlet
应用程序的另一种方法,部署描述符的详情将在第13章“部署描述符”中探讨。部署描述符总是命名为web.xml
,并且放在WEB-INF
目录下。
程序示例
本章介绍了如何创建一个名为app01c
的Servlet
应用程序,并为它编写了一个web.xml
。
创建app01c
项目然后在src
目录下创建app01c
包,app01c
包中有SimpleServlet
和WelcomeServlet
这样两个Servlet
,还有一个要映射Servlets
的部署描述符web.xml
。
SimpleServlet类
1 | package app01c; |
WelcomeServlet类
1 | package app01c; |
部署描述文件web.xml
1 | <?xml version="1.0" encoding="UTF-8"?> |
使用部署描述符的好处
使用部署描述符有诸多好处。
- 其一,可以使用在
@WebServlet
中没有的元素,如load-on-startup
元素。使用这个元素可以在应用程序启动时就调用init
方法来实例化Servlet
,而不是在用户第一次访问该Servlet
是时调用init
方法来实例化Servlet
。如果init
方法很耗时的话,这样可以减少用户第一次访问时的等待时间。 - 使用部署描述符的另一个好处是,如果需要修改配置值,如
Servlet
路径,则不需要重新编译Servlet
类。
运行效果
现在,在部署描述符中声明SimpleServlet
和WelcomeServlet
,可以利用这些URL
来访问它们:
http://localhost:8080/app01c/simple
http://localhost:8080/app01c/welcome
浏览器显示效果如下:
关于部署以及部署描述符的更多信息,请参考第13章。
1.10 处理HTML表单
1.10 处理HTML表单
一个Web
应用程序中几乎总会包含一个或者多个HTML
表单,供用户输入值。你可以轻松地将一个HTML
表单从一个Servlet
发送到浏览器。
当用户提交表单时,在表单元素中输入的值就会被当作请求参数发送到服务器。HTML输入域(文本域、隐藏域或者密码域)或者文本区的值,会被当作字符串发送到服务器。空的输入域或者文本区会发送空的字符串。因此,**凡是有输入域名称的,ServletRequest.getParameter
方法绝对不会返回null
**。
select元素
HTML
的select
元素也向header
发送了一个字符串。如果select
元素中没有任何选项被选中,那么就会发出所显示的这个选项值。包含多个值的select元素(允许选择多个选项并且 用<select-multiple>
表示的select元素)发出一个字符串 数组,并且必须通过SelectRequest.getParameterValues
方法进 行处理。
复选框
复选框比较奇特。核查过的复选框会发送字符串”on
“到服务器。未经核查的复选框则不向服务器发送任何内容,此时ServletRequest.getParameter(fieldName)
将返回null
。
单选框
单选框将被选中按钮的值发送到服务器。如果没有选择任何按钮,将没有任何内容被发送到服务器,此时ServletRequest.getParameter(fieldName)
将返回null
。
多个同名元素的情况
如果一个表单中包含多个输入同名的元素,那么所 有值都会被提交,此时必须利用 ServletRequest.getParameterValues
方法来获取它们。 如果你使用ServletRequest.getParameter
方法的话将只返回最后一个值。
实例
下面的FormServlet
类示范了如何处理HTML
表单。它的**doGet
方法将一个Order
表单发送到浏览器。 它的doPost
方法获取到表单之中输入的值**,并将它们输出。
1 | package app01a; |
利用下面的URL
,可以调用FormServlet
:
http://localhost:8080/Hello/app01b/form
这样Servlet
容器会调用的doGet
方法,doGet()
方法会如下的HTML
表单发送给浏览器:
1 | <form method='post'> |
然后浏览器将解析这个HTML
并显示,浏览器中的显示效果如下:get
请求响应得到的表单的方法设为post
,确保当用户提交表单时,使用HTTP POST
方法提交。**而它的action
属性默认,这表示该表单会被提交给请求它时用的相同的URL**
,还是http://localhost:8080/Hello/form这个URL.
。
现在,填写表单,并单击Submit
按钮。如下图所示:
因为表单设置的方法为post
,所以我们在表单中输入的值,将通过HTTP POST
方法被发送给服务器,这 样就会调用Servlet
的doPost
方法。doPost()
方法给出响应.浏览器得到响应后显示如下:
总结
- 表单中的
action
属性若为空,则表单数据将提交给到当前URL.
- 当第一次输入
URL
是使用的是get
请求,调用的是HttpServlet
的doGet
方法.
1.9.3 HttpServletResponse接口
1.9.2 HttpServletRequest接口
1.9.2 HttpServletRequest接口
HttpServletRequest
表示HTTP
环境中的Servlet
请求。它扩展javax.servlet.ServletRequest
接口,并添加了几个方法。
HttpServletRequest接口新增方法
HttpServletRequest接口新增的部分方法如表所示:
方法 | 描述 |
---|---|
java.lang.String getContextPath() |
返回表示请求上下文的请求URI 部分。 |
Cookie[] getCookies() |
返回一个Cookie 对象数组。 |
java.lang.String getHeader(java.lang.String name) |
返回指定HTTP 标题的值。 |
java.lang.String getMethod() |
返回生成这个请求的HTTP 方法名称。 |
java.lang.String getQueryString() |
返回请求URL 中的查询字符串。 |
HttpSession getSession() |
返回与这个请求相关的会话对象。如果没有,将创 建一个新的会话对象。 |
HttpSession getSession(boolean create) |
返回与这个请求相关的会话对象。如果有,并且 create 参数为true ,将创建一个新的会话对象。 |
1.9 Http Servlets 1.9.1 HttpServlet
1.9 Http Servlets
不说全部,至少大多数应用程序都要与HTTP结合 起来使用。这意味着可以利用HTTP提供的特性。 javax.servlet.http
包是Servlet API
中的第二个包,其中包 含了用于编写Servlet
应用程序的类和接口。 javax.servlet.http
中的许多类型都覆盖
了javax.servlet
中的 类型。 下图展示了javax.servlet.http
中的主要类型。
1.9.1 HttpServlet
HttpServlet
类覆盖了javax.servlet.GenericServlet
类。 使用HttpServlet
时,还要借助分别代表Servlet
请求和Servlet
响应的HttpServletRequest
和HttpServletResponse
对象。HttpServletRequest
接口扩展 javax.servlet.ServletRequest
,HttpServletResponse
扩展 javax.servlet.ServletResponse
。 HttpServlet
覆盖GenericServlet
中的service
方法,并通过下列签名再添加一个service
方法:
1 | protected void service(HttpServletRequest request, |
新service
方法和javax.servlet.Servlet
中service
方法之间的区别
在于方法的参数列表上,前者使用HttpServletRequest
和HttpServletResponse
作为形式参数,而不是ServletRequest
和 ServletResponse
。 像往常一样,Servlet
容器调用javax.servlet.Servlet
中原始的service
方法。HttpServlet
中的编写service
方法如下:
1 | public void service(ServletRequest req, |
原始的service
方法将Servlet
容器创建的request
和response
对象分别转换成HttpServletRequest
和HttpServletResponse
类对象,并调用新的service
方法。这种转换总是会成功的,因为Servlet容器在调用Servlet的service方法时, Servlet容器总会传入一个HttpServletRequest
和一个HttpServletResponse
,预备使用HTTP。所以在通过实现 javax.servlet.Servlet
,或者扩展(继承)javax.servlet.GenericServlet
的创建的Servlet类中,也可以将传给service
方法的servletRequest
和servletResponse
分别转换成HttpServletRequest
和HttpServletResponse
。
然后,HttpServlet
中的service
方法会检验用来发送请求的HTTP方法(通过调用request.getMethod),并调 用以下方法之一:doGet
、doPost
、doHead
、doPut
、 doTrace
、doOptions
和doDelete
。这7种方法中,每一种 方法都表示一个HTTP方法。doGet和doPost是最常用 的。因此,不再需要覆盖service方法了,只要覆盖 doGet或者doPost,或者覆盖doGet和doPost即可。
总之,HttpServlet
有两个特性是GenericServlet
所不 具备的:
- 不用覆盖
service
方法,而是覆盖doGet
方法或者doPost
方法, 或者同时覆盖doGet
和doPost
。在少数情况下,还会覆盖以下任意方法:doHead
、doPut
、doTrace
、doOptions
和doDelete
。 - 使用
HttpServletRequest
和HttpServletResponse
,而不 是ServletRequest
和ServletResponse
。
1.7 ServletContext接口
1.7 ServletContext接口
ServletContext
官方叫servlet
上下文,每个应用(或者叫项目,工程,…)都会有一个ServletContext
对象与之关联.工程内部的所有Servlet
都共享这个ServletContext
对象,因此可以叫做全局应用程序共享对象- 当容器分布在多个虚拟机上时,
web
应用在所分布的每个虚拟机上都拥有一个ServletContext
实例与之关联。缺省情况下,ServletContext
不是分布式的,并且只存在于一个虚拟机上。
ServletContext的作用
通过ServletContext
可以访问应用范围
的初始化参数和属性:
Servlet中如何获取ServletContext对象
通过在ServletConfig
中调用getServletContext
方法, 可以获得ServletContext
。
操作属性方法
保存在ServletContext中的对象被称作属性,ServletContext
中的下列方法负责处理属性:
方法 | 描述 |
---|---|
java.lang.Object getAttribute(java.lang.String name) |
获取属性 |
java.util.Enumeration<java.lang.String> getAttributeNames() |
获取属性枚举 |
void setAttribute(java.lang.String name, java.lang.Object object) |
设置属性 |
void removeAttribute(java.lang.String name) |
移除属性 |
参考资料
https://baike.baidu.com/item/servletContext/6758455
https://blog.csdn.net/qq_36371449/article/details/80314024
1.6 ServletConfig接口
1.6 ServletConfig接口
接口方法
方法 | 描述 |
---|---|
String getInitParameter(String name) |
获取具有给定名称的初始化参数的值。 |
Enumeration<String> getInitParameterNames() |
以Enumeration<String> 对象的形式返回servlet 的初始化参数的名称,如果servlet 没有初始化参数,则返回空的Enumeration 。 |
ServletContext getServletContext() |
返回与所在项目关联的ServletContext 的引用。 |
String getServletName() |
返回此servlet 实例的名称。 |
接口描述
当Servlet
容器初始化Servlet
时,Servlet
容器会给 Servlet
的init
方法传入一个ServletConfig
对象。ServletConfig
封装可以通过@WebServlet
或者通过部署描述符来传给Servlet
的配置信息。这样传入的每一条信息就叫一个初始参数。一个初始参数有key
和value
两个部分。 为了从Servlet
内部获取到初始参数的值,要在 Servlet
容器传给Servlet
的init
方法的ServletConfig
中调用 getInitParameter
方法。getInitParameter
的方法签名如 下:
1 | java.lang.String getInitParameter(java.lang.String name) |
此外,getInitParameterNames
方法则是返回所有初 始参数名称的一个Enumeration
:
1 | java.util.Enumeration<java.lang.String> getInitParameterNames() |
例如,为了获取contactName
参数值,要使用下面的方法签名:
1 | String contactName = |
除getInitParameter
和getInitParameterNames
外,ServletConfig
还提供了另一个很有用的方法: getServletContext
。利用这个方法可以从Servlet
内部获取ServletContext
。关于这个对象的深入探讨,请查阅本 章1.7节。
实例
下面举一个ServletConfig
的范例,在app01a
项目中的src
目录中的app01a
包中添加 一个名为ServletConfigDemoServlet
的Servlet
。这个新的 Servlet
如下所示。
1 | package app01a; |
在@WebServlet
的initParams
属性 中,给Servlet
传入了两个初始参数(admin
和email
):
1 | @WebServlet( |
运行效果
注意这里的urlPatterns
是对于项目路径而言,/servletConfigDemo
在Hello
项目中的路径.加上项目路径,可以调用ServletConfigDemoServlet
,如下所示:
http://localhost:8080/app01a/servletConfigDemo
浏览器将会显示以下文本:
1 | Admin: Harry Taciak |
部署描述符中设置Servlet的初始化参数
另一种方法是,在部署描述符中传入初始参数。使用部署描述符设置Servlet
的初始参数,比使用@WebServlet
更容易,因为部署描述符是一个文本文件,不需要重新编译Servlet
类,就可以对它进行编辑。部署描述符将在本章后续”使用部署描述符”小节以及第13章中详细讲解。
总结
ServletConfig
操作的是Servlet
的初始化参数。
1.5 ServletResponse接口
1.5 ServletResponse接口
javax.servlet.ServletResponse
接口表示一个Servlet
响应。在调用Servlet
的service
方法前,Servlet容器
首先创建一个ServletResponse
类对象,并将它作为第二个参数传给 service
方法。ServletResponse
隐藏了向浏览器发送响应的复杂过程。
getWriter方法
在ServletResponse
中有一个getWriter
方法,它返回了一个可以向客户端发送文本的 java.io.PrintWriter
类对象。默认情况下,PrintWriter
对象使用的编码是 ISO-8859-1
编码。
**在向客户端发送响应时,大多数时候是将响应作为
HTML发送的**。因此,你必须非常熟悉
HTML`。
getOutputStream方法
还有一个方法可以用来向浏览器发送输出,它就是** getOutputStream
方法。但这个方法是用于发送二进制数据**的,因此,大多数情况使用的是getWriter
,而不是getOutputStream
。
setContentType方法
在发送任何HTML
标签前,应该先调用setContentType
方法,设置响应的内容类型,并将"text/html"
作为一个参数传入。这是在告诉浏览器, 内容类型为HTML
。在没有内容类型的情况下,大多数浏览器会默认将响应渲染成HTML
。但是,如果没有设置响应内容类型,有些浏览器就会将HTML
标签显示为普通文本。
1.4 ServletRequest接口
1.4 ServletRequest接口
对于每一个HTTP
请求,Servlet
容器都会创建一个 ServletRequest
实例,并将它作为参数传给Servlet
的service
方法。 ServletRequest
封装了关于这个请求的信息。
ServletRequest接口方法
方法 | 描述 |
---|---|
public int getContentLength() |
返回请求主体的字节数。如果不知道字节长度,这个方法就会返回-1 。 |
public java.lang.String getContentType() |
返回请求主体的MIME 类型,如果不知道类型,返回null 。 |
public java.lang.String getProtocol() |
返回这个HTTP 请求的协议名称和版本。 |
public java.lang.String getParameter(java.lang.String name) |
返回指定请求参数的值。 |
getParameter
是在ServletRequest
中最常用的方法。该方法通常用于返回HTML
表单域的值。在本章后续 的“处理表单”小节中,将会学到如何获取表单值。 getParameter
也可以用于获取查询字符串的值。例如,利用下面的URI
调用Servlet
:http://domain/context/servletName?id=123
用下面这个语句,可以通过Servlet
内部获取id
值:
1 | String id = request.getParameter("id"); |
注意,如果该参数不存在,getParameter
方法将返回null
。除了getParameter
外,还可以使用 getParameterNames
、getParameterMap
和 getParameterValues
获取表单域的名、值以及查询字符 串。这些方法的使用范例请参阅“Http Servlets
”小节。