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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。