在本教程中,我们创建一个经典的 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
<?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.0http://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)中。
$ 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
<?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/javaeehttp://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
<?xml version="1.0" encoding="UTF-8"?><Context path="/FormCheckBox"/>
context.xml文件是 Tomcat 的配置文件。 在文件内部,我们设置上下文路径(应用名称)。 该文件位于META-INF子目录中。
index.html
<!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 库创建的。
<input type="hidden" name="action" value="show">
这个隐藏的input标记定义了一个动作参数,该参数在控制器 Servlet 中使用。
FormFilter.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() {}@Overridepublic 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);}@Overridepublic void destroy() {}@Overridepublic void init(FilterConfig filterConfig) {}}
FormFilter在到达MyController Servlet 之前先处理请求。 它从请求中检索所有参数并进行验证。 我们需要确保值不为 null 或为空。
Map<String, String[]> params = request.getParameterMap();
我们使用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]);});
我们需要将请求参数变成请求属性。 如果请求的属性不为null或为空,则将其设置为该属性。 这些属性可供 FreeMarker 模板引擎处理。
chain.doFilter(request, response);
请求继续到映射的 servlet。
MyController.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";@Overrideprotected 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 将处理由过滤器处理的请求。
@WebServlet(name = "MyController", urlPatterns = {"/MyController"})
@WebServlet批注将具有MyController URL 模式的请求映射到MyController servlet。
@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
该请求是一个 GET 请求,因此我们以doGet()方法为其提供服务。
response.setContentType("text/html;charset=UTF-8");
使用setContentType()方法,我们设置内容类型(HTML)和字符集。
RequestDispatcher dispatcher = request.getRequestDispatcher(path);dispatcher.forward(request, response);
使用RequestDispatcher,我们将请求转发到视图。 该视图是一个 FreeMarker 模板,该模板已转换为 HTML 页面。
show.ftl
<!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 使用${}语法来获取请求属性的值。
<#if adult??>
使用#if指令,我们检查adult属性是否已设置。 ??判断左侧操作数的值是否丢失。
<p>${name!"Guest"} is adult</p>
缺少值时,!用于提供默认值。 (请记住,我们没有为空或null的参数设置属性。)如果设置了name变量,则会显示它;否则,将显示它。 否则,显示"Guest"。
unknown.ftl
<!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 Servlet 图像教程, Servlet FreeMarker JdbcTemplate教程,在 SpringBoot 中提供图像文件, Java 教程, jQuery DatePicker教程或 Stripes 教程。
