Spring Boot和Kotlin无缝整合与完美交融的示例分析
这篇文章主要介绍了Spring Boot和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无缝整合与完美交融的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!