SpringBoot + kotlin/java + Mybatis-Plus +Sqlite + Gradle多模块项目

news2024/9/29 11:28:14

前言

  • 我自己的业务项目,先用kotlin+springboot 搭建, 发现gradle支持kts脚本,于是我就搭建试试。
  • 我就选用了最流行的Sqlite内嵌数据库,虽然H2也不错,但是Sqlite才是最流行的。
  • orm框架我还是选择了Mybatis-Plus ,为此中间踩了坑。
  • 项目支持java+kotlin 混合编程, 没有配置好Lombok, 所以就没有集成了。

整个项目的代码我放在github中了,各位可以下载下来看看。

https://github.com/blanexie/vxpt

项目模块结构

项目由两个小模块组成,分别是 vxpt-bbsvxpt-tracker
在这里插入图片描述

setting.gradle.kts 文件

kts脚本本质还是kotlin代码, 不支持单引号字符串。

gradle项目的组织结构文件, 选用的是kotlin的kts脚本。 内容如下:

rootProject.name = "vxpt"

include(":vxpt-bbs")
include(":vxpt-tracker")

父项目的build.gradle.kts 文件

需要注意的是kotlin的版本和gradle很多插件之间都有兼容关系, 版本号要对应上才能使用, 因此我只能使用1.5.10版本。 jdk使用的是11版本。

plugins {
    id("org.springframework.boot") version "2.5.0"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.5.10"
    kotlin("plugin.spring") version "1.5.10"
    id("org.jetbrains.kotlin.plugin.noarg") version "1.4.20"
}

repositories {
    mavenLocal()
    maven {
        setUrl("https://maven.aliyun.com/nexus/content/groups/public/")
    }
    mavenCentral()
}

subprojects {
    apply(plugin = "java")
    apply(plugin = "kotlin")
    apply(plugin = "idea")
    apply(plugin = "org.springframework.boot")
    apply(plugin = "io.spring.dependency-management")
    apply(plugin = "org.jetbrains.kotlin.plugin.spring")
    apply(plugin = "org.jetbrains.kotlin.jvm")
    apply(plugin = "org.jetbrains.kotlin.plugin.noarg")

    repositories {
        mavenLocal()
        maven {
            setUrl("https://maven.aliyun.com/nexus/content/groups/public/")
        }
        mavenCentral()
    }



    java.sourceCompatibility = JavaVersion.VERSION_11

    configurations {
        compileOnly {
            extendsFrom(configurations.annotationProcessor.get())
        }
    }

    dependencies {
        implementation("org.springframework.boot:spring-boot-starter-web")
        implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
        implementation("org.jetbrains.kotlin:kotlin-reflect")
        implementation("org.jetbrains.kotlin:kotlin-stdlib")


        developmentOnly("org.springframework.boot:spring-boot-devtools")
        annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
        testImplementation("org.springframework.boot:spring-boot-starter-test")
    }


    tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
        kotlinOptions {
            freeCompilerArgs = listOf("-Xjsr305=strict")
            jvmTarget = "11"
        }
    }

    tasks.withType<Test> {
        useJUnitPlatform()
    }
}

vxpt-bbs的子模块的build.gradle.kts文件

  • 这里需要注意noArg的配置,是为了解决Mybtatis需要的对象的无参构造方法的问题。这个问题官方有解决方案,但是都是gradle的Groovy的脚本配置, 为此我各种尝试,才改成kts脚本的方式。
group = "com.github.blanexie.vxpt.bbs"
version = "0.0.1"

plugins {

}

// 必需的,为了解决kotlin数据类无参构造方法的问题,
noArg {
    "com.baomidou.mybatisplus.annotation.TableName"
}

dependencies {
    implementation("org.xerial:sqlite-jdbc:3.21.0.1")
    implementation("com.baomidou:mybatis-plus-boot-starter:3.5.0")
    implementation("org.mybatis:mybatis-typehandlers-jsr310:1.0.2")
    implementation("com.alibaba:fastjson:2.0.23")
}

Mybatis数据对象

这里由于Mybatis的无参构造方法的问题,使用都报找不到UserDO的无参构造方法错误, 为此我尝试了多种方案,尝试方案如下:

  • Spring的allOpen方案,配置无效,应该还是kts脚本的问题
  • Lombok方案,配置无法成功,放弃。
  • Java+Kotlin 混合方案,UserDO使用Java编写。 这个方案刚开始都无法编译Java类,尝试好久最后发现是我把java代码写在src/main/kotlin目录下了,导致无法识别, 最后我把所有代码都放入src/main/java目录下才成功, src/main/java目录可以识别kotlin代码和java代码,但是src/main/kotlin目录只能识别kotlin代码。
  • Kotlin官方的noArg方案,刚开始也无法成功,计划要使用混合编程方案, 最后改了下配置成功了,官方教程中只有Groovy脚本,无kts脚本,我自己尝试出来的。
package com.github.blanexie.vxpt.bbs.user.meta.entity

import com.baomidou.mybatisplus.annotation.IdType
import com.baomidou.mybatisplus.annotation.TableId
import com.baomidou.mybatisplus.annotation.TableName
import java.time.LocalDateTime

@TableName("user")
class UserDO(
    @TableId(type = IdType.AUTO)
    var id: Long?,
    var email: String,
    var nickName: String,
    var password: String,
    var coverImg: String?,
    var role: String,
    var sex: Int,
    var status: Int,
    var createTime: LocalDateTime,
    var updateTime: LocalDateTime,
) {
}

Mybtatis的数据对象的LocalDateTime序列化问题

LocalDateTime 是java8出来的时间对象,用于替换性能不好的Date类, 按理来说早就应该支持了, 但是我引入的最新的Mybatis-Plus包中的Mybatis就是无法识别,我尝试的解决方案如下:

  • 自定义TypeHandler方案, 尝试到一半放弃,因为发现更好的方案, 但是这个方案应该也是行的通的
  • 引入Mybatis的补丁包, implementation("org.mybatis:mybatis-typehandlers-jsr310:1.0.2")

Http的HttpMessageConverters转换器

这个是在对象放回给浏览器端的时候,json序列化对象的设置类,我选用了fastjson,虽然他安全系数不高,但是他API好用啊,我业务项目,无所谓。 配置如下:

package com.github.blanexie.vxpt.bbs.util.config

import com.alibaba.fastjson.serializer.SerializeConfig
import com.alibaba.fastjson.serializer.SerializerFeature
import com.alibaba.fastjson.serializer.ToStringSerializer
import com.alibaba.fastjson.support.config.FastJsonConfig
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.http.HttpMessageConverters
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.http.MediaType
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import java.math.BigInteger
import java.nio.charset.Charset

@Configuration
@ConditionalOnClass(WebMvcConfigurer::class)
@Order(Ordered.HIGHEST_PRECEDENCE)
open class WebConfig : WebMvcConfigurer {
    constructor() : super()
    @Bean
    open fun customConverters(): HttpMessageConverters {
        //创建fastJson消息转换器

        var fastJsonConverter = FastJsonHttpMessageConverter()
        //创建配置类
        var fastJsonConfig = FastJsonConfig()
        //修改配置返回内容的过滤
        fastJsonConfig.setSerializerFeatures(
            // 格式化
            SerializerFeature.PrettyFormat,
            // 可解决long精度丢失 但会有带来相应的中文问题
            //SerializerFeature.BrowserCompatible,
            // 消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
            SerializerFeature.DisableCircularReferenceDetect,
            // 是否输出值为null的字段,默认为false
            SerializerFeature.WriteMapNullValue,
            // 字符类型字段如果为null,输出为"",而非null
            SerializerFeature.WriteNullStringAsEmpty,
            // List字段如果为null,输出为[],而非null
            SerializerFeature.WriteNullListAsEmpty
        )
        // 日期格式
        fastJsonConfig.dateFormat = "yyyy-MM-dd HH:mm:ss"

        // long精度问题
        var serializeConfig = SerializeConfig.globalInstance
        serializeConfig.put(Integer::class.java, ToStringSerializer.instance)
        serializeConfig.put(BigInteger::class.java, ToStringSerializer.instance)
        serializeConfig.put(Long::class.java, ToStringSerializer.instance)
        serializeConfig.put(Long::class.javaObjectType, ToStringSerializer.instance)
        fastJsonConfig.setSerializeConfig(serializeConfig)

        //处理中文乱码问题
        var fastMediaTypes = ArrayList<MediaType>()
        fastMediaTypes.add(MediaType.APPLICATION_JSON)
        fastMediaTypes.add(MediaType(MediaType.TEXT_HTML, Charset.forName("UTF-8")))
        fastMediaTypes.add(MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")))
        fastMediaTypes.add(MediaType(MediaType.APPLICATION_FORM_URLENCODED, Charset.forName("UTF-8")))
        fastMediaTypes.add(MediaType.MULTIPART_FORM_DATA)

        fastJsonConverter.setSupportedMediaTypes(fastMediaTypes)
        fastJsonConverter.setFastJsonConfig(fastJsonConfig)
        //将fastjson添加到视图消息转换器列表内
        return HttpMessageConverters(fastJsonConverter)
    }
}

Sqlite配置问题

  • Sqlite使用很方便,只要使用DBeaver工具创建一个sqlite数据,建好边,最后把数据库文件复制到resource目录下,就能直接使用了。
  • Sqlite是内嵌数据库,会充分使用内存的,不用考虑数据库链接池(druid)等,并且druid还有一些配置不兼容sqlite, 所以我直接使用了默认的HikariPool连接池。

配置目录截图如下:
在这里插入图片描述

配置文件内容如下:

# Tomcat
server:
 port: 8899

#spring
spring:
 profiles:
   active: dev
 datasource:
   #引用项目中的数据库文件
   driver-class-name: org.sqlite.JDBC
   url: jdbc:sqlite::resource:sqlite/bbs.db
   username:
   password:

#mybatis-plus配置控制台打印完整带参数SQL语句
mybatis-plus:
 configuration:
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

UserMapper和UserController类如下

  • UserMapper按照说明文档来,没有啥问题
  • UserController类有个依赖注入的问题。 依赖注入有多种方式,我选择了 lateinit var的方式
package com.github.blanexie.vxpt.bbs.user.controller

import com.github.blanexie.vxpt.bbs.user.dao.UserMapper
import com.github.blanexie.vxpt.bbs.user.meta.entity.UserDO
import com.github.blanexie.vxpt.bbs.util.WebResp
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDateTime
import javax.annotation.Resource

@RestController
@RequestMapping("/api/user")
class UserController {

	//使用lateinit关键字的方式可以直接注入对象,也可以使用UserController的构造方法的方式注入对象
    @Resource
    lateinit var userMapper: UserMapper

    @GetMapping("/login")
    fun login(): WebResp {
        var userDO = UserDO(
            12, "12@vxpt", "12vxpt", "sagsdg", "https://21gsfsa", "user", 1, 1, LocalDateTime.now(), LocalDateTime.now()
        )
        userMapper.insert(userDO)
        return WebResp.success(userDO)
    }

    @GetMapping("/logout")
    fun logout(): WebResp {
        var selectById = userMapper.selectById(12)
        return WebResp.success(selectById)
    }

    @GetMapping("/register")
    fun register(): WebResp {
        return WebResp.success()
    }

}

启动截图

启动控制台如下:
在这里插入图片描述
postman调用如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot的创建和使用

目录 一、Spring Boot介绍 1.1 Spring Boot 是什么 1.2 Spring Boot的优点 二、Spring Boot 项目的创建 2.1 使用idea创建 2.1.1 安装Spring Boot Helper插件 2.1.2 创建 Spring Boot 项目 2.1.3 验证项目是否创建成功 2.2 使用网页创建 三、输出 hello world 一、S…

前端如何提升To B产品用户体验

云计算产品发展的早期常以技术为核心吸引客户&#xff0c;功能的实现是这一时期产品优先考虑的因素。经过数十年的发展&#xff0c;云计算行业已经进入了深耕细作的时代&#xff0c;市场的激烈竞争与云产品快速发展的同时&#xff0c;用户对产品的可用性与易用性也有了更高的要…

交换机中的冗余链路管理

一 交换机冗余链路许多交换机或交换机设备组成的网络环境中&#xff0c;通常使用一些备份连接&#xff0c;以提高网络的健全性&#xff0c;稳定性。备份连接也叫备份链路&#xff0c;冗余链路等。为了解决共享式局域网的碰撞问题&#xff0c;采用了交换机构成的交换式局域网&am…

C语言静态库、动态库的封装和注意事项

1、动态库、静态库介绍 参考博客&#xff1a;《静态库和动态库介绍以及Makefile》&#xff1b; 2、代码目录结构和编译脚本 参考博客&#xff1a;《实际工作开发中C语言工程的目录结构分析》&#xff1b; 3、编写库的流程 (1)明确需求:需求是否合理、需求的使用场景、需求可能遇…

chatgpt:人工智能的一次突破,如何正确的创建用户及使用

Chatgpt的正确创建及使用 chatgpt最近在国内也开始有声音了&#xff0c;其实早在去年12月初&#xff0c;该网站就已经可以在国外进行使用&#xff0c;而且很快渗透到了国外各行各业各个年龄段 &#xff0c;最火的当属国外很多学生用它来生成论文&#xff0c;关键是语句通顺&am…

如何开启多个独立Chrome浏览器

一、简介 作为测试或者开发人员&#xff0c;有些情况下会用到 Chrome 浏览器&#xff0c;但有时是同一个 Chrome 浏览器无法为我们提供隔离开的不同环境。这样 我们就需要清理 cache 、切换账号等&#xff0c;降低了我们的工作效率。今天的主题是如何开启多个独立的 Chrome 浏…

LayUI模板引擎渲染数据

前端模板引擎介绍 接上节Spring boot项目开发实战——&#xff08;LayUI实现前后端数据交换与定义方法渲染数据&#xff09; 模板引擎能简化开发&#xff0c;极大提高效率&#xff0c;小编之前使用过JSP和Thymeleaf&#xff0c;以及python的jinja2&#xff0c;这些是后端的模…

spring(二)-----------如何注入bean

我们从第三方框架mybatis为引&#xff0c;看看如何往spring中注入一个bean 1、纯mybatis开发生成一个mapper对象 如果不使用spring的情况下&#xff0c;mybatis想生成一个mapper对象大概需要做下面的操作&#xff1a; 假设我们有了一个TMapper接口&#xff0c;此时获取该map…

12款开源数据资产(元数据)管理平台选型分析(三)

如上&#xff0c;是ChatGPT的百度指数和微信指数&#xff0c;继2022年12月上旬技术圈火热之后&#xff0c;因为微软、谷歌等巨头的推广加持&#xff0c;ChatGPT成为全球大众热源的话题。各大媒体都在消费这波舆论红利&#xff0c;打开微信公众号&#xff0c;劈天盖地各种姿势的…

前后端学习

最近和锴哥想搞一下前后端接口的事儿&#xff0c;但是不会&#xff0c;所以打算再学学前后端的基础知识&#xff0c;之后好抄作业&#xff0c;做缝纫机&#xff1b;达哥觉得我浮躁&#xff0c;这次一定要支棱起来&#xff1b;这次开始&#xff0c;面向openai学习。 前后端学习1…

ChatGPT (可能)是怎么炼成的

学习自李宏毅老师的课https://www.youtube.com/watch?ve0aKI2GGZNg 1.学习文字接龙 学习方式 GPT只需要在网上阅读大量的句子&#xff0c;不需要人工标注即可学习到大量句子接龙的知识 然而实际上&#xff0c;“你好”后面可以接的字有很多。实际上&#xff0c;GPT学的就是…

3、Go基础数据类型

目录一、Go数据类型二、字符串三、强制类型转换一、Go数据类型 基础数据类型 类型长度(字节)默认值说明bool1falsebyte10uint8&#xff0c;取值范围[0,255]rune40Unicode Code Point, int32int, uint4或8032 或 64 位&#xff0c;取决于操作系统int8, uint810-128 ~ 127, 0 ~…

Freemarker介绍

2. Freemarker介绍 FreeMarker 是一个用 Java 语言编写的模板引擎&#xff0c;它基于模板来生成文本输出。FreeMarker与 Web 容器无关&#xff0c;即在 Web 运行时&#xff0c;它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术&#xff0c;而且还可以用于生成 XML…

Python数据结构:概念、栈

1.概念 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说&#xff0c;数据结构就是设计数据以何种方式组织并存储在计算机中。 比如:列表、集合与字典等都是一种数据结构。 N.Wirth:“程序数据结构算法’ 2.分类 数据结…

基于comsol软件弯曲单模光纤模拟仿真

在本节中&#xff0c;主要基于实验室实际光纤单模圆柱光纤进行模拟&#xff0c;与comsol案例库文件在分析过程和建模有些差异&#xff1a; 模拟主要通过以下三个步骤进行&#xff1a;模型的几何构建、物理场的添加研究、结构处理分析来进行。 下面是第一步骤&#xff1a;几何…

unity2022.1.8之后版本的新的输入行为控制对象变化

文章目录unity2022.1.8之后版本的新的输入行为控制对象变化怎么导入&#xff1f;如何使用&#xff1f;unity2022.1.8之后版本的新的输入行为控制对象变化 我们先了解大概的逻辑。我们要设置触发行为的方式并且让他和对象的行为绑定&#xff0c;再将行为和对象绑定&#xff0c;…

SpringBoot开发规范部分通用模板+idea配置【项目通用-1】

SpringBoot开发规范通用模板 1 分页插件使用 通过MybatisPlus配置分页插件拦截器 Configuration MapperScan("com.xuecheng.content.mapper") public class MybatisPlusConfig {//定义分页的拦截器Beanpublic MybatisPlusInterceptor getMybatisPlusInterceptor() {…

Pascal版本的 - freopen

参数 filename -- 这是包含要打开的文件的名称的字符串。 mode -- 这是包含文件访问模式的字符串。它包括 - 高级编号模式&说明1个 “r” 打开文件进行读取。该文件必须存在。 2个 “w” 创建一个用于写入的空文件。如果已存在同名文件&#xff0c;则删除其内容并将该文件…

【Java容器(jdk17)】ArrayList深入源码,就是这么简单

ArrayList深入源码一、ArrayList源码解析1. MIXIN 的混入2. 属性说明3. 构造方法4. 其他方法&#xff08;核心&#xff09;iterator 和 listIterator 方法add方法remove 方法sort方法其他二、ArrayList 为什么是线程不安全的&#xff1f;体现哪些方面呢&#xff1f;三、ArrayLi…

(day12) 自学Java——集合进阶(双列集合)

目录 1.双列集合特点 Map遍历三种方式 2.HashMap 3.LinkedHashMap 4.TreeMap 5.源码解析 6.可变参数(形参个数可变) 7.Collections 8.综合练习 1.双列集合特点 ①双列集合一次需要存一对数据&#xff0c;分别为键和值 ②键不能重复&#xff0c;值可以重复 ③键和值是一…