随着Kotlin语言的普及,它更常用于Spring Boot来构建后端服务。从版本5开始,Spring Framework引入了对Kotlin的一流支持。在本文中,我将向您展示使用Kotlin和Spring Boot 2进行微服务构建的示例。我将描述Spring Boot的一些有趣功能,在构建基于REST的后端微服务时,可以将其视为一组良好实践。
1.配置和依赖
要在Maven项目使用Kotlin你必须包括插件kotlin-maven-plugin,并且/src/main/kotlin,/src/test/kotlin目录生成配置。我们还将-Xjsr305编译器标志设置为strict。此选项负责检查对JSR-305注释的支持(例如@NotNull注释)。
<build> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory> <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory> <plugins> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <configuration> <args> <arg>-Xjsr305=strict</arg> </args> <compilerPlugins> <plugin>spring</plugin> </compilerPlugins> </configuration> <dependencies> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-allopen</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> </plugin> </plugins> </build>
|
我们还应该包括一些像kotlin-stdlib-jdk8和的核心Kotlin库kotlin-reflect。默认情况下,我们可以在start.spring.io上配置Kotlin项目,生成pom.xml。对于基于REST的应用程序,您还需要用于JSON序列化/反序列化的Jackson库。当然,我们必须包括用于Web应用程序的Spring启动器以及负责提供管理端点的Actuator。<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-kotlin</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-reflect</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib
|
我们使用最新的稳定版Spring Boot和Kotlin 1.2.71
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> <kotlin.version>1.2.71</kotlin.version> </properties>
|
2.架构应用
让我们从基础开始。如果您熟悉Spring Boot和Java,最大的区别在于主类声明。您将runApplication在Spring Boot应用程序类之外调用方法。主要类与Java中的相同,使用注释@SpringBootApplication。
@SpringBootApplication class SampleSpringKotlinMicroserviceApplication fun main(args: Array<String>) { runApplication<SampleSpringKotlinMicroserviceApplication>(*args) }
|
我们的示例应用程序非常简单。它公开了一些REST端点,为模型对象提供CRUD操作。即使在这个代码控制器实现的代码片段中,您也可以看到一些不错的Kotlin功能。我们可以使用缩短的函数声明和推断的返回类型。注释@PathVariable不需要任何参数。输入参数名称被视为与变量名称相同。当然,我们使用与Java相同的注释。在Kotlin中,必须在构造函数中初始化声明为非null类型的每个属性。所以,如果你使用依赖注入初始化它,它必须声明为lateinit。这些在PersonController中实施:
@RestController @RequestMapping("/persons") class PersonController { @Autowired lateinit var repository: PersonRepository @GetMapping("/{id}") fun findById(@PathVariable id: Int): Person? = repository.findById(id) @GetMapping fun findAll(): List<Person> = repository.findAll() @PostMapping fun add(@RequestBody person: Person): Person = repository.save(person) @PutMapping fun update(@RequestBody person: Person): Person = repository.update(person) @DeleteMapping("/{id}") fun remove(@PathVariable id: Int): Boolean = repository.removeById(id) }
|
Kotlin自动为声明为的类属性生成getter和setter var。此外,如果你声明模型作为数据类它产生equals,hashCode和toString方法。我们的模型类的声明Person非常简洁,如下所示。data class Person(var id: Int?, var name: String, var age: Int, var gender: Gender)
|
我已经实现了自己的内存存储库类。我使用Kotlin扩展来操作元素列表。这个内置的Kotlin功能类似于Java流,不同之处在于您不必在Collection和之间执行任何转换Stream。
@Repository class PersonRepository { val persons: MutableList<Person> = ArrayList() fun findById(id: Int): Person? { return persons.singleOrNull { it.id == id } } fun findAll(): List<Person> { return persons } fun save(person: Person): Person { person.id = (persons.maxBy { it.id!! }?.id ?: 0) + 1 persons.add(person) return person } fun update(person: Person): Person { val index = persons.indexOfFirst { it.id == person.id } if (index >= 0) { persons[index] = person } return person } fun removeById(id: Int): Boolean { return persons.removeIf { it.id == id } } }
|
3. 启用执行器端点
由于我们已将Spring Boot starter与Actuator一起包含在应用程序代码中,因此我们可以利用其生产就绪功能。Spring Boot Actuator为您提供了非常强大的工具来监控和管理您的应用程序。您可以提供高级健康检查,信息端点或将指标发送到众多监控系统,如InfluxDB。在包含Actuator工件之后,我们唯一要做的就是通过HTTP为我们的应用程序启用其所有端点。
management.endpoints.web.exposure.include: '*'
我们可以自定义Actuator端点,以提供有关我们应用的更多详细信息。一个好的做法是将有关版本和git提交的信息公开给info端点。像往常一样,Spring Boot为这些功能提供了自动配置,因此我们唯一需要做的就是包含一些Maven插件来构建配置pom.xml。build-info设定的目标是spring-boot-maven-plugin强制它生成包含有关版本的基本信息的属性文件。该文件位于目录中META-INF/build-info.properties。插件git-commit-id-plugin将git.properties在根目录中生成文件。
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>build-info</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>pl.project13.maven</groupId> <artifactId>git-commit-id-plugin</artifactId> <configuration> <failOnNoGitDirectory>false</failOnNoGitDirectory> </configuration> </plugin>
|
现在,您应该使用mvn clean install命令构建应用程序,然后运行它。
$ java -jar target\sample-spring-kotlin-microservice-1.0-SNAPSHOT.jar
该info端点是在地址http://localhost:8080/actuator/info. 它为我们揭示了所有有趣的信息。
{ "git":{ "commit":{ "time":"2019-01-14T16:20:31Z", "id":"f7cb437" }, "branch":"master" }, "build":{ "version":"1.0-SNAPSHOT", "artifact":"sample-spring-kotlin-microservice", "name":"sample-spring-kotlin-microservice", "group":"pl.piomin.services", "time":"2019-01-15T09:18:48.836Z" } }
|
4.启用API文档
构建信息和git属性可以很容易地注入到应用程序代码中。在某些情况下它可能很有用。其中一种情况是您已启用自动生成的API文档。最常用的工具是Swagger。您可以使用SpringFox Swagger项目轻松地将Swagger2与Spring Boot集成。首先,您需要包含以下依赖项pom.xml。
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
|
然后,您应该通过使用注释配置类来启用Swagger @EnableSwagger2。所需的信息是在BuildProperties和GitProperties,我们只需将它们注入到Swagger配置类中,如下所示。我们将它们设置为可选,以防止应用程序启动失败,以防它们不存在于类路径中。
@Configuration @EnableSwagger2 class SwaggerConfig { @Autowired lateinit var build: Optional<BuildProperties> @Autowired lateinit var git: Optional<GitProperties> @Bean fun api(): Docket { var version = "1.0" if (build.isPresent && git.isPresent) { var buildInfo = build.get() var gitInfo = git.get() version = "${buildInfo.version}-${gitInfo.shortCommitId}-${gitInfo.branch}" } return Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo(version)) .select() .apis(RequestHandlerSelectors.any()) .paths{ it.equals("/persons")} .build() .useDefaultResponseMessages(false) .forCodeGeneration(true) } @Bean fun uiConfig(): UiConfiguration { return UiConfiguration(java.lang.Boolean.TRUE, java.lang.Boolean.FALSE, 1, 1, ModelRendering.MODEL, java.lang.Boolean.FALSE, DocExpansion.LIST, java.lang.Boolean.FALSE, null, OperationsSorter.ALPHA, java.lang.Boolean.FALSE, TagsSorter.ALPHA, UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS, null) } private fun apiInfo(version: String): ApiInfo { return ApiInfoBuilder() .title("API - Person Service") .description("Persons Management") .version(version) .build() } }
|
文档在/swagger-ui.html路径下可用。除API文档外,还显示有关应用程序版本,git commit id和分支名称的完整信息。5.选择您的应用服务器
Spring Boot Web可以在三个不同的嵌入式服务器上运行:Tomcat,Jetty或Undertow。默认情况下,它使用Tomcat。要更改默认服务器,您只需要包含合适的Spring Boot启动器并排除spring-boot-starter-tomcat。良好的做法可能是在应用程序构建期间启用服务器之间的切换。您可以通过声明Maven配置文件来实现它,如下所示。
<profiles> <profile> <id>tomcat</id> <activation> <activeByDefault>true</activeByDefault> </activation> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </profile> <profile> <id>jetty</id> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> </dependencies> </profile> <profile> <id>undertow</id> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> </dependencies> </profile> </profiles>
|
现在,如果您想为应用程序启用除Tomcat之外的其他服务器,则应在Maven构建期间激活相应的配置文件。
$ mvn clean install -Pjetty
示例应用程序源代码在GitHub的存储库https://github.com/piomin/sample-spring-kotlin-microservice.git