内容简介:随着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/ko
随着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 <b>class</b> SampleSpringKotlinMicroserviceApplication fun main(args: Array<String>) { runApplication<SampleSpringKotlinMicroserviceApplication>(*args) }
我们的示例应用程序非常简单。它公开了一些REST端点,为模型对象提供CRUD操作。即使在这个代码控制器实现的代码片段中,您也可以看到一些不错的Kotlin功能。我们可以使用缩短的函数声明和推断的返回类型。注释@PathVariable不需要任何参数。输入参数名称被视为与变量名称相同。当然,我们使用与Java相同的注释。在Kotlin中,必须在构造函数中初始化声明为非null类型的每个属性。所以,如果你使用依赖注入初始化它,它必须声明为lateinit。这些在PersonController中实施:
@RestController @RequestMapping(<font>"/persons"</font><font>) <b>class</b> PersonController { @Autowired lateinit <b>var</b> repository: PersonRepository @GetMapping(</font><font>"/{id}"</font><font>) 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(</font><font>"/{id}"</font><font>) fun remove(@PathVariable id: Int): Boolean = repository.removeById(id) } </font>
Kotlin自动为声明为的类属性生成getter和setter var。此外,如果你声明模型作为数据类它产生equals,hashCode和toString方法。我们的模型类的声明Person非常简洁,如下所示。
data <b>class</b> Person(<b>var</b> id: Int?, <b>var</b> name: String, <b>var</b> age: Int, <b>var</b> gender: Gender)
我已经实现了自己的内存存储库类。我使用Kotlin扩展来操作元素列表。这个内置的Kotlin功能类似于Java流,不同之处在于您不必在Collection和之间执行任何转换Stream。
@Repository <b>class</b> PersonRepository { val persons: MutableList<Person> = ArrayList() fun findById(id: Int): Person? { <b>return</b> persons.singleOrNull { it.id == id } } fun findAll(): List<Person> { <b>return</b> persons } fun save(person: Person): Person { person.id = (persons.maxBy { it.id!! }?.id ?: 0) + 1 persons.add(person) <b>return</b> person } fun update(person: Person): Person { val index = persons.indexOfFirst { it.id == person.id } <b>if</b> (index >= 0) { persons[index] = person } <b>return</b> person } fun removeById(id: Int): Boolean { <b>return</b> 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 . 它为我们揭示了所有有趣的信息。
{ <font>"git"</font><font>:{ </font><font>"commit"</font><font>:{ </font><font>"time"</font><font>:</font><font>"2019-01-14T16:20:31Z"</font><font>, </font><font>"id"</font><font>:</font><font>"f7cb437"</font><font> }, </font><font>"branch"</font><font>:</font><font>"master"</font><font> }, </font><font>"build"</font><font>:{ </font><font>"version"</font><font>:</font><font>"1.0-SNAPSHOT"</font><font>, </font><font>"artifact"</font><font>:</font><font>"sample-spring-kotlin-microservice"</font><font>, </font><font>"name"</font><font>:</font><font>"sample-spring-kotlin-microservice"</font><font>, </font><font>"group"</font><font>:</font><font>"pl.piomin.services"</font><font>, </font><font>"time"</font><font>:</font><font>"2019-01-15T09:18:48.836Z"</font><font> } } </font>
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 <b>class</b> SwaggerConfig { @Autowired lateinit <b>var</b> build: Optional<BuildProperties> @Autowired lateinit <b>var</b> git: Optional<GitProperties> @Bean fun api(): Docket { <b>var</b> version = <font>"1.0"</font><font> <b>if</b> (build.isPresent && git.isPresent) { <b>var</b> buildInfo = build.get() <b>var</b> gitInfo = git.get() version = </font><font>"${buildInfo.version}-${gitInfo.shortCommitId}-${gitInfo.branch}"</font><font> } <b>return</b> Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo(version)) .select() .apis(RequestHandlerSelectors.any()) .paths{ it.equals(</font><font>"/persons"</font><font>)} .build() .useDefaultResponseMessages(false) .forCodeGeneration(<b>true</b>) } @Bean fun uiConfig(): UiConfiguration { <b>return</b> UiConfiguration(java.lang.Boolean.TRUE, java.lang.Boolean.FALSE, 1, 1, ModelRendering.MODEL, java.lang.Boolean.FALSE, DocExpansion.LIST, java.lang.Boolean.FALSE, <b>null</b>, OperationsSorter.ALPHA, java.lang.Boolean.FALSE, TagsSorter.ALPHA, UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS, <b>null</b>) } <b>private</b> fun apiInfo(version: String): ApiInfo { <b>return</b> ApiInfoBuilder() .title(</font><font>"API - Person Service"</font><font>) .description(</font><font>"Persons Management"</font><font>) .version(version) .build() } } </font>
文档在/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><b>true</b></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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Is Parallel Programming Hard, And, If So, What Can You Do About
Paul E. McKenney
The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!