亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring Boot和Kotlin的無縫整合與完美交融

2024-07-14 08:41:13
字體:
來源:轉載
供稿:網友

前言

本文講解 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 中配置數據源信息。

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<Author>}

我們來定義實現類,通過 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<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 層的方法,這個是典型的套路。

@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<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 插件。參見筆者之前的另一篇文章: 快速測試 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 應用的初始搭建以及開發過程。為了讓讀者更加熟悉 Kotlin 的語法糖,筆者會在未來的幾篇文章中,聊聊 Kotlin 的新特性及其語法糖。

源代碼

相關示例完整代碼: spring-kotlin-samples

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久中文字幕| 日韩中文字幕在线免费观看| 91美女片黄在线观| 69**夜色精品国产69乱| 欧美在线视频a| 91在线色戒在线| 欧美精品免费在线| 久久影院中文字幕| 538国产精品一区二区在线| 97av在线播放| 97国产精品免费视频| 黄色成人av网| 亚洲精品一区二三区不卡| 久久在线免费观看视频| 国产精品88a∨| 精品国内亚洲在观看18黄| 亚洲成人网在线| 91精品综合久久久久久五月天| 亚洲综合日韩中文字幕v在线| 国产精品综合久久久| 国产精品91久久久久久| 一区二区三区国产在线观看| 国产精品欧美激情在线播放| 日韩成人激情视频| 国内精品久久久久久影视8| 国内精品中文字幕| 中文字幕久热精品在线视频| 国产欧美一区二区三区视频| 日韩男女性生活视频| 国产精品一区二区女厕厕| 欧美一级免费看| 欧美一区视频在线| 欧美性猛交xxxx偷拍洗澡| 亚洲精品国产精品自产a区红杏吧| 亚洲欧美第一页| 国产精品video| 久久人91精品久久久久久不卡| 97人人爽人人喊人人模波多| 97婷婷大伊香蕉精品视频| 最近2019年好看中文字幕视频| 欧美日产国产成人免费图片| 日韩一区二区精品视频| 亚洲自拍欧美另类| 久久久久国产精品免费| 91亚洲va在线va天堂va国| 国产精品国产三级国产专播精品人| 欧美日韩电影在线观看| 在线免费观看羞羞视频一区二区| 欧美日韩国产在线| 在线观看日韩专区| 国产精品中文久久久久久久| 久久视频在线观看免费| 美日韩精品免费视频| 高清一区二区三区日本久| 欧美影院久久久| 亚洲精品国产精品国自产在线| 色偷偷综合社区| 伊人伊成久久人综合网小说| 欧美老少配视频| 日韩免费在线免费观看| 91日本在线观看| 日韩视频永久免费观看| 亚洲乱码一区av黑人高潮| 亚洲在线免费视频| 国产精品88a∨| 国产欧美一区二区三区久久| 日韩av在线不卡| 国产精品视频专区| 国产精品久久激情| 亚洲乱码一区av黑人高潮| 欧美裸体xxxx| 亚洲国产成人在线播放| 91免费视频国产| 亚洲欧美日韩国产中文| 全球成人中文在线| 91免费在线视频| 亚洲美女在线视频| 久久成年人免费电影| 日韩在线视频中文字幕| 久久久欧美精品| 91影院在线免费观看视频| 欧美性猛交xxxx乱大交蜜桃| 亚洲美女久久久| 国产精品av电影| 日本精品久久中文字幕佐佐木| 日韩欧美中文免费| 日韩精品久久久久久久玫瑰园| 国产99久久久欧美黑人| 久久久久久久久久久免费| 欧美成人午夜激情视频| 2020欧美日韩在线视频| 欧美洲成人男女午夜视频| 国产欧美精品xxxx另类| 国产精品96久久久久久又黄又硬| 国产精品久久久久9999| 日韩欧美精品中文字幕| 亚洲一级一级97网| 国产区亚洲区欧美区| 亚洲福利视频专区| 日韩精品免费视频| 中文字幕在线观看日韩| 欧美激情高清视频| 国产极品jizzhd欧美| 一区二区三欧美| 欧美日韩精品二区| 日韩av网址在线观看| 精品福利免费观看| 91精品在线国产| 国产成人在线视频| 欧美性生交xxxxx久久久| 久久九九全国免费精品观看| 久久久精品视频在线观看| 欧美成人激情视频| 亚洲三级 欧美三级| 日韩精品在线私人| 日韩美女av在线免费观看| 国产精品久久久久久久久久新婚| 欧美特黄级在线| 日韩欧美在线字幕| 国产一区二区日韩精品欧美精品| 国产精品青草久久久久福利99| 97国产一区二区精品久久呦| 国产亚洲欧洲高清| 久久夜色精品国产| 国产热re99久久6国产精品| 亚洲成人a**站| 96精品视频在线| 91豆花精品一区| 亚洲精品视频网上网址在线观看| 狠狠躁18三区二区一区| 国产精品美女视频网站| 亚洲影影院av| 午夜精品蜜臀一区二区三区免费| 国产成人av网址| 97精品国产91久久久久久| 亚洲va久久久噜噜噜久久天堂| 精品欧美国产一区二区三区| 亚洲欧美另类国产| 亚洲va电影大全| 国产精品久久在线观看| 国产综合在线视频| 午夜精品福利在线观看| 日本一区二区在线播放| 91精品国产网站| 久久久久北条麻妃免费看| 性欧美暴力猛交69hd| 亚洲天堂av在线免费观看| 国产一区二区在线免费| 亚洲天堂男人的天堂| 国产精品 欧美在线| 欧美激情免费视频| 国产亚洲美女精品久久久| 永久免费毛片在线播放不卡| 亚洲国产欧美一区二区三区同亚洲| 亚洲在线免费看| 九九视频直播综合网| 亚洲男人第一av网站| 欧美激情第6页| 国产丝袜一区二区三区| 亚洲精品99久久久久中文字幕| 欧美激情一区二区三区成人| 欧美极品第一页| 欧美精品久久久久a| 亚洲一区第一页|