当前位置: 首页 > news >正文

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

前言

  • 我自己的业务项目,先用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_11configurations {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.entityimport 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.configimport 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()@Beanopen fun customConverters(): HttpMessageConverters {//创建fastJson消息转换器var fastJsonConverter = FastJsonHttpMessageConverter()//创建配置类var fastJsonConfig = FastJsonConfig()//修改配置返回内容的过滤fastJsonConfig.setSerializerFeatures(// 格式化SerializerFeature.PrettyFormat,// 可解决long精度丢失 但会有带来相应的中文问题//SerializerFeature.BrowserCompatible,// 消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)SerializerFeature.DisableCircularReferenceDetect,// 是否输出值为null的字段,默认为falseSerializerFeature.WriteMapNullValue,// 字符类型字段如果为null,输出为"",而非nullSerializerFeature.WriteNullStringAsEmpty,// List字段如果为null,输出为[],而非nullSerializerFeature.WriteNullListAsEmpty)// 日期格式fastJsonConfig.dateFormat = "yyyy-MM-dd HH:mm:ss"// long精度问题var serializeConfig = SerializeConfig.globalInstanceserializeConfig.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: devdatasource:#引用项目中的数据库文件driver-class-name: org.sqlite.JDBCurl: jdbc:sqlite::resource:sqlite/bbs.dbusername: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.controllerimport 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的构造方法的方式注入对象@Resourcelateinit 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调用如下:
在这里插入图片描述

相关文章:

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

前言 我自己的业务项目&#xff0c;先用kotlinspringboot 搭建&#xff0c; 发现gradle支持kts脚本&#xff0c;于是我就搭建试试。我就选用了最流行的Sqlite内嵌数据库,虽然H2也不错&#xff0c;但是Sqlite才是最流行的。orm框架我还是选择了Mybatis-Plus &#xff0c;为此中…...

Docker 容器与容器云读书笔记(一)

最近都没时间看书&#xff0c;闲暇之余看看书&#xff0c;写写笔记&#xff0c;记录一下这难得的时光。 docker容器的出现 2013年初&#xff0c; 一个名字从云计算领域横空出世&#xff0c;并在整个IT行业激起千层浪&#xff0c;这就是Docker。Docker选择容器作为核心和基础&…...

软件设计(九)

软件设计&#xff08;八&#xff09;https://blog.csdn.net/ke1ying/article/details/128954569?spm1001.2014.3001.5501 81、模块A将学生信息&#xff0c;即学生姓名、学号、手机等放到一个结构体系中&#xff0c;传递给模块B&#xff0c;模块A和B之间的耦合类型为 什么耦合…...

FoveaBox原理与代码解析

paper&#xff1a;FoveaBox: Beyond Anchor-based Object Detectorcode&#xff1a;https://github.com/taokong/FoveaBox背景基于anchor的检测模型需要仔细设计anchor&#xff0c;常用方法之一是根据特定数据集的统计结果确定anchor的number、scale、ratio等&#xff0c;但这种…...

Linux内核启动(1,0.11版本)启动BIOS与加载内核

从电源到启动BIOS 从我们按下启动电源到BIOS&#xff0c;按下电源–>主板会向电源组发出信号–> 接受到信号后&#xff0c;当主板收到电源正常启动信号后&#xff0c;主板会启动CPU(CPU重置所有寄存器数据&#xff0c;并且初始化数据)&#xff0c;比如32位系统&#xff…...

python制作贪吃蛇小游戏,畅玩无限制

前言 大家早好、午好、晚好吖 ❤ ~ 现在这年头&#xff0c;无论玩个什么游戏都有健康机制&#xff0c; 这让我们愉悦玩游戏得步伐变得承重起来&#xff0c; 于是无聊之下我写了个贪吃蛇小游戏&#xff0c;来玩个快乐 代码展示 导入模块 import random import sys import …...

MySQL-InnoDB数据页结构浅析

在MySQL-InnoDB行格式浅析中&#xff0c;们简单提了一下 页 的概念&#xff0c;它是 InnoDB 管理存储空间的基本单位&#xff0c;一个页的大小一般是 16KB 。 InnoDB 为了不同的目的而设计了许多种不同类型的 页&#xff1a; 存放表空间头部信息的页存放 Insert Buffer信息的…...

Java、JSP职工人事管理系统设计与实现

技术&#xff1a;Java、JSP等摘要&#xff1a;现在随着我们这个社会的计算机技术的快速发展&#xff0c;计算机在企业管理中得到普遍的应用&#xff0c;现在我们利用计算机在实现企业职工的管理越来越重要。当今社会是快速发展的信息社会&#xff0c;自动化信息的作用也变得越来…...

数据结构与算法这么难,为什么我们还要学习?

文章目录前言1. 数据结构与算法是什么&#xff1f;2. 为什么数据结构与算法很难&#xff1f;3. 如何系统学习数据结构与算法&#xff1f;&#x1f351; 复杂度&#x1f351; 线性表&#x1f351; 树形结构&#x1f351; 图&#x1f351; 排序&#x1f351; 字符串&#x1f351;…...

剑指 Offer 52. 两个链表的第一个公共节点

摘要 剑指 Offer 52. 两个链表的第一个公共节点 一、双指针解法 使用双指针的方法&#xff0c;可以将空间复杂度降至 O(1)。只有当链表 headA headB都不为空时&#xff0c;两个链表才可能相交。因此首先判断链表 headA和 headB是否为空&#xff0c;如果其中至少有一个链表为…...

可以写进简历的软件测试电商项目,不进来get一下?

前言 说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff…...

蓝桥杯-算法-印章问题

这个题真的顶啊&#xff01;思路&#xff1a;n种图案&#xff0c;m张印章&#xff0c;每一个图案的概率是1/n&#xff0c;这个概率以后用P表示首先我们定义dp[i][j]是买了i张印章&#xff08;对应于上面的m&#xff09;&#xff0c;凑齐j种图案的概率&#xff08;对应于上面的n…...

戴尔游匣G16电脑U盘安装系统操作教程分享

戴尔游匣G16电脑U盘安装系统操作教程分享。有用户在使用戴尔游匣G16电脑的时候遇到了系统问题&#xff0c;比如电脑蓝屏、自动关机重启、驱动不兼容等问题。遇到这些问题如果无法进行彻底解决&#xff0c;我们可以通过U盘重新安装系统的方法来解决&#xff0c;因为这些问题一般…...

2023数学建模美赛赛题思路分析 2023美赛 美国大学生数学建模数模

将在本帖更新2023美国大学生数学建模数模美赛各个赛题思路&#xff0c;大家可以点赞收藏&#xff01; 一、参赛报名 组队参赛&#xff08;每队人数3人&#xff0c;专业不限&#xff09;。 二、赛题思路及资料 会在本帖更新思路分析&#xff0c;Q群可领取模型代码/赛题思路资料…...

vue3与vue2的对比

Vue 3.0 和 Vue 2.0 是 Vue 前端框架的两个主要版本&#xff0c;它们有着不同的更新和优化&#xff1a; Vue 3.0 主要更新内容&#xff1a; 采用 TypeScript 作为开发语言&#xff0c;提高了代码的类型安全性。 速度更快&#xff0c;内存使用更少&#xff0c;支持大规模数据处…...

史上最全软件测试工程师常见的面试题总结(百度、oppo、中软国际、华为)备战金三银四

1、面试&#xff1a;神州数码1.介绍你下你项目中一个自动化实现的流程2.你觉得做自动化的意义在哪里 >需要对之前已经实现的功能进行回归测试、保证当前版本更新的内容不能影响到之前已经实现好的功能3.你们做自动化产生了什么结果 >测试报告、报错截图和报错日志、测试报…...

“深度学习”学习日记。卷积神经网络--用CNN的实现MINIST识别任务

2023.2.11 通过已经实现的卷积层和池化层&#xff0c;搭建CNN去实现MNIST数据集的识别任务&#xff1b; 一&#xff0c;简单CNN的网络构成&#xff1a; 代码需要在有网络的情况下运行&#xff0c;因为会下载MINIST数据集&#xff0c;运行后会生成params.pkl保留训练权重&…...

JavaWeb--JDBC练习

JDBC练习5.1 需求5.2 案例实现5.2.1 环境准备5.2.2 查询所有5.2.3 添加数据5.2.4 修改数据5.2.5 删除数据5.1 需求 完成商品品牌数据的增删改查操作 查询&#xff1a;查询所有数据添加&#xff1a;添加品牌修改&#xff1a;根据id修改删除&#xff1a;根据id删除 5.2 案例实…...

【LeetCode】2335. 装满杯子需要的最短总时长

2335. 装满杯子需要的最短总时长 题目描述 现有一台饮水机&#xff0c;可以制备冷水、温水和热水。每秒钟&#xff0c;可以装满 2 杯 不同 类型的水或者 1 杯任意类型的水。 给你一个下标从 0 开始、长度为 3 的整数数组 amount &#xff0c;其中 amount[0]、amount[1] 和 a…...

Android 12.0 通过驱动实现禁用usb鼠标和usb键盘功能

1.1概述 在12.0的系统产品定制化开发中,在进行定制中有关于usb键盘和usb鼠标的需求中,产品要求禁止usb口挂载usb鼠标和usb键盘,所以需要要求在usb挂载类型的时候 判断如果是usb鼠标和usb键盘就不让挂载,这就需要从驱动方面入手来解决这个问题,接下来看下驱动的某些挂载usb…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...