JavaRush /Java 博客 /Random-ZH /使用 servlet 和 jsp 创建简单的 Web 应用程序(第 2 部分)
fatfaggy
第 26 级
Киев

使用 servlet 和 jsp 创建简单的 Web 应用程序(第 2 部分)

已在 Random-ZH 群组中发布
我继续描述使用 servlet、jsp、Maven 和 Tomcat 创建 Web 应用程序的过程。如有必要,请在文章开头。
我们创建实体。
让我们在entities包中创建一个User类,在其中我们将创建两个私有字符串变量name和password。让我们创建构造函数(默认的和接受两个值的构造函数)、getters/setters、重写 toString() 方法(以防万一)以及 equals() 和 hashCode() 方法。 public class User { private String name; private String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (name != null ? !name.equals(user.name) : user.name != null) return false; return password != null ? password.equals(user.password) : user.password == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); return result; } } 现在我们可以开始创建用户列表,我们将在其中添加用户,并从其中显示用户。但有一个问题。我们不创建 servlet 对象;Tomcat 为我们创建它们。我们在其中重写的方法也已经为我们定义了,我们无法添加参数。那么我们如何创建一个在我们的两个 servlet 中都可见的公共列表呢?如果我们只是在每个 servlet 中创建自己的列表对象,那么我们将把用户添加到一个列表中,但使用 ListServlet servlet 显示用户列表将完全不同。事实证明,我们需要一个两个 servlet 共用的对象。一般来说,我们需要一个对程序中所有类都通用的对象;整个程序的唯一对象。我希望您听说过一些有关设计模式的知识。也许对于某些人来说,这是在他们的程序中使用 Singleton模板的第一个真正需要。您可以发挥创意并制作一些很酷的单例,通过双重检查和同步(是的,我们有一个多线程应用程序,因为 Tomcat 在不同的线程中运行 servlet),但我将使用早期初始化的选项,因为在这种情况下相当合适。
创建模型。
然后我们将在模型包中创建一个类(并在其中实现单例模板),我们也将其称为“模型”。让我们在其中创建一个私有用户列表对象,并创建两个方法:第一个用于添加用户,第二个 - 让它简单地返回字符串(用户名)列表。由于我们的用户对象由名称和密码组成,因此我们不想“泄露”用户密码,因此我们只会返回其名称列表。 public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
关于 mvc 的一些知识。
既然您听说过单例,这意味着您可能听说过另一种设计模式 - MVC(模型-视图-控制器,或俄语中的模型-视图-控制器,或者就像英语中的模型-视图-控制器)。其本质是将业务逻辑与表示分离。也就是说,将决定 做什么的代码与决定 如何显示的代码分开。视图(视图或只是视图)负责呈现某些数据的形式。在我们的例子中,视图是我们的 JSP 页面。这就是为什么我将它们放在一个名为“views”的文件夹中。模型是程序运行时使用的实际数据。在我们的例子中,这些是用户(用户列表)。那么,控制器是它们之间的连接纽带。他们从模型中获取数据并将其传输到视图,或者从 Tomcat 接收一些数据,对其进行处理并将其传输到模型。业务逻辑(即 做什么)应该在其中描述,而不是在模型或视图中。于是,每个人都做自己的事:
  • 模型存储数据
  • 视图绘制出美丽的数据表示
  • 控制器处理数据
这使得它们都相当简单且可维护。而不是一个类中所有代码的巨大转储。MVC 不仅适用于 Web 编程,而且在该领域仍然很常见(如果不是总是)。在我们的例子中,Servlet 将充当控制器。是的,这是对该模式的非常肤浅甚至粗略的描述,但本文不是关于设计模式,而是关于如何制作一个简单的 Web 应用程序:) 谁想了解更多 - Google 知道一切!:) 让我们回到我们的观点。
创建用于添加用户的表单。
让我们向 add.jsp 文件添加一个表单,其中包含两个文本输入(一个是常规输入,另一个是密码类型)和一个用于将数据发送到服务器的按钮。 这里的表单有一个值为 post 的 method 属性。这意味着该表单中的数据将以 POST 请求的形式发送到服务器。未指定操作属性,这意味着该请求将发送到我们访问该页面的同一地址(/add)。因此,绑定到该地址的 servlet 在收到 GET 请求后,会返回此 jsp 以及用于添加用户的表单,如果它收到 POST 请求,则该表单已将其数据发送到那里(我们将从doPost() 方法中的 request 对象,对其进行处理并将其传输到模型进行保存)。值得注意的是,输入在这里有一个名称参数(对于具有名称的字段,它具有值 name,对于具有密码的字段,它具有值 pass)。这是非常重要的一点。因为为了从请求(已经在 servlet 内部)获取这些数据(将输入的名称和密码),我们将准确地使用这些名称和传递。但稍后会详细介绍。用于发送数据的按钮本身再次以按钮的形式制成,而不是通常习惯的输入形式。我不知道这个选项有多通用,但它在 Chrome 中对我有用:)
使用 servlet 处理 POST 请求。
让我们回到 AddServlet servlet。我们已经知道,为了让 servlet 能够“捕获”GET 请求,我们重写 HttpServlet 类中的 doGet() 方法。为了教我们的 servlet 也捕获 POST 请求,我们还重写 doPost() 方法。它从 Tomcat 接收类似的请求和响应对象,我们将使用它。首先,让我们从请求中提取名称并传递表单发送的参数(如果您在表单中对它们进行了不同的命名,那么这些就是您编写的名称)。然后我们将使用接收到的数据创建用户对象。然后我们将获取模型对象并将创建的用户添加到模型中。 @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); }
将数据传输到视图。
现在让我们继续讨论 ListServlet servlet。我们已经实现了 doGet() 方法,它只是将控制转移到 list.jsp 视图。如果您还没有,请使用 AddServlet servlet 中的相同方法进行类推。现在,最好从模型中获取用户名列表并将它们传递给视图,视图将在那里接收它们并很好地显示它们。为此,我们将再次使用从 Tomcat 收到的请求对象。我们可以向这个对象添加一个属性,给它一些名称,事实上,我们想要传输到视图的对象本身。由于以下事实:当将执行过程从 servlet 转移到视图时,我们将 servlet 本身接收到的相同请求和响应对象传递给那里,然后通过将名称列表添加到请求对象,我们就可以从该请求视图中的对象创建我们的用户名列表并获取。我们已经完成了 ListServlet 类,所以这里是整个类的代码。 package app.servlets; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; public class ListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Model model = Model.getInstance(); List names = model.list(); req.setAttribute("userNames", names); RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp"); requestDispatcher.forward(req, resp); } }
在jsp文件中执行java代码。
现在让我们继续讨论 list.jsp 文件。只有当ListServlet经过这里的执行过程时,才会执行这个文件。此外,在该 servlet 中,我们已经从模型中准备了用户名列表,并将其传递到请求对象中。给定一个名称列表,我们可以运行一个 for 循环并打印每个名称。正如我已经说过的,jsp 文件可以执行 java 代码(原则上,这就是它们与静态 html 页面的不同之处)。为了执行一些代码,在我们需要的地方放置一个构造就足够了。 <% // java code %> 在这样的构造中,我们可以访问几个变量: request - 我们的请求对象,我们从 servlet 传递它,在那里它被简单地调用req response - 响应对象,在 servlet 中被称为 resp out - JspWriter 类型的对象(继承自通常的 Writer),借助它我们可以直接将某些内容“写入”到 html 页面本身中。Out.println("Hello world!") 与 System.out.println("Hello world!") 非常相似,但不要混淆它们!out.println()“写入”html 页面,而 System.out.println“写入”系统输出。如果您在包含 jsp 代码的部分中调用 System.out.println() 方法,您将在 Tomcat 控制台中看到结果,而不是像您希望的那样在页面上看到结果:) 您可以在 jsp 中查找其他可用对象 这里。使用 request 对象,我们可以获得从 servlet 传递的名称列表(我们将相应的属性附加到该对象),并使用 out 对象,我们可以显示这些名称。现在让我们简单地以 html 列表的形式执行此操作: 如果我们只想在有用户时显示列表,否则显示还没有用户的警告,我们可以稍微重写此部分: 现在我们知道如何将数据从 servlet 传输到视图 - 我们可以稍微改进一下 AddServlet,以便显示有关成功添加用户的通知。为此,在 doPost() 方法中,将新用户添加到模型后,我们可以将该用户的名称添加到 req 对象的属性中,并将控制权传递回 add.jsp 视图。并且在其中已经用Java代码创建了一个部分,您可以在其中检查请求中是否存在这样的属性,如果是,则显示一条消息,表明用户已成功添加。经过这些更改后,AddServlet servlet 的完整代码将如下所示: 这里,在 doPost() 方法的末尾,我们设置一个属性,其中包含添加到模型中的用户名称,然后调用 doGet( ) 方法,我们将当前请求和响应传递给该方法。doGet() 方法已将控制权转移到视图,并在其中发送一个请求对象,其中添加的用户名称作为属性附加。仍然需要更正 add.jsp 本身,以便在存在此类属性时显示此类通知。最终添加.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    package app.servlets; import app.entities.User; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp"); requestDispatcher.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); req.setAttribute("userName", name); doGet(req, resp); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    页面的主体由一个带有标题的 div 组成,后面是一个内容容器,检查其中是否存在带有用户名的属性,然后是一个带有用于添加用户的表单的 div,最后是一个页脚返回主页的按钮。看起来好像 div 太多了,但我们稍后在添加样式时会用到它们:) 好吧,最终版本是 list.jsp。这样 ,我们就有了一个完全可以工作的 Web 应用程序,它还可以存储和添加用户显示他们的名字列表。剩下的就是修饰它......:) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    添加样式。我们使用W3.CSS框架。
    目前,我们的应用程序正在运行,但绝对疯狂:)我们需要添加背景、文本和按钮的颜色、风格化列表、进行对齐、添加缩进,一般来说有很多事情。如果您手动编写样式,可能会花费大量时间和精力。因此,我建议使用 CSS 框架 W3.CSS。它已经有了带有样式的现成类;剩下的就是将我们想要应用的 CSS 类放置在正确的位置。为了将它们添加到我们的页面中,首先我们需要包含一个带有样式的文件。这可以通过两种方式完成: 1. 浏览我们的页面,并在标题部分插入带有样式的文件的直接链接。 如果您有稳定的互联网连接,则此选项适合。然后,当您在本地服务器上打开页面时,样式将从 Internet 中提取。2. 如果您想在本地拥有所有样式并且不依赖于 Internet 连接,您可以简单地 下载带有样式的文件并将其放置在 web 文件夹中的某个位置(例如 web/styles/w3.css),然后浏览我们所有的页面(index.html、add.jsp、list.jsp)并在 head 部分中输入指向该文件的链接,并使用样式。 之后,只需浏览标签并用您喜欢的样式标记它们。我不会详细讨论这一点,但会立即提供我的三个文件的现成版本以及已安排的样式类。index.html add.jsp list.jsp 就是这样 :) 如果您仍然有任何问题或有任何意见,或者相反,有些事情没有解决 - 请留下评论。好吧,我将附上几张截图来说明这一切的结果。 最后。如果你想练习这个项目,你可以尝试: Super app!

    Super app!

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

    <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users list

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    应用主页 添加用户窗口 用户列表
    • 制作一个 servlet 和 jsp 来删除用户,并制作几个来更改/编辑现有用户。您将在 servlet 上获得真正的 CrUD Web 应用程序:)))
    • 替换列表(列表 )与数据库一起使用,以便添加的用户在服务器重新启动后不会消失:)
    祝你好运!
    评论
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION