1.3编写Spring应用程序

1.3编写Spring应用程序

因为才刚刚开始,所以我们将从对Taco Cloud应用程序的一个相对较小的更改开始,但是这个更改将展示Spring的很多优点。在刚刚开始的时候,添加到Taco Cloud应用程序的第一个功能是主页,这似乎是合适的。当你添加主页,你将创建两个代码构件:

  • 一个处理主页请求的控制器类
  • 一个视图模板,定义了主页的外观

因为测试很重要,所以还将编写一个简单的测试类来测试主页。但首先…我们来写这个控制器。

1.3.1处理web请求

Spring附带了一个强大的web框架,称为Spring MVCSpring MVC的核心是控制器的概念,这是一个处理请求并使用某种信息进行响应的类。对于面向浏览器的应用程序,控制器的响应方式是可选地填充模型数据并将请求传递给视图,以生成返回给浏览器的HTML

你将在第2章学到很多关于Spring MVC的知识。但是现在,将编写一个简单的控制器类来处理根路径的请求(例如 /,并将这些请求转发到主页视图,而不填充任何模型数据。下面的清单显示了简单的控制器类。

package tacos;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {
    @GetMapping("/")
    public String home() {
        return "home";
    }
}

可以看到,这个类是用 @Controller 注释的。@Controller 本身并没有做多少事情。它的主要目的是将该类识别为组件扫描的组件。由于 HomeController 是用 @Controller 注释的,因此Spring的组件扫描会自动发现它,并在Spring应用程序上下文中创建一个 HomeController 实例作为bean

实际上,其他一些注释(包括 @Component@Service@Repository)的用途与 @Controller 类似。你可以用任何其他的注解来有效地注释 HomeController,它仍然可以工作。但是,选择 @Controller 更能描述该组件在应用程序中的角色。

home() 方法与控制器方法一样简单。它使用 @GetMapping 进行注释,以指示如果接收到根路径 /HTTP GET请求,则此方法应该处理该请求。除了返回 homeString 值外,它什么也不做。

此值被解释为视图的逻辑名称。如何实现该视图取决于几个因素,但是因为Thymeleaf在类路径中,所以可以使用Thymeleaf定义该模板。

为什么是Thymeleaf

你可能想知道为什么选择Thymeleaf作为模板引擎。为什么不是JSP?为什么不是FreeMarker?为什么不是其他几个选项中的一个呢?

简单地说,我必须选择一些东西,我喜欢Thymeleaf,相比其他选项更喜欢。尽管JSP看起来是一个不做的选择,但是在使用JSP进行Spring引导时仍然存在一些需要克服的挑战。我不想在第1章中掉进那个陷阱。不要紧,我们将在第2章中讨论其他模板选项,包括JSP

模板名称由逻辑视图名称派生而来,它的前缀是/templates/,后缀是.html。模板的结果路径是/templates/home.html。因此,需要将模板放在项目的/src/main/resources/templates/home.html中。现在让我们创建该模板。

1.3.2定义视图

为了保持你的主页简洁,它应该做的只是欢迎用户访问网站。下一个清单显示了定义Taco Cloud主页的基本Thymeleaf模板。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Taco Cloud</title>
  </head>

  <body>
    <h1>Welcome to...</h1>
    <img th:src="@{/images/TacoCloud.png}" />
  </body>
</html>

关于这个模板没有太多要讨论的。唯一值得注意的代码行是显示Taco Cloud标志的 <img> 标记。它使用一个Thymeleafth:src 属性和一个 @{…} 表达式引用具有上下文相对路径的图片。除去这些,它只是一个Hello World页面。

但是让我们再多讨论一下这个图片。我将把它留给你来定义一个你喜欢的Taco Cloud标志。你需要将它放在项目中的恰当位置。

该图片是通过上下文相对路径/images/TacoCloud.png进行引用的。从我们对项目结构的回顾中可以想起,像图片这样的静态内容保存在/src/main/resources/static文件夹中。这意味着Taco Cloud标志图片也必须驻留在项目的/src/main/resources/static/images/TacoCloud.png中。

现在已经有了处理主页请求的控制器和呈现主页的视图模板,几乎已经准备好启动应用程序并看到它的实际运行效果了。但首先,让我们看看如何针对控制器编写测试。

1.3.3测试控制器

在对HTML页面的内容进行断言时,测试web应用程序可能比较棘手。幸运的是,Spring提供了一些强大的测试支持,使测试web应用程序变得很容易。

就主页而言,你将编写一个与主页本身复杂度相当的测试。你的测试将对根路径 / 执行一个HTTP GET请求并期望得到一个成功的结果,其中视图名称为home,结果内容包含短语 “Welcome to…”。下面的方法应该可以达到目的。

package tacos;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testHomePage() throws Exception {
        mockMvc.perform(get("/"))
            .andExpect(status().isOk())
            .andExpect(view().name("home"))
            .andExpect(content().string(containsString("Welcome to...")));
    }
}

关于这个测试,你可能注意到的第一件事是,它与 TacoCloudApplicationTests 类在应用到它的注释方面略有不同。HomeControllerTest 使用 @WebMvcTest 注释,而不是 @SpringBootTest 标记。这是Spring Boot提供的一个特殊测试注释,它安排测试在Spring MVC应用程序的上下文中运行。更具体地说,在本例中,它安排 HomeControllerSpring MVC中注册,这样你就可以对它进行请求。

@WebMvcTest 还为测试Spring MVC提供了Spring支持。虽然可以让它启动服务器,但模拟Spring MVC的机制就足以满足你的目的了。测试类被注入了一个 MockMvc 对象中,以此用来测试来驱动模型。

testHomePage() 方法定义了要对主页执行的测试。它从 MockMvc 对象开始,执行针对 /(根路径)的HTTP GET请求。该请求规定了下列期望值:

  • 响应应该有一个HTTP 200(OK)状态。

  • 视图应该有一个合理的主页名称。

  • 呈现的视图应该包含 “Welcome to…”

如果在 MockMvc 对象执行请求之后,这些期望中的任何一个都没有满足,那么测试就会失败。但是控制器和视图模板是为了满足这些期望而编写的,所以测试应该能够通过,或者至少能够通过一些表示测试通过的绿色提示。

控制器写好了,视图模板创建好了,测试通过了。看来你已经成功地实现了主页。但是,即使测试通过了,在浏览器中查看结果也会稍微让人更满意一些。毕竟,Taco Cloud的客户也将这样看待它。让我们构建应用程序并运行它。

1.3.4构建并运行应用程序

正如有多种方法可以初始化Spring应用程序一样,也有多种方法可以运行Spring应用程序。如果愿意,可以翻到附录部分,阅读一些更常见的运行Spring引导应用程序的方法。

因为选择使用Spring Tool Suite来初始化和处理项目,所以有一个称为Spring Boot Dashboard的便利功能可以帮助你在IDE中运行应用程序。Spring Boot Dashboard显示为一个选项卡,通常位于IDE窗口的左下方。图1.7显示了Spring Boot Dashboard的注释截图。

虽然图1.7包含了一些最有用的细节,但我不想花太多时间来检查Spring Boot Dashboard所做的一切。现在需要知道的重要事情是如何使用它来运行Taco Cloud应用程序。确保taco-cloud应用程序在项目列表中突出显示(这是图1.7中显示的惟一应用程序,然后单击start按钮(最左边的按钮,其中有绿色三角形和红色正方形,应用程序应该会立即启动。

![1.7 Spring Boot Dashboard高亮](E:\Document\spring-in-action-v5-translate\第一部分Spring基础\第一章Spring入门\1.7 Spring Boot Dashboard高亮.jpg)

1.7 Spring Boot Dashboard注释

当应用程序启动时,将在控制台中看到一些Spring ASCII图飞过,然后看到一些日志条目描述应用程序启动时的步骤。在停止日志记录之前,将看到一个日志条目,其中说Tomcatport(s): 8080 (http)上启动,这意味着已经准备好将web浏览器指向主页,以查看结果。

等一下,Tomcat启动?何时将应用程序部署到Tomcat

Spring Boot应用程序倾向于裹挟所有需要的东西,而不需要部署到某个应用服务器。你从未将应用程序部署到Tomcat… 其实Tomcat是应用程序的一部分!(将在1.3.6小节中详细描述Tomcat如何成为应用程序的一部分的。)

现在应用程序已经启动,将web浏览器指向http://localhost:8080(或单击Spring Boot Dashboard中地球仪样子的按钮),应该会看到类似图1.8所示的内容。如果你设计了自己的图标,那么结果可能不同,但是它与在图1.8中看到的应该相差不大。

![1.8 Taco Cloud主页](E:\Document\spring-in-action-v5-translate\第一部分Spring基础\第一章Spring入门\1.8 Taco Cloud主页.jpg)

1.8 Taco Cloud主页

它可能没什么好看的。但这并不是一本关于平面设计的书。主页的简陋外观现在已经足够了。它为你了解Spring提供了一个坚实的开端。

到目前为止,忽略了DevTools。在初始化项目时将其作为依赖项进行选择。它作为一个依赖项出现在生成的pom.xml文件中。Spring Boot Dashboard甚至显示项目已经启用了DevTools。但是什么是DevTools,它能为您做什么?让我们快速浏览一下DevTools的几个最有用的特性。

1.3.5了解Spring Boot DevTools

顾名思义,DevToolsSpring开发人员提供了一些方便的开发同步工具。这些是:

  • 当代码更改时自动重启应用程序

  • 当以浏览器为目标的资源(如模板、JavaScript、样式表等)发生变化时,浏览器会自动刷新

  • 自动禁用模板缓存

  • 如果H2数据库正在使用,则在H2控制台中构建

理解DevTools不是IDE插件是很重要的,它也不要求您使用特定的IDE。它在Spring Tool SuiteIntelliJ IDEANetBeans中工作得同样好。此外,由于它仅用于开发目的,所以在部署生产环境时禁用它本身是非常明智的(我们将在第19章中讨论如何部署应用程序)现在,让我们关注一下Spring Boot DevTools最有用的特性,首先是自动重启应用程序。

自动重启应用程序

使用DevTools作为项目的一部分,将能够对项目中的Java代码和属性文件进行更改,并在短时间内查看这些更改的应用。DevTools监视更改,当它看到某些内容发生更改时,它会自动重新启动应用程序。

更准确地说,当DevTools起作用时,应用程序被加载到Java虚拟机(JVM)中的两个单独的类加载器中。一个类装入器装入Java代码、属性文件以及项目的src/main/path中的几乎所有东西。这些项目可能会频繁更改。另一个类加载器加载了依赖库,它们不太可能经常更改。

当检测到更改时,DevTools只重新加载包含项目代码的类加载器,并重新启动Spring应用程序上下文,但不影响其他类加载器和JVM。尽管这一策略很微妙,但它可以略微减少启动应用程序所需的时间。

这种策略的缺点是对依赖项的更改在自动重新启动时不可用。这是因为类装入器包含依赖项库 不是自动重新加载。这意味着,每当在构建规范中添加、更改或删除依赖项时,都需要重新启动应用程序才能使这些更改生效。

自动刷新浏览器和禁用模板缓存

默认情况下,模板选项(如ThymeleafFreeMarker)被配置为缓存模板解析的结果,这样模板就不需要对它们所服务的每个请求进行修复。这在生产中非常有用,因为它可以带来一些性能上的好处。

但是,缓存的模板在开发时不是很好。缓存的模板使它不可能在应用程序运行时更改模板,并在刷新浏览器后查看结果。即使做了更改,缓存的模板仍将继续使用,直到重新启动应用程序。

DevTools通过自动禁用所有模板缓存来解决这个问题。对模板进行尽可能多的修改,并且要知道只有浏览器刷新才能看到结果。

但如果像我一样,甚至不想被点击浏览器的刷新按钮所累,如果能够立即在浏览器中进行更改并查看结果,那就更好了。幸运的是,DevTools为我们这些懒得点击刷新按钮的人提供了一些特别的功能。

DevTools起作用时,它会自动启用LiveReload (http://livereload.com/)服务器和应用程序。就其本身而言,LiveReload服务器并不是很有用。但是,当与相应的LiveReload浏览器插件相结合时,它会使得浏览器在对模板、图像、样式表、JavaScript等进行更改时自动刷新 —— 实际上,几乎所有最终提供给浏览器的更改都会自动刷新。

LiveReload有针对Google ChromeSafariFirefox浏览器的插件(对不起,ieEdge的粉丝们)请访问 http://livereload.com/extensions/,了解如何为浏览器安装LiveReload

H2控制台中构建

虽然项目还没有使用数据库,但这将在第3章中进行更改。如果选择使用H2数据库进行开发,DevTools还将自动启用一个H2控制台,你可以从web浏览器访问该控制台。只需将web浏览器指向http://localhost:8080/h2-console,就可以深入了解应用程序正在处理的数据。

至此,已经编写了一个完整但简单的Spring应用程序。你将在本书的整个过程中扩展它。但是现在是回顾已经完成的工作以及Spring如何发挥作用的好时机。

1.3.6回顾

回想一下是如何走到这一步的。简而言之,以下是构建基于SpringTaco Cloud应用程序的步骤:

  • 使用Spring Initializr创建了一个初始项目结构。
  • 写了一个控制器类来处理主页请求。
  • 定义了一个视图模板来呈现主页。
  • 写了一个简单的测试类来检验上诉工作。

看起来很简单,不是吗?除了启动项目的第一步之外,所采取的每一个行动都是为了实现创建主页的目标。

事实上,编写的几乎每一行代码都是针对这个目标的。不计算Javaimport语句,只计算控制器类中的两行代码,而视图模板中没有Spring的特定代码。尽管测试类的大部分都使用了Spring的测试支持,但是在测试上下文中,它的侵入性似乎要小一些。

这是使用Spring开发的一个重要好处。可以关注于满足应用程序需求的代码,而不是满足框架的需求。尽管确实需要不时地编写一些特定于框架的代码,但这通常只是代码库的一小部分。如前所述,Spring (通过Spring Boot)可以被认为是 无框架的框架

这到底是怎么回事?Spring在幕后做了什么来确保您的应用程序需求得到满足?为了理解Spring在做什么,让我们从构建规范开始。

pom.xml文件中,声明了对WebThymeleaf启动器的依赖。这两个依赖关系带来了一些其他的依赖关系,包括:

  • Spring MVC框架
  • 嵌入式Tomcat
  • ThymeleafThymeleaf布局方言

它还带来了Spring Boot的自动配置库。当应用程序启动时,Spring Boot自动配置自动检测这些库并自动执行:

  • Spring应用程序上下文中配置bean以启用Spring MVC
  • 将嵌入式Tomcat服务器配置在Spring应用程序上下文中
  • 为使用Thymeleaf模板呈现Spring MV C视图,配置了一个Thymeleaf视图解析器

简而言之,自动配置完成了所有繁重的工作,让你专注于编写实现应用程序功能的代码。如果你问我这样好不好,我会说这是一个很好的安排!

你的Spring之旅才刚刚开始。Taco Cloud应用程序只涉及Spring提供的一小部分内容。在你开始下一步之前,让我们来俯瞰Spring的风景线,看看你在旅途中会遇到什么地标。

上一页
下一页