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”小节。