本资料是“企业发展概论”系列的一部分。往期文章:
您是否已经知道如何编写在控制台上显示文本的 Java 应用程序,但您仍然不知道如何创建您的第一个 Web 应用程序?太好了,让自己舒服。在本文中,我们将熟悉 servlet 并编写一个您可以向朋友吹嘘的应用程序,而无需向他们发送 JAR 文件,也无需强迫他们下载 Java。让我们编写一个简单的Web 应用程序。如果您还不熟悉 Web 开发中使用的方法,我建议您先阅读“企业开发简介”系列中的第一篇文章。

什么是小服务程序?
首先,让我们弄清楚什么是 servlet 以及为什么您会如此频繁地听到它们。Java Servlet API是一种旨在在服务器上实现的标准化 API。它根据请求-响应方案与客户端进行交互。servlet是一个可以接收来自客户端的请求并将响应返回给客户端的类。事实上,servlet 正是我们用来在 Java 中创建客户端-服务器体系结构的构建块。您可能还记得我们已经在本系列的另一篇文章中讨论过该架构。我们不会拐弯抹角:让我们立即编写一些代码。创建 Web 应用程序所需的条件
为了在使用 Java servlet 时获得最大便利,您需要 IntelliJ IDEA Ultimate Edition。它是付费产品,但您可以激活 30 天试用版或使用始终免费的抢先体验版。此外,安装 Apache Tomcat — 我们应用程序的服务器。Tomcat 是一个 servlet 容器:它处理传入的请求并将它们传递给我们的应用程序。在此处下载 Tomcat 。让我们创建我们的第一个 Web 应用程序
如果一切就绪,创建一个 Maven 项目。如果您不熟悉 Maven,请查看上一篇文章。让我们开始!-
在pom.xml中添加javax.servlet-api依赖,指定WAR打包:
<?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>org.example</groupId> <artifactId>servlets</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies> </project>
简单的 servlet 类:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/hello") public class MainServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter printWriter = resp.getWriter(); printWriter.write("Hello!"); printWriter.close(); } }
-
要运行该应用程序,您需要创建一个 Tomcat 配置:
-
接下来,我们指出我们将使用哪个版本的 Tomcat,以及与服务器通信的 URL 和端口。你应该有这样的东西:
-
现在我们只需要指定将部署在容器中的工件(JAR 存档中的组装项目)。您可以单击Fix按钮并选择war exploded:这意味着在重建项目后,工件将自动放置在 servlet 容器中。
-
应用上下文的默认值是servlets_war_exploded。这意味着我们在以下位置访问应用程序:http://localhost:8080/servlets_war_exploded。
为什么我们需要任何额外的文本?让我们删除不需要的东西。现在我们的 Web 应用程序的地址是:http://localhost:8080。
-
单击确定。我们看到我们现在可以启动应用程序了:
现在,当您在浏览器中打开该应用程序时,您应该会收到 404 错误。这是有道理的,因为地址http://localhost:8080/需要一个映射到“/”的 servlet,但我们唯一的 servlet 映射到“/hello”。
-
我们可以在http://localhost:8080/hello访问它。一旦我们这样做了,我们就会得到预期的答案——字符串“Hello”!
@WebServlet()
注释。这是我们将 servlet 绑定(或映射)到特定路径(“/hello”)的地方。这个注解只出现在Java Servlet API 3.0,所以网上有很多通过XML文件进行servlet映射的例子。这不再是必要的。为了处理 GET 请求,我们覆盖了该doGet()
方法。注意方法的参数:HttpServletRequest
和HttpServletResponse
。该HttpServletRequest
对象为我们提供了有关请求的所有必要信息。在 中HttpServletResponse
,我们编写响应并设置必要的标头。
使用参数和会话
让我们改进我们的 servlet,以便它可以处理请求参数并使用会话:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Integer visitCounter = (Integer) session.getAttribute("visitCounter");
if (visitCounter == null) {
visitCounter = 1;
} else {
visitCounter++;
}
session.setAttribute("visitCounter", visitCounter);
String username = req.getParameter("username");
resp.setContentType("text/html");
PrintWriter printWriter = resp.getWriter();
if (username == null) {
printWriter.write("Hello, Anonymous" + "<br>");
} else {
printWriter.write("Hello, " + username + "<br>");
}
printWriter.write("Page was visited " + visitCounter + " times.");
printWriter.close();
}
}
visitCounter
现在 servlet 与会话一起工作,每次访问页面时 都会增加值。如果visitCounter
尚未创建属性(在第一次访问页面时),该getAttribute()
方法返回 null,因此我们需要检查是否为 null。请求参数也是如此。如果用户没有传递用户名参数,那么它的值将为空。在这种情况下,我们将用户视为匿名访客。要在 GET 请求中传递参数,使用查询字符串,例如,我们可以使用以下 URL:http://localhost:8080/hello? 用户名=保罗。您可以在上一篇文章中阅读有关 HTTP 请求的更多信息在系列中。我们的应用程序目前没有太多逻辑,但我们在根路径处遇到 404 错误有点烦人。为了解决这个问题,我们将创建另一个 servlet 并将其映射到起始页:@WebServlet("/")
。这个 servlet 的目的是将请求重定向到“/hello”路径。有两种方法可以做到这一点:使用“转发”或“重定向”。也许值得了解它们之间的区别。转发将请求的处理委托给服务器上的另一个 servlet。客户不参与。为此,将以下代码添加到新的 servlet 的 doGet() 方法中:
getServletContext().getRequestDispatcher("/hello").forward(req, resp);
在这段代码中,我们访问 servlet 上下文,获取相关 servlet 的请求分派器,并要求它处理带有指定参数 (req, resp) 的特定请求。重定向向客户端返回客户端必须用于处理其请求的地址。大多数浏览器会自动导航到返回的 URL。要实现重定向,您需要添加以下代码:
resp.sendRedirect(req.getContextPath() + "/hello");
我们redirect()
在HttpServletResponse
参数上调用该方法,并将客户端需要使用的地址传递给它。这里有一个重要的细节:还必须在完整重定向路径的末尾添加 HTTP 参数,这不是很方便。在我们的情况下,最好使用forward
,但有时使用redirect
更好。如果您了解它们工作方式的不同,就不会做出错误的选择。新 servlet 的代码如下所示:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// getServletContext().getRequestDispatcher("/hello").forward(req, resp);
resp.sendRedirect(req.getContextPath() + "/hello");
}
}
GO TO FULL VERSION