# Spring Boot `Model`

> 原文： [http://zetcode.com/springboot/model/](http://zetcode.com/springboot/model/)

Spring Boot `Model`教程展示了如何在 Spring Boot 应用中使用模型。 在 Spring，模型由`Model`，`ModelMap`和`ModelAndView`表示。

Spring 是流行的 Java 应用框架，而 Spring Boot 是 Spring 的演进，可以帮助轻松地创建独立的，生产级的基于 Spring 的应用。

## MVC

MVC（模型-视图-控制器）是一种软件架构模式，它将应用分为三个部分：模型，视图和控制器。 该模型表示一个携带数据的 Java 对象。 该视图使模型包含的数据可视化。 控制器管理流入模型对象的数据流，并在数据更改时更新视图。 它使视图和模型分离。

## Spring MVC

Spring MVC 是基于 Servlet API 构建的原始 Web 框架。 它基于 MVC 设计模式。 Spring Framework 5.0 引入了一个名为 Spring WebFlux 的并行反应式栈 Web 框架。

## `Model`，`ModelMap`，`ModelAndView`

`Model`，`ModelMap`和`ModelAndView`用于在 Spring MVC 应用中定义模型。 `Model`定义了模型属性的持有者，并且主要用于向模型添加属性。 `ModelMap`是`Model`的扩展，具有在映射和链式方法调用中存储属性的能力。 `ModelAndView`是模型和视图的支架； 它允许在一个返回值中返回模型和视图。

## Spring Boot `Model`示例

以下简单的 Web 应用在控制器方法中使用`Model`，`ModelMap`和`ModelAndView`。 该模型保存应用数据，该数据显示在视图中。 我们将 Freemaker 库用于视图层。

```java
pom.xml
src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── Application.java
    │   │           └── controller
    │   │               └── MyController.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       │   └── index.html
    │       └── templates
    │           └── show.ftl
    └── test
        └── java

```

这是 Spring 应用的项目结构。

`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>springbootmodelex</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

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

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

```

这是 Maven `pom.xml`文件。 `spring-boot-starter-parent`是父 POM，它为使用 Maven 构建的应用提供依赖关系和插件管理。 `spring-boot-starter-freemarker`是 Freemarker 模板引擎的依赖项。 此依赖项还将在项目中包含 Spring MVC。 `spring-boot-maven-plugin`将 Spring 应用打包到可执行的 JAR 或 WAR 归档文件中。

`resources/application.properties`

```java
spring.main.banner-mode=off
logging.level.org.springframework=ERROR

mymessage=Hello there

```

`application.properties`是 Spring Boot 中的主要配置文件。 我们通过选择错误消息来关闭 Spring 横幅，并减少 Spring 框架的日志记录量。 `mymessage`属性包含该消息。

`com/zetcode/MyController.java`

```java
package com.zetcode.controller;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {

    @Value("${mymessage}")
    private String message;

    @GetMapping("/getMessage")
    public String getMessage(Model model) {

        model.addAttribute("message", message);

        return "show";
    }

    @GetMapping("/getMessage2")
    public ModelAndView getMessage() {

        var mav = new ModelAndView();

        mav.addObject("message", message);
        mav.setViewName("show");

        return mav;
    }

    @GetMapping("/getMessageAndTime")
    public String getMessageAndTime(ModelMap map) {

        var ldt = LocalDateTime.now();

        var fmt = DateTimeFormatter.ofLocalizedDateTime(
                FormatStyle.MEDIUM);

        fmt.withLocale(new Locale("sk", "SK"));
        fmt.withZone(ZoneId.of("CET"));

        var time = fmt.format(ldt);

        map.addAttribute("message", message).addAttribute("time", time);

        return "show";
    }
}

```

这是`MyController`。 它具有三种响应客户端请求的方法。

```java
@Controller
public class MyController {

```

`MyController`带有`@Controller`注解。

```java
@Value("${mymessage}")
private String message;

```

使用`@Value`注解，我们将`application.properties`文件中的`mymessage`属性插入到`message`属性中。

```java
@GetMapping("/getMessage")
public String getMessage(Model model) {

    model.addAttribute("message", message);

    return "show";
}

```

`@GetMapping`将`/getMessage` URL 模式映射到`getMessage()`方法。 在`getMessage()`方法中，我们使用`Model`。 它使用`addAttribute()`方法接收`message`属性。 return 关键字返回视图的名称，该名称将解析为`show.ftl`，因为我们使用的是 Freemarker 模板系统。

```java
@GetMapping("/getMessage2")
public ModelAndView getMessage() {

    var mav = new ModelAndView();
    mav.addObject("message", message);
    mav.setViewName("show");

    return mav;
}

```

在第二种情况下，我们使用`ModelAndView`。 我们使用`addObject()`和`setViewName()`添加模型数据和视图名称。 该方法返回`ModelAndView`对象。

```java
@GetMapping("/getMessageAndTime")
public String getMessageAndTime(ModelMap map) {

    var ldt = LocalDateTime.now();

    var fmt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);

    fmt.withLocale(new Locale("sk", "SK"));
    fmt.withZone(ZoneId.of("CET"));

    var time = fmt.format(ldt);

    map.addAttribute("message", message).addAttribute("time", time);

    return "show";
}

```

在`getMessageAndTime()`方法中，我们使用`ModelMap`。 模型图接收两个属性：消息和时间。

`resources/static/index.html`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <ul>
            <li><a href="getMessage">Get message</a></li>
            <li><a href="getMessage2">Get message 2</a></li>
            <li><a href="getMessageAndTime">Get message and time</a></li>
        </ul>
    </body>
</html>

```

这是主页。 它包含三个调用 Spring 控制器方法的链接。 它是静态资源，位于预定义的`src/main/resources/static`目录中。

`resources/templates/show.ftl`

```java
<!DOCTYPE html>
<html>
    <head>
        <title>Message</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <p>
            Message: ${message}
        </p>

        <#if time??>
            <p>Date and time: ${time}</p>
        </#if>

    </body>
</html>

```

`show.ftl`是一个 Freemarker 模板文件。 它位于预定义的`src/main/resources/templates`目录中。 它使用`${}`语法输出消息和时间（可选）。

`com/zetcode/Application.java`

```java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application  {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

```

`Application`是设置 Spring Boot 应用的入口。 `@SpringBootApplication`注解启用自动配置和组件扫描。 在扫描过程中，将查找`@Controller`注解，并从`MyController`类创建一个 Spring bean。

```java
$ mvn spring-boot:run

```

启动应用后，我们导航到`localhost:8080`。

在本教程中，我们已经在 Spring 应用中使用了模型。 您可能也对相关教程感兴趣： [Spring Boot `@ModelAttribute`教程](/springboot/modelattribute/)， [Spring Boot `@Controller`教程](/springboot/controller/)， [Spring Boot Freemaker 教程](/springboot/freemarker/)， [Spring Boot `@RequestParam`教程](/springboot/requestparam/)， [Java 教程](/lang/java/)或列出[所有 Spring Boot 教程](/all/#springboot)。