21.3.1 编写 Groovy 控制器

如前所述,Groovy 不像 Java 那样有很多的繁文缛节。这意味着我们在编写 Groovy 代码的时候,可以省略如下的内容:

  • 分号;

  • 像 public 和 private 这样的修饰符;

  • 属性的 Setter 和 Getter 方法;

  • 方法返回值的 return 关键字。

借助 Groovy 更加灵活的语法(以及 Spring Boot 的魔力),我们可以使用 Groovy 重写 ContactController 类,如程序清单 21.8 所示。

程序清单 21.8 使用 Groovy 编写的 ContactController 要比使用 Java 更简单
@Grab("spring-boot-starter-actuator")
@Grab("thymeleaf-spring4")

@Controller
@RequestMapping("/")
class ContactController {

	@Autowired
	ContactRepository contactRepo

	@RequestMapping(method=RequestMethod.GET)
	String home(Map<String,Object> model) {
		List<Contact> contacts = contactRepo.findAll()
		model.putAll([contacts: contacts])
		"home"
	}

	@RequestMapping(method=RequestMethod.POST)
	String submit(Contact contact) {
		contactRepo.save(contact)
		"redirect:/"
	}

}

我们可以看到,这个版本的 ContactController 要比对应的 Java 版本更加简洁。排除掉 Groovy 不需要的内容后,ContactController 更加简短也更易于阅读。

程序清单 21.8 还移除了一些内容,你可能也发现了,这里没有 import 代码行,在 Java 代码中这是很常见的。Groovy 默认会导入一些包和类,包括:

  • java.io.*

  • java.lang.*

  • java.math.BigDecimal

  • java.math.BigInteger

  • java.net.*

  • java.util.*

  • groovy.lang.*

  • groovy.util.*

因为有了这些默认的导入,所以 ContactController 就不需要导入 List 类了。这个类位于 java.util 包中,包含在默认的导入里面。

但是,像 @Controller、@RequestMapping、@Autowired 以及 @RequestMethod 这样的 Spring 类型该怎么处理呢?它们没有位于默认的导入中,我们该如何省略 import 代码行呢? 稍后,当我们运行应用的时候,Spring Boot CLI 将会试图使用 Groovy 编译器编译这些 Groovy 类。因为这些类型没有导入进来,所以将会导致编译失败。

但是,Spring Boot CLI 却不会就这样轻易放弃,在这里 CLI 将自动配置达到了一个新高度。CLI 将会识别出失败是因为缺少 Spring 类型,它会采取两个步骤来修正这个问题。首先会获取 Spring Boot Web Starter 依赖并将其依赖的其他内容都添加到类路径下(这样会下载并添加 JAR 到类路径下)。然后,它会将必要的包添加到 Groovy 编译器的默认导入列表中,然后重新尝试编译代码。

CLI 这种自动添加依赖/自动导入的结果就是我们的控制器类不需要任何的 import 语句了,并且我们没有必要再手动或者通过 Maven、Gradle 来解析 Spring 库。Spring Boot CLI 将会为我们完成所有的事情。

现在,让我们后退一步,考虑一下这里都发生了什么。通过在代码中使用 Spring MVC 类型,如 @Controller 或 @RequestMapping,CLI 将会自动解析 Spring Boot Web Starter 依赖。将 Web Starter 的依赖传递添加到类路径之后,Spring Boot 的自动配置将会发挥作用,它会为我 们自动配置 Spring MVC 功能所需的 bean。不过,在这里我们需要做的 仅仅是使用这些类型,Spring Boot 将会处理所有的事情。

当然,CLI 的功能也会有一些限制。尽管它知道如何解析众多的 Spring 依赖,并且能够自动将很多 Spring 类型(以及很多其他的库)添加到导入中,但是它不能自动解析和导入所有的功能。例如,使用 Thymeleaf 模板是一个可替换的方案,所以要在代码中通过 @Grab 显示声明。

还要注意,很多的依赖都没有必要指定 group ID 和版本号。Spring Boot 将会在解析 @Grab 依赖的时候参与进来,将缺失的 group ID 和版本号添加上。

借助 @Grab 注解,我们声明了要使用 Thymeleaf,这会触发自动配置功能,将会自动配置在 Spring MVC 中支持 Thymeleaf 模板所需的 bean。

尽管 Contact 类与 Spring Boot 没有太大关系,但为了样例的完整性,我还是将它的 Groovy 代码展现在了下面:

class Contact {
  long id
  String firstName
  String lastName
  String phoneNumber
  String emailAddress
}

可以看到,Contact 也更加简洁,没有分号、存取器方法以及像 public 和 private 这样的修饰符。这完全归功于 Groovy 简单的语法,其实 Spring Boot 并没有参与简化 Contact 类。

接下来,我们看一下如何借助 Spring Boot CLI 和 Groovy 来简化 Repository 类。

Last updated