首页 > 编程语言 > 使用kotlin集成springboot开发的超详细教程
2023
01-31

使用kotlin集成springboot开发的超详细教程

目前大多数都在使用java集成 springboot进行开发,本文演示仅仅将 java换成 kotlin,其他不变的情况下进行开发。

一、安装支持插件

idea中安装 kotlin插件(大多数情况下会默认安装了)

安装插件

二、maven配置 注意

kotlin目前不支持 lombok所以不能使用或引用 lombok相关的插件或依赖包,下面是一个排除示例,同时也不支持 maven-enforcer-plugin

<dependency>
            <groupId>com.ayouran.common</groupId>
            <artifactId>a-common</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <exclusions>
                 <exclusion>
                       <groupId>org.projectlombok</groupId>
                       <artifactId>lombok</artifactId>
                 </exclusion>
            </exclusions>
</dependency>

maven的属性配置

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <kotlin.version>1.3.21</kotlin.version>
        <!--增量编译-->
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <!--关闭协程编译警告-->
        <experimentalCoroutines>enable</experimentalCoroutines>
        <spring-boot.version>2.2.4.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
        <swagger.version>2.7.0</swagger.version>
        <main.class>com.lc.github.KotlinDemoApplication</main.class>
        <querydsl.version>4.2.1</querydsl.version>
        <mapstruct.version>1.3.1.Final</mapstruct.version>
    </properties>

必要的依赖

<dependencies>
       <!--反射支持包,不需要可以去掉-->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
     <!--jdk8下的 kotlin支持包-->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>

编译部分

 <build>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <configuration>
                    <correctErrorTypes>true</correctErrorTypes>
                    <languageVersion>${kotlin.language.version}</languageVersion>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>kapt</id>
                        <goals>
                            <goal>kapt</goal>
                        </goals>
                        <configuration>
                            <correctErrorTypes>true</correctErrorTypes>
                            <sourceDirs>
                                <sourceDir>src/main/kotlin</sourceDir>
                                <sourceDir>src/main/java</sourceDir>
                            </sourceDirs>
                            <annotationProcessorPaths>
                                <annotationProcessorPath>
                                    <groupId>com.google.dagger</groupId>
                                    <artifactId>dagger-compiler</artifactId>
                                    <version>2.9</version>
                                </annotationProcessorPath>
                                <annotationProcessorPath>
                                    <groupId>com.querydsl</groupId>
                                    <artifactId>querydsl-apt</artifactId>
                                    <version>${querydsl.version}</version>
                                    <classifier>jpa</classifier>
                                </annotationProcessorPath>
                                <annotationProcessorPath>
                                    <groupId>org.mapstruct</groupId>
                                    <artifactId>mapstruct-processor</artifactId>
                                    <version>${mapstruct.version}</version>
                                </annotationProcessorPath>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                    <execution>
                        <id>compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/main/kotlin</sourceDir>
                                <sourceDir>src/main/java</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-kapt</id>
                        <goals>
                            <goal>test-kapt</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/test/kotlin</sourceDir>
                                <sourceDir>src/test/java</sourceDir>
                            </sourceDirs>
                            <annotationProcessorPaths>
                                <annotationProcessorPath>
                                    <groupId>com.google.dagger</groupId>
                                    <artifactId>dagger-compiler</artifactId>
                                    <version>2.9</version>
                                </annotationProcessorPath>
                                <annotationProcessorPath>
                                    <groupId>com.querydsl</groupId>
                                    <artifactId>querydsl-apt</artifactId>
                                    <version>${querydsl.version}</version>
                                    <classifier>jpa</classifier>
                                </annotationProcessorPath>
                                <annotationProcessorPath>
                                    <groupId>org.mapstruct</groupId>
                                    <artifactId>mapstruct-processor</artifactId>
                                    <version>${mapstruct.version}</version>
                                </annotationProcessorPath>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/test/kotlin</sourceDir>
                                <sourceDir>src/test/java</sourceDir>
                                <sourceDir>target/generated-sources/kapt/test</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <proc>none</proc>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <arg>-Amapstruct.suppressGeneratorTimestamp=true</arg>
                        <arg>-Amapstruct.defaultComponentModel=spring</arg>
                    </compilerArgs>
                </configuration>
                <executions>
                    <!-- Replacing default-compile as it is treated specially by maven -->
                    <execution>
                        <id>default-compile</id>
                        <phase>none</phase>
                    </execution>
                    <!-- Replacing default-testCompile as it is treated specially by maven -->
                    <execution>
                        <id>default-testCompile</id>
                        <phase>none</phase>
                    </execution>
                    <execution>
                        <id>java-compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>java-test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>${main.class}</mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

javakotlin混合的情况,在上面的 <plugins>下加入下面的编译插件

<plugin>
                            <groupId>org.apache.maven.plugins</groupId>
                            <artifactId>maven-compiler-plugin</artifactId>
                            <version>3.8.1</version>
                            <configuration>
                                <proc>none</proc>
                                <source>${java.version}</source>
                                <target>${java.version}</target>
                                <annotationProcessorPaths>
                                    <path>
                                        <groupId>org.mapstruct</groupId>
                                        <artifactId>mapstruct-processor</artifactId>
                                        <version>${mapstruct.version}</version>
                                    </path>
                                </annotationProcessorPaths>
                                <compilerArgs>
                                    <arg>-Amapstruct.suppressGeneratorTimestamp=true</arg>
                                    <arg>-Amapstruct.defaultComponentModel=spring</arg>
                                </compilerArgs>
                            </configuration>
                            <executions>
                                <!-- Replacing default-compile as it is treated specially by maven -->
                                <execution>
                                    <id>default-compile</id>
                                    <phase>none</phase>
                                </execution>
                                <!-- Replacing default-testCompile as it is treated specially by maven -->
                                <execution>
                                    <id>default-testCompile</id>
                                    <phase>none</phase>
                                </execution>
                                <execution>
                                    <id>java-compile</id>
                                    <phase>compile</phase>
                                    <goals>
                                        <goal>compile</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>java-test-compile</id>
                                    <phase>test-compile</phase>
                                    <goals>
                                        <goal>testCompile</goal>
                                    </goals>
                                </execution>
                            </executions>
                        </plugin>

maven配置集成了 querydslmapstructdagger2的编译,基本上能满足常规的使用

三、创建入口函数类

创建入口函数

四、编写入口函数

springboot的启动方法及 swagger的配置

@EnableAsync
@EnableSwagger2
@EnableScheduling
@SpringBootApplication
class KotlinDemoApplication : CommandLineRunner {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            SpringApplication.run(KotlinDemoApplication::class.java, *args)
        }
    }

    @Bean
    fun api(): Docket {
        return Docket(DocumentationType.SWAGGER_2)
                .ignoredParameterTypes(Session::class.java)
                .select()
//                .apis(RequestHandlerSelectors.any())
                .apis(RequestHandlerSelectors.basePackage("com.ayouran.flow.controllers"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(ApiInfoBuilder()
                        .description("ayouram-flow相关API")
                        .title("ayouram-flow")
                        .version("1.0")
                        .build())
                .pathMapping("/")
    }

    override fun run(vararg args: String?) {
        println("*************************** ok ***********************************")
    }
}

五、创建数据库对象

import com.fasterxml.jackson.annotation.JsonFormat
import org.hibernate.annotations.DynamicInsert
import org.hibernate.annotations.DynamicUpdate
import java.util.*
import javax.persistence.*

/****
 * 设备流量规则
 */
@Entity
@Table(name = "device_rules",
        indexes = [Index(name = "device_no", columnList = "device_no"),
            Index(name = "rules_no", columnList = "rules_no"),
            Index(name = "deleted", columnList = "deleted")],
        uniqueConstraints = [UniqueConstraint(name = "device_no_rules_no", columnNames = ["device_no", "rules_no"])])
@DynamicUpdate
@DynamicInsert
class DeviceRules {

    @Id
    @Column(name = "id", columnDefinition = "bigint(20) COMMENT 'ID,自增'")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null

    @Column(name = "device_no", columnDefinition = "varchar(18) COMMENT '设备编号'")
    var deviceNo: String? = null

    @Column(name = "rules_no", columnDefinition = "varchar(18) COMMENT '规则编号'")
    var rulesNo: String? = null

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(name = "create_at", columnDefinition = "datetime COMMENT '创建时间'")
    var createAt: Date? = null

    @Column(name = "update_at", columnDefinition = "datetime COMMENT '修改时间'")
    var updateAt: Date? = null

    /**
     * 触发jpa update代码需要执行的逻辑
     */
    @PreUpdate
    fun preUpdate() {
        updateAt = Date()
    }

    /**
     * 自动设置必要字段的值
     */
    @PrePersist
    fun prePersist() {
        updateAt = Date()
        createAt = updateAt
        deleted = BaseEnum.NOT_REMOVE.index
    }
}

注解使用了 hibernate的功能主要用于自动创建/更新表结构以及索引的生成,如果需要 mybatis版本的,只需要去掉这里面的注释就好。

六、创建仓库操作接口

基于 springboot-data-jparepository

@Repository
interface DeviceRulesRepository : JpaRepository<DeviceRules, Long>,
        JpaSpecificationExecutor<DeviceRules>, QuerydslPredicateExecutor<DeviceRules> {
    fun getAllByDeviceNoAndDeleted(deviceNo: String, deleted: Int): Optional<MutableList<DeviceRules>>
}

七、创建一个业务接口来声明业务

interface DeviceService {
  
    /**
     * 查询设备的路由规则
     */
    fun queryDeviceFlowRules(aPageRequest: APageRequest): PageResult<QueryDeviceFlowRulesVO>
}

八、创建一个业务接口实现来实现声明的业务

@Service
class DeviceServiceImpl @Autowired
constructor(private val deviceRepository: DeviceRepository,
            private val deviceRulesRepository: DeviceRulesRepository,
            private val querydslUtlis: QuerydslUtlis,
            private val deviceMapstruct: DeviceMapstruct) : DeviceService {
    private val logger = LoggerFactory.getLogger(javaClass)
    
    override fun queryDeviceFlowRules(aPageRequest: APageRequest): PageResult<QueryDeviceFlowRulesVO> {
        val qDeviceRules = QDeviceRules.deviceRules
        val qFlowRules = QFlowRules.flowRules
        var rredicate: Predicate? = null
        if (StringUtils.isNotBlank(aPageRequest.query)) rredicate = qDeviceRules.deviceNo.eq(aPageRequest.query)
        val exprs = arrayOf<Expression<*>>(qDeviceRules.deviceNo, qDeviceRules.deleted, qFlowRules.rulesNo, qFlowRules.flowMax,
                qFlowRules.startTime, qFlowRules.endTime)
        val results = querydslUtlis.getQueryFactory()
                .select(*exprs)
                .from(qDeviceRules)
                .where(ExpressionUtils.allOf(rredicate))
                .leftJoin(qFlowRules)
                .on(qDeviceRules.rulesNo.eq(qFlowRules.rulesNo))
                .orderBy(qDeviceRules.createAt.desc())
                .offset((aPageRequest.pageIndex!! - 1) * aPageRequest.pageSize!!)
                .limit(aPageRequest.pageSize!!)
                .fetchResults()
        return PageUtlis.retPage(results, querydslUtlis.getCollection(results.results, exprs, QueryDeviceFlowRulesVO::class.java) as Collection<QueryDeviceFlowRulesVO>)
    }
}

这里使用了 querydsl来完成一个多表查询

九、创建一个 http服务接口

@RestWrapper
@RestController
@RequestMapping("/device")
@Api(value = "device", description = "设备相关接口", tags = ["device"])
class DeviceController @Autowired
constructor(private val deviceService: DeviceService) {

    @GetMapping("/query_device")
    fun queryDevice(aPageRequest: APageRequest) = deviceService.queryDevice(aPageRequest)

    @GetMapping("/query_device_flow_rules")
    fun queryDeviceFlowRules(aPageRequest: APageRequest) = deviceService.queryDeviceFlowRules(aPageRequest)
}

至此完成一个基本的开发过程,大多数情况下可以直接将 java代码粘贴到 kotlin文件中,会自动转换成合适的 kotlin代码(偶尔需要自己调整,毕竟编辑器不是万能的)

到此这篇关于使用kotlin集成springboot开发的文章就介绍到这了,更多相关kotlin集成springboot开发内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!

编程技巧