Spring Boot和Kotlin的无缝整合与完美交融
前言
本文讲解 spring boot2 基础下,如何使用 kotlin,并无缝整合与完美交融。为了让读者更加熟悉 kotlin 的语法糖,笔者会在未来的几篇文章中,聊聊 kotlin 的新特性及其语法糖。下面话不多说了,来一起看看详细的介绍吧
环境依赖
修改 pom 文件,添加 spring boot 依赖。
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.0.2.release</version> <relativepath/> </parent> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-jdbc</artifactid> </dependency> </dependencies>
紧接着,我们需要添加 mysql 依赖。
<dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>5.1.35</version> </dependency> <dependency> <groupid>com.alibaba</groupid> <artifactid>druid</artifactid> <version>1.0.14</version> </dependency>
最后,添加 kotlin 依赖。
<dependency> <groupid>org.jetbrains.kotlin</groupid> <artifactid>kotlin-stdlib-jdk8</artifactid> </dependency> <dependency> <groupid>org.jetbrains.kotlin</groupid> <artifactid>kotlin-reflect</artifactid> </dependency> <dependency> <groupid>org.jetbrains.kotlin</groupid> <artifactid>kotlin-stdlib</artifactid> </dependency>
注意的是,在 kotlin 中,data class 默认没有无参构造方法,并且 data class 默认为 final 类型,不可以被继承。注意的是,如果我们使用 spring + kotlin 的模式,那么使用 @autowared 就可能遇到这个问题。因此,我们可以添加 noarg 为标注的类生成无参构造方法。使用 allopen 为被标注的类去掉 final,允许被继承。
<plugin> <artifactid>kotlin-maven-plugin</artifactid> <groupid>org.jetbrains.kotlin</groupid> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <goals> <goal>test-compile</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupid>org.jetbrains.kotlin</groupid> <artifactid>kotlin-maven-noarg</artifactid> <version>${kotlin.version}</version> </dependency> <dependency> <groupid>org.jetbrains.kotlin</groupid> <artifactid>kotlin-maven-allopen</artifactid> <version>${kotlin.version}</version> </dependency> </dependencies> </plugin>
至此,我们 maven 的依赖环境大致配置完毕。完整的源码,可以参见文末 github 仓库。
数据源
方案一 使用 spring boot 默认配置
使用 spring boot 默认配置,不需要在创建 datasource 和 jdbctemplate 的 bean。
在 src/main/resources/application.properties 中配置数据源信息。
spring.datasource.driver-class-name=com.mysql.jdbc.driver spring.datasource.url=jdbc:mysql://localhost:3307/springboot_db spring.datasource.username=root spring.datasource.password=root
方案二 手动创建
在 src/main/resources/config/source.properties 中配置数据源信息。
# mysql source.driverclassname = com.mysql.jdbc.driver source.url = jdbc:mysql://localhost:3306/springboot_db source.username = root source.password = root
这里, 创建 datasource 和jdbctemplate。
@configuration @enabletransactionmanagement @propertysource(value = *arrayof("classpath:config/source.properties")) open class beanconfig { @autowired private lateinit var env: environment @bean open fun datasource(): datasource { val datasource = druiddatasource() datasource.driverclassname = env!!.getproperty("source.driverclassname").trim() datasource.url = env.getproperty("source.url").trim() datasource.username = env.getproperty("source.username").trim() datasource.password = env.getproperty("source.password").trim() return datasource } @bean open fun jdbctemplate(): jdbctemplate { val jdbctemplate = jdbctemplate() jdbctemplate.datasource = datasource() return jdbctemplate } }
脚本初始化
先初始化需要用到的 sql 脚本。
create database /*!32312 if not exists*/`springboot_db` /*!40100 default character set utf8 */; use `springboot_db`; drop table if exists `t_author`; create table `t_author` ( `id` bigint(20) unsigned not null auto_increment comment '用户id', `real_name` varchar(32) not null comment '用户名称', `nick_name` varchar(32) not null comment '用户匿名', primary key (`id`) ) engine=innodb auto_increment=1 default charset=utf8;
使用 jdbctemplate 操作
实体对象
class author { var id: long? = null var realname: string? = null var nickname: string? = null }
dao相关
interface authordao { fun add(author: author): int fun update(author: author): int fun delete(id: long): int fun findauthor(id: long): author? fun findauthorlist(): list<author> }
我们来定义实现类,通过 jdbctemplate 定义的数据访问操作。
@repository open class authordaoimpl : authordao { @autowired private lateinit var jdbctemplate: jdbctemplate override fun add(author: author): int { return jdbctemplate.update("insert into t_author(real_name, nick_name) values(?, ?)", author.realname, author.nickname) } override fun update(author: author): int { return jdbctemplate.update("update t_author set real_name = ?, nick_name = ? where id = ?", *arrayof(author.realname, author.nickname, author.id)) } override fun delete(id: long): int { return jdbctemplate.update("delete from t_author where id = ?", id) } override fun findauthor(id: long): author? { val list = jdbctemplate.query<author>("select * from t_author where id = ?", arrayof<any>(id), beanpropertyrowmapper(author::class.java)) return list?.get(0); } override fun findauthorlist(): list<author> { return jdbctemplate.query("select * from t_author", arrayof(), beanpropertyrowmapper(author::class.java)) } }
service相关
interface authorservice { fun add(author: author): int fun update(author: author): int fun delete(id: long): int fun findauthor(id: long): author? fun findauthorlist(): list<author> }
我们来定义实现类,service 层调用 dao 层的方法,这个是典型的套路。
@service("authorservice") open class authorserviceimpl : authorservice { @autowired private lateinit var authordao: authordao override fun update(author: author): int { return this.authordao.update(author) } override fun add(author: author): int { return this.authordao.add(author) } override fun delete(id: long): int { return this.authordao.delete(id) } override fun findauthor(id: long): author? { return this.authordao.findauthor(id) } override fun findauthorlist(): list<author> { return this.authordao.findauthorlist() } }
controller相关
为了展现效果,我们先定义一组简单的 restful api 接口进行测试。
@restcontroller @requestmapping(value = "/authors") class authorcontroller { @autowired private lateinit var authorservice: authorservice /** * 查询用户列表 */ @requestmapping(method = [requestmethod.get]) fun getauthorlist(request: httpservletrequest): map<string, any> { val authorlist = this.authorservice.findauthorlist() val param = hashmap<string, any>() param["total"] = authorlist.size param["rows"] = authorlist return param } /** * 查询用户信息 */ @requestmapping(value = "/{userid:\\d+}", method = [requestmethod.get]) fun getauthor(@pathvariable userid: long, request: httpservletrequest): author { return authorservice.findauthor(userid) ?: throw runtimeexception("查询错误") } /** * 新增方法 */ @requestmapping(method = [requestmethod.post]) fun add(@requestbody jsonobject: jsonobject) { val userid = jsonobject.getstring("user_id") val realname = jsonobject.getstring("real_name") val nickname = jsonobject.getstring("nick_name") val author = author() author.id = java.lang.long.valueof(userid) author.realname = realname author.nickname = nickname try { this.authorservice.add(author) } catch (e: exception) { throw runtimeexception("新增错误") } } /** * 更新方法 */ @requestmapping(value = "/{userid:\\d+}", method = [requestmethod.put]) fun update(@pathvariable userid: long, @requestbody jsonobject: jsonobject) { var author = this.authorservice.findauthor(userid) val realname = jsonobject.getstring("real_name") val nickname = jsonobject.getstring("nick_name") try { if (author != null) { author.realname = realname author.nickname = nickname this.authorservice.update(author) } } catch (e: exception) { throw runtimeexception("更新错误") } } /** * 删除方法 */ @requestmapping(value = "/{userid:\\d+}", method = [requestmethod.delete]) fun delete(@pathvariable userid: long) { try { this.authorservice.delete(userid) } catch (e: exception) { throw runtimeexception("删除错误") } } }
最后,我们通过 springkotlinapplication 运行程序。
@springbootapplication(scanbasepackages = ["com.lianggzone.demo.kotlin"]) open class springkotlinapplication{ fun main(args: array<string>) { springapplication.run(springkotlinapplication::class.java, *args) } }
关于测试
这里,笔者推荐 idea 的 editor rest client。idea 的 editor rest client 在 intellij idea 2017.3 版本就开始支持,在 2018.1 版本添加了很多的特性。事实上,它是 intellij idea 的 http client 插件。参见笔者之前的另一篇文章: 快速测试 api 接口的新技能
### 查询用户列表 get http://localhost:8080/authors accept : application/json content-type : application/json;charset=utf-8 ### 查询用户信息 get http://localhost:8080/authors/15 accept : application/json content-type : application/json;charset=utf-8 ### 新增方法 post http://localhost:8080/authors content-type: application/json { "user_id": "21", "real_name": "梁桂钊", "nick_name": "梁桂钊" } ### 更新方法 put http://localhost:8080/authors/21 content-type: application/json { "real_name" : "lianggzone", "nick_name": "lianggzone" } ### 删除方法 delete http://localhost:8080/authors/21 accept : application/json content-type : application/json;charset=utf-8
总结
通过,上面这个简单的案例,我们发现 spring boot 整合 kotlin 非常容易,并简化 spring 应用的初始搭建以及开发过程。为了让读者更加熟悉 kotlin 的语法糖,笔者会在未来的几篇文章中,聊聊 kotlin 的新特性及其语法糖。
源代码
相关示例完整代码: ()
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。