博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot 与 Kotlin 完美交融
阅读量:6031 次
发布时间:2019-06-20

本文共 10069 字,大约阅读时间需要 33 分钟。

本文讲解 Spring Boot2 基础下,如何使用 Kotlin,并无缝整合与完美交融。

环境依赖

修改 POM 文件,添加 spring boot 依赖。

org.springframework.boot
spring-boot-starter-parent
2.0.2.RELEASE
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-jdbc
复制代码

紧接着,我们需要添加 mysql 依赖。

mysql
mysql-connector-java
5.1.35
com.alibaba
druid
1.0.14
复制代码

最后,添加 Kotlin 依赖。

org.jetbrains.kotlin
kotlin-stdlib-jdk8
org.jetbrains.kotlin
kotlin-reflect
org.jetbrains.kotlin
kotlin-stdlib
复制代码

注意的是,在 Kotlin 中,data class 默认没有无参构造方法,并且 data class 默认为 final 类型,不可以被继承。注意的是,如果我们使用 Spring + Kotlin 的模式,那么使用 @autowared 就可能遇到这个问题。因此,我们可以添加 NoArg 为标注的类生成无参构造方法。使用 AllOpen 为被标注的类去掉 final,允许被继承。

kotlin-maven-plugin
org.jetbrains.kotlin
${kotlin.version}
compile
compile
test-compile
test-compile
org.jetbrains.kotlin
kotlin-maven-noarg
${kotlin.version}
org.jetbrains.kotlin
kotlin-maven-allopen
${kotlin.version}
复制代码

至此,我们 Maven 的依赖环境大致配置完毕。完整的源码,可以参见文末 GitHub 仓库。

数据源

方案一 使用 Spring Boot 默认配置

使用 Spring Boot 默认配置,不需要在创建 dataSource 和 jdbcTemplate 的 Bean。

src/main/resources/application.properties 中配置数据源信息。

spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3307/springboot_dbspring.datasource.username=rootspring.datasource.password=root
复制代码

方案二 手动创建

src/main/resources/config/source.properties 中配置数据源信息。

# mysqlsource.driverClassName = com.mysql.jdbc.Driversource.url = jdbc:mysql://localhost:3306/springboot_dbsource.username = rootsource.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
}复制代码

我们来定义实现类,通过 JdbcTemplate 定义的数据访问操作。

@Repositoryopen 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
("select * from t_author where id = ?", arrayOf
(id), BeanPropertyRowMapper(Author::class.java)) return list?.get(0); } override fun findAuthorList(): List
{ 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
}复制代码

我们来定义实现类,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
{ 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
{ val authorList = this.authorService.findAuthorList() val param = HashMap
() 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
) { 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/authorsAccept : application/jsonContent-Type : application/json;charset=UTF-8### 查询用户信息GET http://localhost:8080/authors/15Accept : application/jsonContent-Type : application/json;charset=UTF-8### 新增方法POST http://localhost:8080/authorsContent-Type: application/json{    "user_id": "21",    "real_name": "梁桂钊",    "nick_name": "梁桂钊"}### 更新方法PUT http://localhost:8080/authors/21Content-Type: application/json{    "real_name" : "lianggzone",    "nick_name": "lianggzone"}### 删除方法DELETE http://localhost:8080/authors/21Accept : application/jsonContent-Type : application/json;charset=UTF-8复制代码

总结

通过,上面这个简单的案例,我们发现 Spring Boot 整合 Kotlin 非常容易,并简化 Spring 应用的初始搭建以及开发过程。

欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

转载于:https://juejin.im/post/5cb69b5b6fb9a068b9582e4e

你可能感兴趣的文章
在Office应用中打开WPF窗体并且让子窗体显示在Office应用上
查看>>
Linux常用基本命令:uniq-去重复
查看>>
workflow的简介
查看>>
springcloud超时时间与重试次数配置
查看>>
Unity3D客户端实时同步技术
查看>>
布隆过滤器(Bloom Filter)详解
查看>>
oracle 11g创建表空间与赋予用户全校性
查看>>
Cocos2d游戏开发之(一)多触点与触屏事件详解
查看>>
Directx教程(28) 简单的光照模型(7)
查看>>
Hadoop在MapReduce中使用压缩详解
查看>>
读Ext之十一(通过innerHTML创建元素)
查看>>
todos 应用实践
查看>>
C#事件-自定义事件的使用方法
查看>>
通俗理解C#委托和事件
查看>>
O-C浮点数转化整数
查看>>
解决win10打开组策略弹出管理模板对话框问题
查看>>
C++用数组和链表分别实现Queue
查看>>
HDU_1158 Employment Planning(DP)
查看>>
oracle 函数WMSYS.WM_CONCAT()的用法(让查询结果行转列)
查看>>
遭遇ASP.NET的Request is not available in this context
查看>>