前言
本文講解 spring boot2 基礎下,如何使用 kotlin,并無縫整合與完美交融。為了讓讀者更加熟悉 kotlin 的語法糖,筆者會在未來的幾篇文章中,聊聊 kotlin 的新特性及其語法糖。下面話不多說了,來一起看看詳細的介紹吧
環(huán)境依賴
修改 pom 文件,添加 spring boot 依賴。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<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 依賴。
1
2
3
4
5
6
7
8
9
10
|
<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 依賴。
1
2
3
4
5
6
7
8
9
10
11
12
|
<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 默認沒有無參構(gòu)造方法,并且 data class 默認為 final 類型,不可以被繼承。注意的是,如果我們使用 spring + kotlin 的模式,那么使用 @autowared 就可能遇到這個問題。因此,我們可以添加 noarg 為標注的類生成無參構(gòu)造方法。使用 allopen 為被標注的類去掉 final,允許被繼承。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<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 的依賴環(huán)境大致配置完畢。完整的源碼,可以參見文末 github 倉庫。
數(shù)據(jù)源
方案一 使用 spring boot 默認配置
使用 spring boot 默認配置,不需要在創(chuàng)建 datasource 和 jdbctemplate 的 bean。
在 src/main/resources/application.properties 中配置數(shù)據(jù)源信息。
1
2
3
4
|
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 |
方案二 手動創(chuàng)建
在 src/main/resources/config/source.properties 中配置數(shù)據(jù)源信息。
1
2
3
4
5
|
# mysql source.driverclassname = com.mysql.jdbc.driver source.url = jdbc:mysql: //localhost:3306/springboot_db source.username = root source.password = root |
這里, 創(chuàng)建 datasource 和jdbctemplate。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@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 腳本。
1
2
3
4
5
6
7
8
9
10
11
12
|
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 操作
實體對象
1
2
3
4
5
|
class author { var id: long ? = null var realname: string? = null var nickname: string? = null } |
dao相關(guān)
1
2
3
4
5
6
7
|
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> } |
我們來定義實現(xiàn)類,通過 jdbctemplate 定義的數(shù)據(jù)訪問操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@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相關(guān)
1
2
3
4
5
6
7
|
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> } |
我們來定義實現(xiàn)類,service 層調(diào)用 dao 層的方法,這個是典型的套路。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
@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相關(guān)
為了展現(xiàn)效果,我們先定義一組簡單的 restful api 接口進行測試。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
@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 運行程序。
1
2
3
4
5
6
|
@springbootapplication (scanbasepackages = [ "com.lianggzone.demo.kotlin" ]) open class springkotlinapplication{ fun main(args: array<string>) { springapplication.run(springkotlinapplication:: class .java, *args) } } |
關(guān)于測試
這里,筆者推薦 idea 的 editor rest client。idea 的 editor rest client 在 intellij idea 2017.3 版本就開始支持,在 2018.1 版本添加了很多的特性。事實上,它是 intellij idea 的 http client 插件。參見筆者之前的另一篇文章: 快速測試 api 接口的新技能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
### 查詢用戶列表 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 |
總結(jié)
通過,上面這個簡單的案例,我們發(fā)現(xiàn) spring boot 整合 kotlin 非常容易,并簡化 spring 應用的初始搭建以及開發(fā)過程。為了讓讀者更加熟悉 kotlin 的語法糖,筆者會在未來的幾篇文章中,聊聊 kotlin 的新特性及其語法糖。
源代碼
相關(guān)示例完整代碼:spring-kotlin-samples
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:http://blog.720ui.com/2018/springboot2_kotlin_prime/