Introduction to Java Servlets – Java Servlets简介

最后修改: 2016年 12月 16日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we will have a look at a core aspect of web development in Java – Servlets.

在这篇文章中,我们将看一下Java中Web开发的一个核心方面–Servlets。

2. The Servlet and the Container

2.Servlet和容器

Simply put, a Servlet is a class that handles requests, processes them and reply back with a response.

简单地说,Servlet是一个处理请求的类,对它们进行处理,并回复一个响应。

For example, we can use a Servlet to collect input from a user through an HTML form, query records from a database, and create web pages dynamically.

例如,我们可以使用Servlet通过一个HTML表单收集用户的输入,从数据库中查询记录,并动态地创建Web页面。

Servlets are under the control of another Java application called a Servlet Container. When an application running in a web server receives a request, the Server hands the request to the Servlet Container – which in turn passes it to the target Servlet.

Servlet是在另一个称为Servlet容器的Java应用程序的控制之下。当运行在Web服务器中的应用程序收到一个请求时,服务器将该请求交给Servlet容器–后者又将其传递给目标Servlet。

3. Maven Dependencies

3.Maven的依赖性

To add Servlet support in our web app, the javax.servlet-api dependency is required:

要在我们的Web应用程序中添加Servlet支持,需要依赖javax.servlet-api

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

The latest maven dependency can be found here.

最新的maven依赖性可以在这里找到。

Of course, we’ll also have to configure a Servlet container to deploy our app to; this is a good place to start on how to deploy a WAR on Tomcat.

当然,我们还必须配置一个Servlet容器来部署我们的应用程序;这是一个开始了解如何在Tomcat上部署WAR的好地方

4. Servlet Lifecycle

4.小程序生命周期

Let’s go through the set of methods which define the lifecycle of a Servlet.

让我们来看看定义Servlet生命周期的一系列方法。

4.1. init()

4.1.init()

The init method is designed to be called only once. If an instance of the servlet does not exist, the web container:

init方法被设计为只被调用一次。如果servlet的一个实例不存在,Web容器。

  1. Loads the servlet class
  2. Creates an instance of the servlet class
  3. Initializes it by calling the init method

The init method must complete successfully before the servlet can receive any requests. The servlet container cannot place the servlet into service if the init method either throws a ServletException or does not return within a time period defined by the Web server.

init方法必须在Servlet可以接收任何请求之前成功完成。如果init方法抛出ServletException或在Web服务器定义的时间段内没有返回,Servlet容器就不能将Servlet投入服务。

public void init() throws ServletException {
    // Initialization code like set up database etc....
}

4.2. service()

4.2.service()

This method is only called after the servlet’s init() method has completed successfully.

这个方法只有在servlet的init()方法成功完成后才会被调用.

The Container calls the service() method to handle requests coming from the client, interprets the HTTP request type (GET, POST, PUT, DELETE, etc.) and calls doGet, doPost, doPut, doDelete, etc. methods as appropriate.

容器调用service()方法来处理来自客户端的请求,解释HTTP请求类型(GET, POST, PUT, DELETE,等等)并根据情况调用doGet, doPost, doPut, doDelete,等等方法。

public void service(ServletRequest request, ServletResponse response) 
  throws ServletException, IOException {
    // ...
}

4.3. destroy()

4.3.destroy()

Called by the Servlet Container to take the Servlet out of service.

由Servlet容器调用,以使Servlet退出服务。

This method is only called once all threads within the servlet’s service method have exited or after a timeout period has passed. After the container calls this method, it will not call the service method again on the Servlet.

只有在Servlet的service方法中的所有线程都退出后,或者在超时期过后,才会调用这个方法。在容器调用此方法后,它将不再调用Servlet上的service方法。

public void destroy() {
    // 
}

5. Example Servlet

5.服务器实例

First, to change the context root from javax-servlets-1.0-SNAPSHOT to / add:

首先,将改变上下文根,从 javax-servlets-1.0-SNAPSHOT改为/添加。

<Context path="/" docBase="javax-servlets-1.0-SNAPSHOT"></Context>

under the Host tag in $CATALINA_HOME\conf\server.xml.

$CATALINA_HOME\conf\server.xml.中的Host标签下。

Let’s now set up a full example of handling information using a form.

现在让我们建立一个使用表单处理信息的完整例子

To start, let’s define a servlet with a mapping /calculateServlet which will capture the information POSTed by the form and return the result using a RequestDispatcher:

首先,让我们定义一个带有映射/calculateServlet的servlet,该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);
    }
}

As shown above, classes annotated with @WebServlet must extend the javax.servlet.http.HttpServlet class. It is important to note that @WebServlet annotation is only available from Java EE 6 onward.

如上所示,用@WebServlet注解的类必须扩展javax.Servlet.http.HttpServlet类。需要注意的是,@WebServlet注解仅从Java EE 6开始可用。

The @WebServlet annotation is processed by the container at deployment time, and the corresponding servlet made available at the specified URL patterns. It is worth noticing that by using the annotation to define URL patterns, we can avoid using XML deployment descriptor named web.xml for our Servlet mapping.

@WebServlet注解在部署时由容器处理,并在指定的URL模式下提供相应的Servlet。值得注意的是,通过使用注解来定义URL模式,我们可以避免在Servlet映射中使用名为web.xml的XML部署描述符。

If we wish to map the Servlet without annotation, we can use the traditional web.xml instead:

如果我们希望在没有注释的情况下映射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>

Next, let’s create a basic HTML form:

接下来,让我们创建一个基本的HTMLform

<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>

Finally – to make sure everything’s working as expected, let’s also write a quick test:

最后–为了确保一切按预期工作,我们也来写一个快速测试。

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 and JSP

6.Servlet、HttpServlet和JSP

It’s important to understand that the Servlet technology is not limited to the HTTP protocol.

重要的是要明白,Servlet技术并不局限于HTTP协议。

In practice it almost always is, but Servlet is a generic interface and the HttpServlet is an extension of that interface – adding HTTP specific support – such as doGet and doPost, etc.

在实践中,它几乎总是如此,但Servlet是一个通用接口,而HttpServlet是该接口的扩展–添加HTTP特定支持–如doGetdoPost,等等。

Finally, the Servlet technology is also the main driver a number of other web technologies such as JSP – JavaServer Pages, Spring MVC, etc.

最后,Servlet技术也是其他一些网络技术的主要驱动力,如JSP – JavaServer Pages、Spring MVC等。

7. Conclusion

7.结论

In this quick article, we introduced the foundations of Servlets in a Java web application.

在这篇快速文章中,我们介绍了Servlets在Java网络应用中的基础。

The example project can be downloaded and run as it is as a GitHub project.

该示例项目可以作为GitHub项目下载并运行。