# 2.4 使用视图控制器

到目前为止，已经为 Taco Cloud 应用程序编写了三个控制器。尽管每个控制器在应用程序的功能上都有不同的用途，但它们几乎都遵循相同的编程模型：

* 它们都用 @Controller 进行了注释，以表明它们是控制器类，应该由 Spring 组件扫描自动发现，并在 Spring 应用程序上下文中作为 bean 进行实例化。
* 除了 HomeController 之外，所有的控制器都在类级别上使用 @RequestMapping 进行注释，以定义控制器将处理的基本请求模式。
* 它们都有一个或多个方法，这些方法都用 @GetMapping 或 @PostMapping 进行了注释，以提供关于哪些方法应该处理哪些请求的细节。

即将编写的大多数控制器都将遵循这种模式。但是，如果一个控制器足够简单，不填充模型或流程输入（就像 HomeController 一样），那么还有另一种定义控制器的方法。请查看下一个程序清单，了解如何声明视图控制器 —— 一个只将请求转发给视图的控制器。

{% code title="程序清单 2.15 声明视图控制器" %}

```java
package tacos.web;
​
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
​
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}
```

{% endcode %}

关于 @WebConfig 最值得注意的是它实现了 WebMvcConfigurer 接口。WebMvcConfigurer 定义了几个配置 Spring MVC 的方法。尽管它是一个接口，但它提供了所有方法的默认实现，因此只需覆盖所需的方法。在本例中，覆盖了 addViewControllers() 方法。

addViewControllers() 方法提供了一个 ViewControllerRegistry，可以使用它来注册一个或多个视图控制器。在这里，在注册表上调用 addViewController()，传入 “/”，这是视图控制器处理 GET 请求的路径。该方法返回一个 ViewControllerRegistration 对象，在该对象上立即调用 setViewName() 来指定 home 作为应该转发 “/” 请求的视图。

就像这样，已经能够用配置类中的几行代码替换 HomeController。现在可以删除 HomeController，应用程序的行为应该与以前一样。惟一需要做的其他更改是重新访问第 1 章中的 HomeControllerTest，从 @WebMvcTest 注释中删除对 HomeController 的引用，这样测试类就可以无错误地编译了。

这里，已经创建了一个新的 WebConfig 配置类来存放视图控制器声明。但是任何配置类都可以实现 WebMvcConfigurer 并覆盖 addViewController() 方法。例如，可以将相同的视图控制器声明添加到引导 TacoCloudApplication 类中，如下所示：

```java
@SpringBootApplication
public class TacoCloudApplication implements WebMvcConfigurer {
    
    public static void main(String[] args) {
        SpringApplication.run(TacoCloudApplication.class, args);
    }
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}
```

通过扩展现有的配置类，可以避免创建新的配置类，从而降低项目工件数量。但是我倾向于为每种配置（web、数据、安全性等等）创建一个新的配置类，保持应用程序引导配置的简洁。

说到视图控制器，更一般地说，是控制器将请求转发给的视图，到目前为止，已经为所有视图使用了 Thymeleaf。我非常喜欢 Thymeleaf，但也许你更喜欢应用程序视图的不同模板模型。让我们看看 Spring 支持的许多视图选项。
