# Spring 引导 CLI

Spring 引导 CLI 是一个命令行工具，如果你想快速开发 Spring 应用程序，可以使用它。它允许你运行 Groovy 脚本，这意味着你有一个熟悉的类似 Java 的语法，而不需要那么多样板代码。你还可以引导一个新项目或为其编写自己的命令。

## 1. 安装 CLI

可以使用 SDKMAN 手动安装 Spring boot cli（命令行界面）！（SDK 管理器），或者如果你是 OSX 用户，则使用 Homebrew 或 MacPorts。有关全面的安装说明，请参见“入门”部分中的 *[getting-started.html](getting-started.html#getting-started.installing.cli)*。

## 2. 使用 CLI

一旦安装了 CLI，就可以通过输入`spring`并在命令行按 Enter 来运行它。如果你在没有任何参数的情况下运行`spring`，将显示一个帮助屏幕，如下所示：

```
$ spring
usage: spring [--help] [--version]
       <command> [<args>]

Available commands are:

  run [options] <files> [--] [args]
    Run a spring groovy script

  _... more command help is shown here_
```

你可以键入`spring help`来获取有关任何支持的命令的更多详细信息，如以下示例所示：

```
$ spring help run
spring run - Run a spring groovy script

usage: spring run [options] <files> [--] [args]

Option                     Description
------                     -----------
--autoconfigure [Boolean]  Add autoconfigure compiler
                             transformations (default: true)
--classpath, -cp           Additional classpath entries
--no-guess-dependencies    Do not attempt to guess dependencies
--no-guess-imports         Do not attempt to guess imports
-q, --quiet                Quiet logging
-v, --verbose              Verbose logging of dependency
                             resolution
--watch                    Watch the specified file for changes
```

`version`命令提供了一种快速的方法来检查你正在使用的 Spring 启动版本，如下所示：

```
$ spring version
Spring CLI v2.6.4
```

### 2.1.使用 CLI 运行应用程序

你可以使用`run`命令编译和运行 Groovy 源代码。 Spring 引导 CLI 是完全自包含的，因此不需要任何外部 Groovy 安装。

下面的示例展示了一个用 Groovy 编写的“Hello World”Web 应用程序：

你好。Groovy

```
@RestController
class WebApplication {

    @RequestMapping("/")
    String home() {
        "Hello World!"
    }

}

```

要编译和运行应用程序，请键入以下命令：

```
$ spring run hello.groovy
```

要将命令行参数传递给应用程序，请使用`--`将命令与“ Spring”命令参数分开，如以下示例所示：

```
$ spring run hello.groovy -- --server.port=9000
```

要设置 JVM 命令行参数，可以使用`JAVA_OPTS`环境变量，如以下示例所示：

```
$ JAVA_OPTS=-Xmx1024m spring run hello.groovy
```

|   |在 Microsoft Windows 上设置`JAVA_OPTS`时，请确保引用整个指令，例如`set "JAVA_OPTS=-Xms256m -Xmx2048m"`。<br/>这样做可以确保将值正确地传递给进程。|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### 2.1.1.推导出“抓取”依赖项

标准 Groovy 包含一个`@Grab`注释，它允许你声明对第三方库的依赖关系。这一有用的技术让 Groovy 以与 Maven 或 Gradle 相同的方式下载 JAR，但不需要使用构建工具。

Spring Boot 进一步扩展了这种技术，并试图根据你的代码推断出要“抓取”哪些库。例如，由于前面显示的`WebApplication`代码使用`@RestController`注释， Spring 引导抓取“ Tomcat”和“ Spring MVC”。

以下项目被用作“抓取提示”：

|项目|            Grabs             |
|----------------------------------------------------------|------------------------------|
|`JdbcTemplate`, `NamedParameterJdbcTemplate`, `DataSource`|      JDBC Application.       |
|`@EnableJms`|       JMS Application.       |
|`@EnableCaching`|     Caching abstraction.     |
|`@Test`|            JUnit.            |
|`@EnableRabbit`|          RabbitMQ.           |
|扩展`Specification`|         Spock test.          |
|`@EnableBatchProcessing`|        Spring Batch.         |
|`@MessageEndpoint` `@EnableIntegration`|     Spring Integration.      |
|`@Controller` `@RestController` `@EnableWebMvc`|Spring MVC + Embedded Tomcat. |
|`@EnableWebSecurity`|       Spring Security.       |
|`@EnableTransactionManagement`|Spring Transaction Management.|

|   |参见[`CompilerAutoConfiguration`]（https://github.com/ Spring-projects/ Spring-boot/tree/v2.6.4/ Spring-boot-project/ Spring-boot-cli/SRC/main/java/org/springframework/boot/cli/compiler/compiler/compilerautorfigation.java）的子类，在 Spring bootcli 源代码中了解定制是如何应用的。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### 2.1.2.推导出的“抓取”坐标

Spring Boot 扩展了 Groovy 的标准`@Grab`支持，允许你指定一个没有组或版本的依赖项（例如，`@Grab('freemarker')`）。这样做会参考 Spring Boot 的默认依赖关系元数据来推断工件的组和版本。

|   |默认的元数据与你使用的 CLI 版本绑定，<br/>只有当你移动到新版本的 CLI 时，它才会发生变化，让你控制依赖项的版本何时可能更改。<br/>在[appendix](dependency-versions.html#appendix.dependency-versions)中可以找到一个表，该表显示了默认元数据中包含的依赖项及其版本。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### 2.1.3.默认导入语句

为了帮助减少 Groovy 代码的大小，会自动包含几个`import`语句。注意前面的示例是如何引用`@Component`、`@RestController`和`@RequestMapping`而不需要使用完全限定的名称或`import`语句的。

|   |许多 Spring 注释在不使用`import`语句的情况下工作。<br/>在添加导入之前，尝试运行你的应用程序以查看失败的原因。|
|---|-----------------------------------------------------------------------------------------------------------------------------------------|

#### 2.1.4.自动主法

与等效的 Java 应用程序不同，你不需要在`Groovy`脚本中包含`public static void main(String[] args)`方法。将自动创建`SpringApplication`，你的编译代码将充当`source`。

#### 2.1.5.自定义依赖管理

默认情况下，CLI 在解析`@Grab`依赖关系时使用在`spring-boot-dependencies`中声明的依赖关系管理。可以通过使用`@DependencyManagementBom`注释来配置附加的依赖项管理，该管理覆盖了默认的依赖项管理。注释的值应该指定一个或多个 Maven boms 的坐标（`groupId:artifactId:version`）。

例如，考虑以下声明：

```
@DependencyManagementBom("com.example.custom-bom:1.0.0")

```

前面的声明在 Maven 存储库中的`com/example/custom-versions/1.0.0/`下获取`custom-bom-1.0.0.pom`。

当你指定多个 BOM 时，它们将按照你声明它们的顺序应用，如下例所示：

```
@DependencyManagementBom([
    "com.example.custom-bom:1.0.0",
    "com.example.another-bom:1.0.0"])

```

前面的示例表明，`another-bom`中的依赖管理重写了`custom-bom`中的依赖管理。

你可以在任何可以使用`@DependencyManagementBom`的地方使用`@Grab`。然而，为了确保依赖管理的一致顺序，你可以在应用程序中最多使用`@DependencyManagementBom`一次。

### 2.2.具有多个源文件的应用程序

你可以在所有接受文件输入的命令中使用“shell globbing”。这样做可以让你从一个目录中使用多个文件，如下面的示例所示：

```
$ spring run *.groovy
```

### 2.3.打包你的应用程序

你可以使用`jar`命令将你的应用程序打包成一个自包含的可执行文件 jar，如下例所示：

```
$ spring jar my-app.jar *.groovy
```

jar 结果包含通过编译应用程序产生的类和应用程序的所有依赖项，这样就可以使用`java -jar`运行它。 jar 文件还包含来自应用程序 Classpath 的条目。可以使用`--include`和`--exclude`来添加和删除 jar 的显式路径。两者都是用逗号分隔的，并且都接受前缀，以“+”和“-”的形式表示它们应该从默认值中删除。默认值包括以下内容：

```
public/**, resources/**, static/**, templates/**, META-INF/**, *
```

默认排除如下：

```
.*, repository/**, build/**, target/**, **/*.jar, **/*.groovy
```

有关详细信息，请在命令行上键入`spring help jar`。

### 2.4.初始化一个新项目

`init`命令允许你在不离开 shell 的情况下使用[start.spring.io](https://start.spring.io)创建一个新项目，如下面的示例所示：

```
$ spring init --dependencies=web,data-jpa my-project
Using service at https://start.spring.io
Project extracted to '/Users/developer/example/my-project'
```

前面的示例使用基于 Maven 的项目创建`my-project`目录，该项目使用`spring-boot-starter-web`和`spring-boot-starter-data-jpa`。你可以使用`--list`标志列出服务的功能，如以下示例所示：

```
$ spring init --list
=======================================
Capabilities of https://start.spring.io
=======================================

Available dependencies:
-----------------------
actuator - Actuator: Production ready features to help you monitor and manage your application
...
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
websocket - Websocket: Support for WebSocket development
ws - WS: Support for Spring Web Services

Available project types:
------------------------
gradle-build -  Gradle Config [format:build, build:gradle]
gradle-project -  Gradle Project [format:project, build:gradle]
maven-build -  Maven POM [format:build, build:maven]
maven-project -  Maven Project [format:project, build:maven] (default)

...
```

`init`命令支持许多选项。有关更多详细信息，请参见`help`输出。例如，下面的命令创建了一个使用 Java8 和`war`打包的 Gradle 项目：

```
$ spring init --build=gradle --java-version=1.8 --dependencies=websocket --packaging=war sample-app.zip
Using service at https://start.spring.io
Content saved to 'sample-app.zip'
```

### 2.5.使用嵌入式外壳

Spring 引导包括用于 bash 和 zsh shell 的命令行完成脚本。如果不使用这两个 shell 中的任何一个（也许你是 Windows 用户），则可以使用`shell`命令来启动一个集成的 shell，如下例所示：

```
$ spring shell
Spring Boot (v2.6.4)
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
```

在嵌入的 shell 中，你可以直接运行其他命令：

```
$ version
Spring CLI v2.6.4
```

嵌入式外壳支持 ANSI 颜色输出以及`tab`补全。如果需要运行本机命令，可以使用`!`前缀。要退出嵌入的 shell，请按`ctrl-c`。

### 2.6.向 CLI 添加扩展

你可以使用`install`命令向 CLI 添加扩展。该命令以`group:artifact:version`的格式接受一组或多组工件坐标，如以下示例所示：

```
$ spring install com.example:spring-boot-cli-extension:1.0.0.RELEASE
```

除了安装由你提供的坐标标识的工件外，还安装了所有工件的依赖关系。

要卸载依赖项，请使用`uninstall`命令。与`install`命令一样，它以`group:artifact:version`的格式接受一组或多组工件坐标，如以下示例所示：

```
$ spring uninstall com.example:spring-boot-cli-extension:1.0.0.RELEASE
```

它卸载由你提供的坐标和它们的依赖关系所标识的工件。

要卸载所有附加依赖项，可以使用`--all`选项，如以下示例所示：

```
$ spring uninstall --all
```

## 3. 使用 Groovy Beans DSL 开发应用程序

Spring Framework4.0 对`beans{}`“DSL”（借鉴自[Grails](https://grails.org/)）具有原生支持，并且你可以通过使用相同的格式在 Groovy 应用程序脚本中嵌入 Bean 定义。这有时是一种很好的方式，可以包含外部特性，比如中间件声明，如下例所示：

```
@Configuration(proxyBeanMethods = false)
class Application implements CommandLineRunner {

    @Autowired
    SharedService service

    @Override
    void run(String... args) {
        println service.message
    }

}

import my.company.SharedService

beans {
    service(SharedService) {
        message = "Hello World"
    }
}

```

你可以在同一个文件中将类声明与`beans{}`混合在一起，只要它们保持在顶层，或者，如果你愿意，可以将 bean DSL 放在一个单独的文件中。

## 4. 使用 settings.xml 配置 CLI

Spring 引导 CLI 使用 Maven resolver（ Maven 的依赖项解析引擎）来解析依赖项。CLI 使用`~/.m2/settings.xml`中的 Maven 配置来配置 Maven 解析器。以下配置设置由 CLI 执行：

* 离线

* 镜子

* 服务器

* 代理

* 配置文件

  * 激活

  * 存储库

* 活动配置文件

有关更多信息，请参见[Maven’s settings documentation](https://maven.apache.org/settings.html)。

## 5. 接下来要读什么？

GitHub 存储库中有一些[Groovy 脚本示例](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot-cli/samples)可用，你可以使用它们来尝试 Spring 引导 CLI。在[源代码](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot-cli/src/main/java/org/springframework/boot/cli)中也有大量的 Javadoc。

如果你发现你已经达到了 CLI 工具的极限，那么你可能希望将你的应用程序转换为完整的 Gradle 或 Maven 构建的“Groovy 项目”。下一节将介绍 Spring boot 的“[构建工具插件](build-tool-plugins.html#build-tool-plugins)”，你可以在 Gradle 或 Maven 中使用它。
