您现在的位置是:首页 > 文章详情

SpringBoot 与 Kotlin 完美交融

日期:2018-11-28点击:506

本文讲解 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 中配置数据源信息。


<pre>

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

</pre>


方案二 手动创建

在 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 层的方法,这个是典型的套路。

    @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 插件。

### 查询用户列表 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 的新特性及其语法糖。


源代码

相关示例完整代码: https://github.com/lianggzone/spring-kotlin-samples


相关推荐:https://www.roncoo.com/course/list.html?courseName=spring+boot



原文链接:https://blog.roncoo.com/article/133272
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章