为了账号安全,请及时绑定邮箱和手机立即绑定

使用Kotlin开发Webflux应用

使用技术。kotlin,gradle,SpringBoot2.0,WebFlux,Mybatis,Thymeleaf

技术介绍

Kotlin** 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。

Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。

在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言。

而Spring5之后,大部分Spring系框架也支持了kotlin。

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的语言。

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

WebFlux 模块的名称是 spring-webflux,名称中的 Flux 来源于 Reactor 中的类 Flux。该模块中包含了对反应式 HTTP、服务器推送事件和 WebSocket 的客户端和服务器端的支持。对于开发人员来说,比较重要的是服务器端的开发,这也是本文的重点。在服务器端,WebFlux 支持两种不同的编程模型:第一种是 Spring MVC 中使用的基于 Java 注解的方式;第二种是基于 Java 8 的 lambda 表达式的函数式编程模型。这两种编程模型只是在代码编写方式上存在不同。它们运行在同样的反应式底层架构之上,因此在运行时是相同的。WebFlux 需要底层提供运行时的支持,WebFlux 可以运行在支持 Servlet 3.1 非阻塞 IO API 的 Servlet 容器上,或是其他异步运行时环境,如 Netty 和 Undertow。

Thymeleaf是用于Web和独立环境的现代服务器端Java模板引擎。Thymeleaf的主要目标是将优雅的自然模板带到您的开发工作流程中—HTML能够在浏览器中正确显示,并且可以作为静态原型,从而在开发团队中实现更强大的协作。Thymeleaf能够处理HTML,XML,JavaScript,CSS甚至纯文本。Thymeleaf的主要目标是提供一个优雅和高度可维护的创建模板的方式。 为了实现这一点,它建立在自然模板的概念之上,以不影响模板作为设计原型的方式将其逻辑注入到模板文件中。 这改善了设计沟通,弥合了前端设计和开发人员之间的理解偏差。Thymeleaf也是从一开始就设计(特别是HTML5)允许创建完全验证的模板。

创建

创建项目,使用Spring工具创建 网址 https://start.spring.io/

注意构建工具,语言,引入依赖

点击>构建项目

解压压缩包。将内容放到项目目录。使用IDEA打开这个项目。

整理项目

将包名整理一下,构建工具将会把项目名也构建到包中,需要删除。

配置

application.yml

server:
  port: 3011
mybatis:
    mapperLocations: classpath:mapper/*.xml
logging:
  level:
    root: debug
spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: 123456
        url: jdbc:mysql://localhost:3306/webflux_demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        hikari:
              driver-class-name: com.mysql.cj.jdbc.Driver
              maximum-pool-size: 30

日志请调制Debug,因为异常运行异常只有在Debug才能看到

创建CityEntiy.kt

data class CityEntity(var id: Long?=0L,
                      var name: String = "",
                      var privinceId: Long = 0L,
                      var description:String ="")

kotlin有一个data修饰符,修饰class,这个类将会变成实体类,自动生成get,set。

创建CityDao.kt

@Mapper
interface CityDao {
    @Select("select id,name,privince_id,description from city ")
    fun findAll(): List<CityEntity>

    @Select("insert  into city (name,privince_id,description ) values (#{name},#{privince_id},#{description})")
    fun insert(entity: CityEntity): Int

}

这里比较简单,使用了Select注解,没有使用xml。

创建CityService.kt

@Service
class CityService {
    @Autowired
    private lateinit var cityDao:CityDao


    fun getAll(): Flux<CityEntity> {
        var list=cityDao.findAll()
        //此处应该使用流处理,但是不知道为什么一直报错
        /**
         *
        val flux = Flux.push<CityEntity> { fluxSink ->
        list.stream().collect(data->{fluxSink.next(data) })
        fluxSink.complete()
        }
         */
        val flux = Flux.push<CityEntity> { fluxSink ->
            for (entity in list) {
                fluxSink.next(entity);
            }
            fluxSink.complete()
        }
        return flux
    }
}

创建CityController

@Controller
@RequestMapping("/")
class CityController {
    @Autowired
    private lateinit var cityService: CityService
    
    @GetMapping()
    fun getAll(model:Model): Mono<String> {
         var list=cityService.getAll()
        model.addAttribute("list",list)
        return Mono.create { monoSink -> monoSink.success("cityList") }
    }
}

创建cityList.html

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8"/>
    <title>城市列表</title>
</head>
<body>
<div>
    <table>
        <legend>
            <strong>城市列表</strong>
        </legend>
        <thead>
        <tr>
            <th>城市编号</th>
            <th>省份编号</th>
            <th>名称</th>
            <th>描述</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="city : ${list}">
            <td th:text="${city.id}"></td>
            <td th:text="${city.privinceId}"></td>
            <td th:text="${city.name}"></td>
            <td th:text="${city.description}"></td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

创建数据库和表

create database webflux_demo;

创建表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

CREATE TABLE `city`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `privince_id` int(11) NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `city`(name,privince_id,description ) VALUES ( '河南', 0, '河南省');

运行

Github地址

mybatis的entity必须有无参构造函数

如果发现没有无参构造函数,将会报错

所以在data class中,所有的变量都需要有默认值。

点击查看更多内容
6人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
2674
获赞与收藏
170

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消