Spring Boot和Kotlin的无缝整合与完美交融
前言
本文讲解SpringBoot2基础下,如何使用Kotlin,并无缝整合与完美交融。为了让读者更加熟悉Kotlin的语法糖,笔者会在未来的几篇文章中,聊聊Kotlin的新特性及其语法糖。下面话不多说了,来一起看看详细的介绍吧
环境依赖
修改POM文件,添加springboot依赖。
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中,dataclass默认没有无参构造方法,并且dataclass默认为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仓库。
数据源
方案一使用SpringBoot默认配置
使用SpringBoot默认配置,不需要在创建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")) openclassBeanConfig{ @Autowired privatelateinitvarenv:Environment @Bean openfundataSource():DataSource{ valdataSource=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() returndataSource } @Bean openfunjdbcTemplate():JdbcTemplate{ valjdbcTemplate=JdbcTemplate() jdbcTemplate.dataSource=dataSource() returnjdbcTemplate } }
脚本初始化
先初始化需要用到的SQL脚本。
CREATEDATABASE/*!32312IFNOTEXISTS*/`springboot_db`/*!40100DEFAULTCHARACTERSETutf8*/; USE`springboot_db`; DROPTABLEIFEXISTS`t_author`; CREATETABLE`t_author`( `id`bigint(20)unsignedNOTNULLAUTO_INCREMENTCOMMENT'用户ID', `real_name`varchar(32)NOTNULLCOMMENT'用户名称', `nick_name`varchar(32)NOTNULLCOMMENT'用户匿名', PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8;
使用JdbcTemplate操作
实体对象
classAuthor{ varid:Long?=null varrealName:String?=null varnickName:String?=null }
DAO相关
interfaceAuthorDao{ funadd(author:Author):Int funupdate(author:Author):Int fundelete(id:Long):Int funfindAuthor(id:Long):Author? funfindAuthorList():List}
我们来定义实现类,通过JdbcTemplate定义的数据访问操作。
@Repository openclassAuthorDaoImpl:AuthorDao{ @Autowired privatelateinitvarjdbcTemplate:JdbcTemplate overridefunadd(author:Author):Int{ returnjdbcTemplate.update("insertintot_author(real_name,nick_name)values(?,?)", author.realName,author.nickName) } overridefunupdate(author:Author):Int{ returnjdbcTemplate.update("updatet_authorsetreal_name=?,nick_name=?whereid=?", *arrayOf(author.realName,author.nickName,author.id)) } overridefundelete(id:Long):Int{ returnjdbcTemplate.update("deletefromt_authorwhereid=?",id) } overridefunfindAuthor(id:Long):Author?{ vallist=jdbcTemplate.query("select*fromt_authorwhereid=?", arrayOf (id),BeanPropertyRowMapper(Author::class.java)) returnlist?.get(0); } overridefunfindAuthorList():List { returnjdbcTemplate.query("select*fromt_author",arrayOf(),BeanPropertyRowMapper(Author::class.java)) } }
Service相关
interfaceAuthorService{ funadd(author:Author):Int funupdate(author:Author):Int fundelete(id:Long):Int funfindAuthor(id:Long):Author? funfindAuthorList():List}
我们来定义实现类,Service层调用Dao层的方法,这个是典型的套路。
@Service("authorService") openclassAuthorServiceImpl:AuthorService{ @Autowired privatelateinitvarauthorDao:AuthorDao overridefunupdate(author:Author):Int{ returnthis.authorDao.update(author) } overridefunadd(author:Author):Int{ returnthis.authorDao.add(author) } overridefundelete(id:Long):Int{ returnthis.authorDao.delete(id) } overridefunfindAuthor(id:Long):Author?{ returnthis.authorDao.findAuthor(id) } overridefunfindAuthorList():List{ returnthis.authorDao.findAuthorList() } }
Controller相关
为了展现效果,我们先定义一组简单的RESTfulAPI接口进行测试。
@RestController @RequestMapping(value="/authors") classAuthorController{ @Autowired privatelateinitvarauthorService:AuthorService /** *查询用户列表 */ @RequestMapping(method=[RequestMethod.GET]) fungetAuthorList(request:HttpServletRequest):Map{ valauthorList=this.authorService.findAuthorList() valparam=HashMap () param["total"]=authorList.size param["rows"]=authorList returnparam } /** *查询用户信息 */ @RequestMapping(value="/{userId:\\d+}",method=[RequestMethod.GET]) fungetAuthor(@PathVariableuserId:Long,request:HttpServletRequest):Author{ returnauthorService.findAuthor(userId)?:throwRuntimeException("查询错误") } /** *新增方法 */ @RequestMapping(method=[RequestMethod.POST]) funadd(@RequestBodyjsonObject:JSONObject){ valuserId=jsonObject.getString("user_id") valrealName=jsonObject.getString("real_name") valnickName=jsonObject.getString("nick_name") valauthor=Author() author.id=java.lang.Long.valueOf(userId) author.realName=realName author.nickName=nickName try{ this.authorService.add(author) }catch(e:Exception){ throwRuntimeException("新增错误") } } /** *更新方法 */ @RequestMapping(value="/{userId:\\d+}",method=[RequestMethod.PUT]) funupdate(@PathVariableuserId:Long,@RequestBodyjsonObject:JSONObject){ varauthor=this.authorService.findAuthor(userId) valrealName=jsonObject.getString("real_name") valnickName=jsonObject.getString("nick_name") try{ if(author!=null){ author.realName=realName author.nickName=nickName this.authorService.update(author) } }catch(e:Exception){ throwRuntimeException("更新错误") } } /** *删除方法 */ @RequestMapping(value="/{userId:\\d+}",method=[RequestMethod.DELETE]) fundelete(@PathVariableuserId:Long){ try{ this.authorService.delete(userId) }catch(e:Exception){ throwRuntimeException("删除错误") } } }
最后,我们通过SpringKotlinApplication运行程序。
@SpringBootApplication(scanBasePackages=["com.lianggzone.demo.kotlin"]) openclassSpringKotlinApplication{ funmain(args:Array){ SpringApplication.run(SpringKotlinApplication::class.java,*args) } }
关于测试
这里,笔者推荐IDEA的EditorRESTClient。IDEA的EditorRESTClient在IntelliJIDEA2017.3版本就开始支持,在2018.1版本添加了很多的特性。事实上,它是IntelliJIDEA的HTTPClient插件。参见笔者之前的另一篇文章:快速测试API接口的新技能
###查询用户列表 GEThttp://localhost:8080/authors Accept:application/json Content-Type:application/json;charset=UTF-8 ###查询用户信息 GEThttp://localhost:8080/authors/15 Accept:application/json Content-Type:application/json;charset=UTF-8 ###新增方法 POSThttp://localhost:8080/authors Content-Type:application/json { "user_id":"21", "real_name":"梁桂钊", "nick_name":"梁桂钊" } ###更新方法 PUThttp://localhost:8080/authors/21 Content-Type:application/json { "real_name":"lianggzone", "nick_name":"lianggzone" } ###删除方法 DELETEhttp://localhost:8080/authors/21 Accept:application/json Content-Type:application/json;charset=UTF-8
总结
通过,上面这个简单的案例,我们发现SpringBoot整合Kotlin非常容易,并简化Spring应用的初始搭建以及开发过程。为了让读者更加熟悉Kotlin的语法糖,笔者会在未来的几篇文章中,聊聊Kotlin的新特性及其语法糖。
源代码
相关示例完整代码:spring-kotlin-samples (本地下载)
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。