# Java Servlet 复选框教程

> 原文： [http://zetcode.com/articles/javaservletcheckbox/](http://zetcode.com/articles/javaservletcheckbox/)

在本教程中，我们创建一个经典的 Web 应用，该应用从 HTML 复选框中读取一个值。 表单值通过过滤器类进行验证。 使用 FreeMarker 模板创建视图。 该 Web 应用是使用 Java Servlet 创建的，并部署在 Tomcat 服务器上。

Servlet 是 Java 类，可响应特定类型的网络请求-最常见的是 HTTP 请求。 Servlet 用于实现 Web 应用。 它们在 Tomcat 或 Jetty 之类的 servlet 容器中运行。 在现代 Java Web 开发中，程序员使用在 Servlet 之上构建的框架。

Java 过滤器是一个对象，它对对资源（servlet 或静态内容）的请求，或对资源的响应，或两者都执行过滤任务。 它用于执行认证，审核，日志记录，数据加密或数据验证之类的任务。

FreeMarker 是 Java 编程语言的模板引擎。 模板以 FreeMarker 模板语言（FTL）编写。 在 Web 应用中使用模板来创建 UI。

Apache Tomcat 是由 Apache 软件基金会（ASF）开发的开源 Java Servlet 容器。 它是最受欢迎的 Java Web 服务器。

Bootstrap 是 HTML，CSS 和 JS 框架，用于在 Web 上开发响应式，移动优先项目。 它包含用于印刷，表单，按钮，导航和其他界面组件的 HTML 和 CSS 设计模板，以及可选的 JavaScript 扩展。

## 应用

以下 Web 应用具有一个简单的 Web 表单，该表单包含一个复选框和一个输入文本。 值将发送到 Web 应用的控制器，该控制器是 Java servlet。 在请求到达控制器之前，将在 Java 过滤器中验证这些值。 最后，这些值显示在 HTML 文件中，该文件是用 FreeMarker 模板构建的。 FreeMarker 将 HTML 与数据结合在一起。

`pom.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>FormCheckBox</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>FormCheckBox</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

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

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.25-incubating</version>
        </dependency>             

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

```

`javax.servlet-api`依赖项是用于构建 Java Servlet 的库。 `freemarker`工件用于 FreeMarker 模板引擎。 `maven-war-plugin`收集 Web 应用的所有工件依赖项，类和资源，并将它们打包到 Web 应用存档（WAR）中。

```java
$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── filter
    │   │           │   └── FormFilter.java
    │   │           └── web
    │   │               └── MyController.java
    │   ├── resources
    │   └── webapp
    │       ├── index.html
    │       ├── META-INF
    │       │   └── context.xml
    │       └── WEB-INF
    │           ├── template
    │           │   ├── show.ftl
    │           │   └── unknown.ftl
    │           └── web.xml
    └── test
        └── java

```

用`tree`命令显示项目目录结构。

`web.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

    <servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>

        <init-param>
            <param-name>TemplatePath</param-name>
            <param-value>/WEB-INF/template/</param-value>
        </init-param>
        <init-param>
            <param-name>NoCache</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>ResponseCharacterEncoding</param-name>
            <param-value>fromTemplate</param-value>
        </init-param>
        <init-param>
            <param-name>ExceptionOnMissingTemplate</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>incompatible_improvements</param-name>
            <param-value>2.3.25-incubating</param-value>
        </init-param>
        <init-param>
            <param-name>template_exception_handler</param-name>
            <param-value>html_debug</param-value>
        </init-param>
        <init-param>
            <param-name>template_update_delay</param-name>
            <param-value>0 s</param-value>
        </init-param>
        <init-param>
            <param-name>default_encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>output_encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>locale</param-name>
            <param-value>en_US</param-value>
        </init-param>
        <init-param>
            <param-name>number_format</param-name>
            <param-value>0.##########</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>freemarker</servlet-name>
        <url-pattern>*.ftl</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>FreeMarker MVC Views</web-resource-name>
            <url-pattern>*.ftl</url-pattern>
        </web-resource-collection>
        <auth-constraint>
        </auth-constraint>
    </security-constraint> 
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

```

在`web.xml`文件中，我们设置了 FreeMarker 模板。 它通过`freemarker.ext.servlet.FreemarkerServlet`起作用。 模板目录设置为`/WEB-INF/template/`。

`context.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/FormCheckBox"/>

```

`context.xml`文件是 Tomcat 的配置文件。 在文件内部，我们设置上下文路径（应用名称）。 该文件位于`META-INF`子目录中。

`index.html`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Check box</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <div class="container">
            <div class="form">

                <form action="MyController">

                    <input type="hidden" name="action" value="show">

                    <div class="form-group">
                        <label>Name:</label>    
                        <input type="text" name="name" class="form-control">
                    </div>

                    <div class="checkbox">
                        <label><input type="checkbox" name="adult">Adult</label>    
                    </div>

                    <button type="submit" class="btn btn-default">Submit</button>

                </form>
            </div>
        </div>
    </body>
</html>

```

`index.html`文件是我们应用的主页。 它包含一个带文本输入和复选框的 HTML 表单。 页面外观是使用 Bootstrap 库创建的。

```java
<input type="hidden" name="action" value="show">

```

这个隐藏的`input`标记定义了一个动作参数，该参数在控制器 Servlet 中使用。

`FormFilter.java`

```java
package com.zetcode.filter;

import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter(filterName = "FormFilter", servletNames = {"MyController"})
public class FormFilter implements Filter {

    public FormFilter() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        Map<String, String[]> params = request.getParameterMap();

        params.keySet().stream().forEach(key -> {

            String value = params.get(key)[0];

            if (key != null && ! value.trim().isEmpty())
                request.setAttribute(key, params.get(key)[0]);

        });

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) {

    }
}

```

`FormFilter`在到达`MyController` Servlet 之前先处理请求。 它从请求中检索所有参数并进行验证。 我们需要确保值不为 null 或为空。

```java
Map<String, String[]> params = request.getParameterMap();

```

我们使用`getParameterMap()`方法从请求中获取所有参数。

```java
params.keySet().stream().forEach(key -> {

    String value = params.get(key)[0];

    if (key != null && ! value.trim().isEmpty())
        request.setAttribute(key, params.get(key)[0]);

});

```

我们需要将请求参数变成请求属性。 如果请求的属性不为`null`或为空，则将其设置为该属性。 这些属性可供 FreeMarker 模板引擎处理。

```java
chain.doFilter(request, response);

```

请求继续到映射的 servlet。

`MyController.java`

```java
package com.zetcode.web;

import com.zetcode.util.Validate;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "MyController", urlPatterns = {"/MyController"})
public class MyController extends HttpServlet {

    private static final String SHOW_ACTION = "show";
    private static final String SHOW_VIEW = "show.ftl";
    private static final String UNKNOW_VIEW = "unknown.ftl";

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String action = request.getParameter("action");

        String path = UNKNOW_VIEW;

        if (SHOW_ACTION.equals(action)) {

            path = SHOW_VIEW;
        } 

        response.setContentType("text/html;charset=UTF-8");

        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }
}

```

`MyController` Servlet 将处理由过滤器处理的请求。

```java
@WebServlet(name = "MyController", urlPatterns = {"/MyController"})

```

`@WebServlet`批注将具有`MyController` URL 模式的请求映射到`MyController` servlet。

```java
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

```

该请求是一个 GET 请求，因此我们以`doGet()`方法为其提供服务。

```java
response.setContentType("text/html;charset=UTF-8");

```

使用`setContentType()`方法，我们设置内容类型（HTML）和字符集。

```java
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.forward(request, response);

```

使用`RequestDispatcher`，我们将请求转发到视图。 该视图是一个 FreeMarker 模板，该模板已转换为 HTML 页面。

`show.ftl`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Show page</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
<body>

    <#if adult??>
        <p>${name!"Guest"} is adult</p>
    <#else>
        <p>${name!"Guest"} is minor</p>
    </#if>

</body>
</html>

```

这是`show.ftl`模板。 两个属性传递给模板：`adult`和`name`。 FreeMarker 使用`${}`语法来获取请求属性的值。

```java
<#if adult??>

```

使用`#if`指令，我们检查`adult`属性是否已设置。 `??`判断左侧操作数的值是否丢失。

```java
<p>${name!"Guest"} is adult</p>

```

缺少值时，`!`用于提供默认值。 （请记住，我们没有为空或`null`的参数设置属性。）如果设置了`name`变量，则会显示它；否则，将显示它。 否则，显示`"Guest"`。

`unknown.ftl`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Unknow action</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
<body>

    <p>Unknown action</p>

</body>
</html>

```

这是`unknown.ftl`模板文件。

在本教程中，我们已将数据从 HTML 表单发送到 Java servlet。 该表单包含一个输入标签和一个复选框。 请求参数已在 Java 过滤器中经过验证，并转换为请求属性，并发送到 FreeMarker 模板进行显示。

您可能也对以下相关教程感兴趣： [Java `RequestDispatcher`](/java/requestdispatcher/) ， [Java Servlet 图像教程](/articles/javaservletimage/)， [Servlet FreeMarker `JdbcTemplate`教程](/articles/servletfreemarker/)，[在 SpringBoot 中提供图像文件](/articles/springbootserveimage/)， [Java 教程](/lang/java/)， [jQuery DatePicker教程](/articles/jquerydatepicker/)或 [Stripes 教程](/java/stripes/)。