Spring Boot 入门

Spring Boot 介绍

Spring Boot 是 Java 世界中最流行的应用程序构建框架。Spring Boot 是一种基于约定而非配置的方法,用于构建基于 Spring 框架的应用程序。

使用 Spring Boot,你可以构建单体应用程序、微服务、serverless 应用程序、批处理应用程序等不同类型的应用程序。

让我们快速了解一下 Spring Boot 有哪些关键功能使其如此受欢迎。

Spring Boot 关键特性

自动配置

Spring Boot 对应用程序有自己的约定,它会根据默认约定自动配置组件(又称 Bean),而不需要你显式配置所有内容。不过,如果需要,你可以通过各种方式自定义或覆盖 Bean 配置。

例如,如果添加 spring-boot-starter-data-jpa 依赖,它将添加 Hibernate 作为 JPA 实现,因为它是最常用的 JPA 提供程序。此外,Spring Boot 还会自动配置使用 Spring Data Jpa 所需的组件,如 DataSourceEntityManagerFactoryPlatformTransactionManager 等。如果 classpath 中存在内存 JDBC 驱动程序(如 H2HSQL),那么 Spring Boot 将自动配置基于内存的数据源。

如果要使用 MySQLPostgresql 等非内存数据库,可以添加相应的 JDBC 驱动程序 jar,并在 application.properties 文件中配置 JDBC 连接参数。然后,Spring Boot 将使用这些属性来配置 DataSource Bean,而不是使用默认的内存数据库。你甚至可以使用 @Bean 注解自行配置 DataSource Bean,然后 Spring Boot 将回退并使用你配置的 DataSource Bean,而不是自动配置。

有了 Spring Boot 的自动配置功能,对 Spring 应用程序配置的需求就大大减少了。

约定大于配置

Spring Boot 依靠各种默认约定来自动配置应用程序。

例如,在大多数基于 Spring(不是基于 Spring Boot)的应用程序中,我们使用配置属性并注册 PropertySourcesPlaceholderConfigurer Bean。在 Spring Boot 中,你可以将配置属性放在 src/main/resources/application.properties 文件中,Spring Boot 将自动注册 PropertySourcesPlaceholderConfigurer Bean,并加载该文件中的属性。你不必明确指定属性文件名。

同样,你可能希望根据环境(devqastagingprod)为属性配置不同的值。你可以在 application-{profile}.properties 中配置配置文件属性,其中配置文件可以是 devqastagingprod。然后,只需启用所需的配置文件,Spring Boot 就能从特定的配置文件属性文件中读取值。

Spring Boot 非常灵活,可以根据项目或团队的偏好自定义这些约定。

依赖的版本管理

通常情况下,Spring Boot 应用程序继承自 spring-boot-starter-parent,而 spring-boot-starter-parent 已配置了所有兼容的依赖的版本,因此你不必再检查哪个依赖的版本与哪个版本的 Spring 兼容。你可以查看 org.springframework.boot:spring-boot-dependencies 模块的 pom.xml,了解预先配置的所有依赖。

生产准备就绪的监控功能

监控是任何在生产中运行的应用程序的一个重要方面。Spring Boot 通过 Actuator 提供了生产就绪监控功能。你可以通过 Actuator REST 端点获取内存使用情况、磁盘空间、各种组件的健康检查等应用程序运行时信息。Actuator 在运行状态下使用 Micrometer,你可以使用它将所有这些应用程序指标导出到各种监控服务,如 PrometheusDatadogInflux 等。

嵌入式服务器的支持

传统上,基于 Java 的 web 应用程序是以 war 文件的形式构建的,然后部署到 servlet 容器或 TomcatWildflyWebSphere 等应用服务器上。更现代的方法是将服务器运行时嵌入到应用程序本身,这样就可以直接运行应用程序,而无需从外部安装和配置服务器。

Spring Boot 支持嵌入 Tomcat、Jetty、Undertow 等 servlet 容器,你可以,以独立于服务器的方式定制各种服务器属性。Spring Boot 还提供各种特定于服务器的自定义属性。

Spring 生态

Spring Boot 拥有庞大的项目生态系统,可支持各种类型的应用程序。

  • SpringMVC 和 Spring WebFlux:你可以使用 SpringMVC 或 Spring WebFlux 构建传统的 web 应用程序和 REST API。
  • Spring Data:Spring Data 为 ORM 和 NoSQL 数据访问库提供了高级抽象,因此你无需重复实现模板化的 CRUD 操作。
  • Spring Security:你可以使用 Spring Security 实现身份验证和授权。它还支持实现基于 OAuth 2.0 的认证和授权。
  • Spring Batch:你可以使用 SpringBatch 构建强大的批处理应用程序
  • Spring Integration:Spring Integration 实现了许多企业集成模式,可用于与第三方服务集成。
  • Spring Cloud:Spring Cloud 支持按照 12 要素应用程序 原则构建云原生应用程序。
  • Spring Cloud Streams:你可以构建数据管道,处理 Kafka 等基于流的数据源。

还有更多有趣的项目。更多 Spring 生态系统项目,请参见 https://spring.io/projects

让我们使用 Spring Boot 构建一个简单的 REST API 应用程序,并探索它的一些功能。

创建 Spring Boot 应用

可以使用 Spring InitializrSpring Tool 或带有 Spring Boot PluginIntelliJ IDEANetBeans IDE 创建 Spring Boot 应用程序。

我们将使用 Spring Initializr 并提供以下项目元数据。

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 3.1.2
  • Project Metadata:
    • Group: com.sivalabs
    • Artifact: spring-boot-helloworld
    • Name: spring-boot-helloworld
    • Description: Spring Boot HelloWorld
    • Package name: com.sivalabs.helloworld
    • Packaging: jar
    • Java: 17
  • 点击 ADD DEPENDENCIES,添加 Spring Web, Lombok starter。
  • 点击 GENERATE

生成的 Spring Boot 应用程序将被下载到本地。你可以解压缩并将项目导入你的 IDE。我将使用 IntelliJ IDEA,但你也可以使用任何你喜欢的 IDE。

使用 Spring Boot 开发简单的 REST API

我们要构建的是一个简单的 REST API,其中有一个端点 GET /api/hello?name={name},返回 JSON 响应 { "greeting" : "Hello {name}"}。我们不想硬编码问候语前缀 "Hello",而是希望它是可配置的。

让我们从创建响应 model 类 GreetingResponse 开始,如下所示:

// src/main/java/com/sivalabs/helloworld/GreetingResponse.java

record GreetingResponse(String greeting){}

接下来,创建 ApplicationProperties 类来绑定应用程序配置参数。

// src/main/java/com/sivalabs/helloworld/ApplicationProperties.java

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app") // (1)
@Setter
@Getter
public class ApplicationProperties {
    private String greeting = "Hello";
    private String defaultName = "World";
}
  1. 我们将 application.properties 文件中带有通用前缀 app. 的属性绑定到 ApplicationProperties 类字段中。

创建 GreetingService 并实现 sayHello(String name) 方法如下:

// src/main/java/com/sivalabs/helloworld/GreetingService.java

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service // (1)
@RequiredArgsConstructor // (2)
public class GreetingService {
    private final ApplicationProperties properties;  // (3)

    public String sayHello(String name) {
        String s = name == null ? properties.getDefaultName(): name;
        return String.format("%s %s", properties.getGreeting(), s);
    }
}
  1. 使用 @Service 注解将 GreetingService 声明为 Spring Bean。
  2. Lombok 的 @RequiredArgsConstructor 注解将生成一个包含所有 final 属性的构造函数。在本例中,它将生成一个带有 ApplicationProperties 参数的构造函数。
  3. 注入 ApplicationProperties 实例作为 GreetingService Bean 的依赖。

创建 HelloWorldController 并实现 GET /api/hello API 端点,如下所示:

// src/main/java/com/sivalabs/helloworld/HelloWorldController.java

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController // (1)
@RequiredArgsConstructor
@Slf4j // (2)
public class HelloWorldController {
    private final GreetingService greetingService;

    @GetMapping("/api/hello") // (3)
    public GreetingResponse sayHello(
            @RequestParam(name = "name", required = false) String name) {
        log.info("Say Hello to Name: {}", name);
        String greeting = greetingService.sayHello(name);
        return new GreetingResponse(greeting);
    }
}
  1. 将类声明为 Spring Controller,并带有 request handler 方法。
  2. 使用 Lomkok 的 @Slf4j 注解自动创建 SLF4J Logger 实例,而不是手动创建 private static final Logger log = LoggerFactory.getLogger(HelloWorldController.class);
  3. sayHello() 方法被注解为 @GetMapping("/api/hello"),表示它是 HTTP GET /api/hello URL 的请求处理方法。

让我们在 src/main/resources/application.properties 中配置如下属性:

app.greeting=Hello
app.default-name=World

最后,我们需要使用 @EnableConfigurationProperties 启用配置属性绑定,如下所示:

// src/main/java/com/sivalabs/helloworld/SpringBootHelloWorldApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties({ApplicationProperties.class}) // (1)
//@ConfigurationPropertiesScan // (2)
public class SpringBootHelloWorldApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootHelloWorldApplication.class, args);
    }
}
  1. 明确启用 ApplicationProperties 类的配置属性绑定。如果有更多这样的配置绑定类,我们可以一一列出。
  2. 我们可以使用 @ConfigurationPropertiesScan 注解来扫描所有带有 @ConfigurationProperties 注解的类,而不是显式地指定所有配置绑定类。

我们只需运行 SpringBootHelloWorldApplication 中的 main() 方法,就能在 IDE 中运行应用程序。

使用 Maven 和 Gradle 运行程序

Spring Boot Maven 和 Gradle 插件提供了无需构建构件(jar 或 war)即可运行应用程序的功能。

Maven:

./mvnw spring-boot:run

Gradle:

./gradlew bootRun

以 FatJar 方式运行程序

我们可以将 Spring Boot 应用程序构建为 fat-jar,然后使用 java -jar 命令运行它。

Maven:

$ ./mvnw clean package
$ java -jar target/spring-boot-helloworld-0.0.1-SNAPSHOT.jar

Gradle:

$ ./gradlew clean build
$ java -jar build/libs/spring-boot-helloworld-0.0.1-SNAPSHOT.jar

我们可以使用 cURL 对 API 端点进行如下验证:

$ curl http://localhost:8080/api/hello
{"greeting":"Hello World"}

$ curl http://localhost:8080/api/hello?name=Siva
{"greeting":"Hello Siva"}

总结

我们已经了解了 Spring Boot、其生态系统和一些核心功能,并且使用 Spring Boot 创建了一个简单的 REST API,并使用 cURL 进行了测试。


参考:https://www.sivalabs.in/getting-started-with-spring-boot/