Java Servlet简介
1. 概述
在本文中,我们将了解 Java 中 Web 开发的一个核心方面——Servlet。
2. Servlet 和容器
简而言之,Servlet 是一个处理请求、处理请求并返回响应的类。
例如,我们可以使用 Servlet 通过 HTML 表单收集用户的输入,从数据库中查询记录,以及动态创建网页。
Servlet 受另一个称为**Servlet 容器的 Java 应用程序的控制。**当在 Web 服务器中运行的应用程序接收到请求时,服务器将请求交给 Servlet 容器——后者又将其传递给目标 Servlet。
3. Maven依赖
要在我们的 Web 应用程序中添加 Servlet 支持,需要javax.servlet-api依赖项:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
最新的 maven 依赖可以在这里 找到。
当然,我们还必须配置一个 Servlet 容器来部署我们的应用程序;这里 了解如何在 Tomcat 上部署 WAR。
4. Servlet 生命周期
让我们看一下定义 Servlet 生命周期的方法集。
4.1. init()
init方法被设计为只被调用一次。如果 servlet 的实例不存在,则 Web 容器:
- 加载 servlet 类
- 创建 servlet 类的实例
- 通过调用init方法对其进行初始化
init方法必须成功完成,servlet 才能接收任何请求。如果init方法抛出ServletException或未在 Web 服务器定义的时间段内返回,则 servlet 容器无法将 servlet 投入使用。
public void init() throws ServletException {
// Initialization code like set up database etc....
}
4.2. service()
此方法仅在 servlet 的*init()*方法成功完成后调用。
Container 调用service()方法来处理来自客户端的请求,解释 HTTP 请求类型(GET、POST、PUT、DELETE等)并根据需要调用doGet、doPost、doPut、doDelete等方法。
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
// ...
}
4.3. destroy()
由 Servlet 容器调用以使 Servlet 停止服务。
只有在 servlet 的服务方法中的所有线程都退出或经过超时时间之后,才会调用此方法。容器调用该方法后,不会在Servlet上再次调用该服务方法。
public void destroy() {
//
}
5. Servlet示例
请参考Tomcat根目录下部署应用 将javax-servlets-1.0-SNAPSHOT上下文根更改为 /:
<Context path=”/” docBase=”javax-servlets-1.0-SNAPSHOT”></Context>
在 Host 下 $CATALINA_HOME\conf\server.xml 中的标记
现在让我们设置一个使用表单处理信息的完整示例。
首先,让我们定义一个带有映射*/calculateServlet*的 servlet ,它将捕获表单发布的信息并使用RequestDispatcher 返回结果:
@WebServlet(name = "FormServlet", urlPatterns = "/calculateServlet")
public class FormServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String height = request.getParameter("height");
String weight = request.getParameter("weight");
try {
double bmi = calculateBMI(
Double.parseDouble(weight),
Double.parseDouble(height));
request.setAttribute("bmi", bmi);
response.setHeader("Test", "Success");
response.setHeader("BMI", String.valueOf(bmi));
request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response);
} catch (Exception e) {
request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response);
}
}
private Double calculateBMI(Double weight, Double height) {
return weight / (height * height);
}
}
如上所示,使用@WebServlet 注解的类必须扩展javax.servlet.http.HttpServlet 类。需要注意的是,*@WebServlet *注解仅从 Java EE 6 开始可用。
@WebServlet 注解在部署时由容器处理,相应的 servlet 在指定的 URL 模式下可用。值得注意的是,通过使用注解定义 URL 模式,我们可以避免使用名为web.xml的 XML 部署描述符来进行 Servlet 映射。
如果我们希望映射没有注解的 Servlet,我们可以使用传统的web.xml代替:
<web-app ...>
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>com.root.FormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/calculateServlet</url-pattern>
</servlet-mapping>
</web-app>
接下来,让我们创建一个基本的 HTML form:
<form name="bmiForm" action="calculateServlet" method="POST">
<table>
<tr>
<td>Your Weight (kg) :</td>
<td><input type="text" name="weight"/></td>
</tr>
<tr>
<td>Your Height (m) :</td>
<td><input type="text" name="height"/></td>
</tr>
<th><input type="submit" value="Submit" name="find"/></th>
<th><input type="reset" value="Reset" name="reset" /></th>
</table>
<h2>${bmi}</h2>
</form>
最后——为了确保一切都按预期工作,让我们也写一个快速测试:
public class FormServletLiveTest {
@Test
public void whenPostRequestUsingHttpClient_thenCorrect()
throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost method = new HttpPost(
"http://localhost:8080/calculateServlet");
List<BasicNameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("height", String.valueOf(2)));
nvps.add(new BasicNameValuePair("weight", String.valueOf(80)));
method.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse httpResponse = client.execute(method);
assertEquals("Success", httpResponse
.getHeaders("Test")[0].getValue());
assertEquals("20.0", httpResponse
.getHeaders("BMI")[0].getValue());
}
}
6. Servlet、HttpServlet和JSP
重要的是要了解Servlet 技术不仅限于 HTTP 协议。
在实践中几乎总是如此,但*Servlet 是一个通用接口,而HttpServlet 是该接口的扩展——添加了 HTTP 特定的支持——例如doGet和doPost*等。
最后,Servlet 技术也是许多其他 Web 技术的主要驱动力,例如JSP – JavaServer Pages 、 Spring MVC 等。