前言
上一篇文章请看这里: https://zhuanlan.zhihu.com/p/146733027
上一篇文章介绍了Kotlin搭配Springboot的开发流程,从搭建项目、ORM、Controller到Swagger集成和docker部署都有,不过大师说我那篇文章太多代码了,吹水太少了,于是我决定再水一篇,介绍一下Web开发中常用的几种操作。
在做完这个简单的系统,Kotlin搭配Springboot给我的感受就是,挺爽的,Springboot本身就是一套傻瓜式的解决方案,要什么功能全部gradle down下来然后注册一下,美滋滋,这就完事了,唯一不足的地方是这些都在Java这个垃圾语言下才能实现,每次用Java都有种吃*的感觉,特别恶心。
写一个简单的data class需要我每个字段配上该死的get和set方法,不知道这是哪个睿智的大佬发明的,看到这里可能有些小伙伴要说可以用Lombok实现自动生成get和set方法,我笑了,被坑过的人都懂。
至于null啊、泛型、值类型引用类型什么鬼乱七八糟的臭**,我就不多说什么了。
PS:喜欢Java的同学别喷,以上只是个人感受,语言只是赚钱的工具,只要钱给够,要我用易语言都没问题 (逃~
好了,可以进入正题了
自定义配置
自定义配置有两种,放在application.yml中,或者是自定义的文件里面,这里我配置比较少,放在application.yml里就行了。
我的配置:
onecat:
pageSize: 10
然后在configuration
包中定义一个类:
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component
@Component
@ConfigurationProperties("onecat")
object OneCatConfig {
@Value("\${onecat.pageSize}")
var pageSize: Int = 10
}
使用 object 关键字定义的类是静态类,这样其他地方可以直接调用:
OneCatConfig.pageSize
就这么完事了
跨域问题
跨域是Web开发中老生常谈的问题,解决办法很多,我只选最简单的,过个过滤器,在每个相应中加个header,松松
在 filter 包中新建一个过滤器:
@WebFilter(filterName = "CorsFilter")
@Configuration
class CorsFilter : Filter {
override fun doFilter(req: ServletRequest?, res: ServletResponse?, chain: FilterChain?) {
val response = res as HttpServletResponse
response.setHeader("Access-Control-Allow-Origin", "*")
response.setHeader("Access-Control-Allow-Credentials", "true")
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT")
response.setHeader("Access-Control-Max-Age", "3600")
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
chain!!.doFilter(req, res)
}
}
就这么也完事了,Springboot自动配置真滴方便。
分页
接下来介绍分页,我相信,Springboot生态中一定有很多分页组件,但我并没有用,能自己实现的,就不要用第三方组件~
首先我在 ViewModels 中定义了一个Page类,代码如下:
data class Page<T>(
val page: Int,
val pageSize: Int,
val count: Int,
val totalPages: Int = if (count % pageSize == 0) count / pageSize else count / pageSize + 1,
val currentList: List<T>
)
然后我用了Ktorm的sequence操作,有drop和take这两个方法,映射到SQL语句就是limit操作。
代码如下:
@ApiOperation("获取用户列表")
@GetMapping("/")
fun list(@RequestParam("page") page: Int): Response<Page<User>> {
val users = database.sequenceOf(UserDao)
.drop((page - 1) * OneCatConfig.pageSize).take(OneCatConfig.pageSize)
return Response(true, "获取用户列表",
Page(page, OneCatConfig.pageSize, users.totalRecords, currentList = users.toList()))
}
就是这样,也很简单实现。
这里吐槽一下Ktorm的作者,太坑了,他在GitHub给的例子代码里面关于分页的操作是错的,一开始我被误导了,后面自己改了代码,给原作者的代码填坑 = = 真难
ViewModel
其实刚才介绍分页的时候已经有用到 ViewModel 了,不过Page只是一个单纯data class,这里的ViewModel我要对传入的数据进行进一步的操作。
比如下面的代码,对每种类型下的装备数量和可用装备进行统计。
class EquipmentGroupViewModel(
private val database: Database,
val group: EquipmentGroup
) {
var total: Int
var available: Int
init {
val queryset = database.sequenceOf(EquipmentDao).filter { it.equipmentGroup eq group.id }
total = queryset.totalRecords
available = 0
for (equipment in queryset) {
if (equipment.rentStatus == 1 && equipment.damageStatus == 1)
available++
}
}
}
这样就OK了,一次测试通过,Kotlin好用就完事了
总结
Springboot香是挺香的,Kotlin这语言也挺好用,就是比起C#还是差点感觉,JVM限制了它的发挥,不过也是借着JVM的生态,kotlin才能上位,毕竟和Java可以无缝互调访问,这个体验,大家懂的,以后的Java项目也许都可以慢慢转Kotlin(并不)
只不过这个Ktorm给我有些不太好的体验,小坑啊,论ORM,DjangoORM第一,EFCore第二,能自动迁移实在是方便,你喜欢自己写SQL的灵活,我喜欢直接映射的方便,各取所需吧。
语言之争没有意义,面向工资编程才是真的,有人觉得JavaWeb开发钱多,屁颠屁颠就去学Java,无可厚非,有人喜欢.net core的965和一头秀发,那也是一种追求。至于Python、Rails on Ruby这类脚本语言来Web开发,更是优秀,项目做完钱到手就跑路(我瞎说的哈哈哈,你猜我为啥那么喜欢Python?)
欢迎交流
我整理了一系列的技术文章和资料,在公众号「程序设计实验室」后台回复 linux、flutter、c#、netcore、android、java、python 等可获取相关技术文章和资料,同时有任何问题都可以在公众号后台留言~