1.概述

在本文中,我们将创建一个小型Web应用程序,该应用程序使用基本的Servlet和JSP来实现MVC设计模式。

在真正开始前,我们将探讨MVC的工作方式及其主要功能。

2. MVC简介

模型-视图-控制器(MVC)是一种在软件工程中用于将应用程序逻辑与用户界面分开的模式。

顾名思义,MVC模式具有三层。

模型定义应用程序的业务层,控制器管理应用程序的流程,视图定义应用程序的表示层。

尽管MVC模式并非特定于Web应用程序,但它非常适合此类应用程序。

在Java上下文中,模型由简单的Java类组成,控制器由servlet组成,视图由JSP页面组成。

这是该模式的一些主要功能:

  • 将表示层与业务层分开。
  • 控制器执行调用模型并将数据发送到View的操作。
  • 模型甚至不知道某些Web应用程序或桌面应用程序正在使用它。

让我们看一下每一层。

2.1 模型层

数据层,它包含系统的业务逻辑,并且还表示应用程序的状态。

它独立于表示层,控制器从模型层获取数据并将其发送到视图层。

2.2 控制器层

控制器层充当视图和模型之间的接口。它从View层接收请求并进行处理,包括必要的验证。

这些请求将进一步发送到模型层进行数据处理,处理后,数据将发送回控制器,然后显示在视图上。

2.3 视图层

表示应用程序的输出,通常是某种形式的UI。表示层用于显示控制器获取的模型数据。

3.带有Servlet和JSP的MVC

为了实现基于MVC设计模式的Web应用程序,我们将创建StudentStudentService类。

它们将充当我们的模型层。StudentServlet类将充当Controller,对于表示层,我们将创建student-record.jsp页面。

现在,让我们逐层编写这些层,我们从Student类开始:

public class Student {

    private int id;
    private String firstName;
    private String lastName;
    
  	// constructors and getters and setters
}

现在让我们编写我们的StudentService,它将处理我们的业务逻辑:

public class StudentService {

    public Optional<Student> getStudent(int id) {
        switch (id) {
            case 1:
                return Optional.of(new Student(1, "Li", "A"));
            case 2:
                return Optional.of(new Student(2, "Sun", "B"));
            case 3:
                return Optional.of(new Student(3, "Song", "C"));
            default:
                return Optional.empty();
        }
    }
}

现在,让我们创建控制类StudentServlet

@WebServlet(name = "StudentServlet", urlPatterns = "/student-record")
public class StudentServlet extends HttpServlet {

    private final StudentService studentService = new StudentService();

    private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String studentID = request.getParameter("id");
        if (studentID != null) {
            int id = Integer.parseInt(studentID);
            studentService.getStudent(id)
                    .ifPresent(s -> request.setAttribute("studentRecord", s));
        }

        RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/student-record.jsp");
        dispatcher.forward(request, response);
    }

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

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }
}

StudentServlet是我们的Web应用程序的控制器。

首先,它从请求中读取请求参数id。如果有请求参数id,则会从业务层获取Student对象。

一旦从模型中检索到必要的数据,就使用*setAttribute()*方法将该数据放入请求中。

最后,控制器将请求和响应对象转发到JSP,即应用程序视图。

接下来,让我们编写表示层student-record.jsp

<%@ page import="com.ripjava.servlet.mvc.model.Student" %>
<html>
<head>
    <title>Student Record</title>
</head>
<body>
<%
  if (request.getAttribute("studentRecord") != null) {
    Student student = (Student) request.getAttribute("studentRecord");
%>

<h1>Student Record</h1>
<div>ID: <%= student.getId()%></div>
<div>First Name: <%= student.getFirstName()%></div>
<div>Last Name: <%= student.getLastName()%></div>

<%
} else {
%>

<h1>No student record found.</h1>

<% } %>
</body>
</html>

当然,JSP是应用程序的视图。它从控制器接收它需要的所有信息,不需要直接与业务层进行交互。

我们启动Jetty测试。

mvn jetty:run

我们来测试一下,在浏览器中输入以下的URL:

http://localhost:8080/student-record?id=1

结果如下:

image-20200602184356060

我们将URL中的请求参数去掉:

http://localhost:8080/student-record

结果如下:

image-20200602184420765

4. 结论

在本文中,我们学习了MVC模式,并且着重于如何实现一个简单的示例。

与往常一样,此处提供的代码可以在GitHub上找到。