随着Vert.x进化到3.5.0,本系列也迎来了新篇章。

CORS的新变化

对于CORS,搞Web开发(不论你是前端,还是后端)的同志应该不陌生,尤其是如今微服务盛行的时代,CORS更是最常用的配置项之一。假若你对此还有一点点的疑问,不用问,你已经落伍了!

Vert.x很早就支持了CORS,但到了3.5.0,出于安全性上的考虑,它增加了一个限制:

当allowedOriginPattern为“*”时,allowCredentials不允许为“true”。

这个限制其实起源自协议的限制:

The string "*" cannot be used for a resource that supports credentials.The string "*" cannot be used for a resource that supports credentials.

即:Access-Control-Allow-Origin为“*”时,Access-Control-Allow-Credentials会被忽略,Credentials信息(一般是Cookie)也不会被user-agent发送。大家可以参考这篇文章(英文原版)了解如何安全地设置各个header。

在3.5.0时,当allowedOriginPattern为“*”和allowCredentials为“true”时,Vert.x会产生一个异常,若不处理会导致Verticle不能正常启动。在之前的版本中,不会出现这种情况。

CB for handler

断路器是个好东东,强烈建议在框架设计上就考虑它,以避免粗心的开发者写的代码扰乱其他好代码。在我写dgate和dfx时,对所有对外暴露的服务也都强加了这个限制。

既然CB这么好,是不是动过将其应用到普通Handler上的念头?不过由于Vert.x CB的文档示例中给出的都是清一色的HTTP请求的例子,要想将CB推而广之应用到普通的Handler上还得费点气力。

在dfx中我写了一个工具类,对此需求进行了封装:

public static void withCircuitBreaker(Vertx vertx, CircuitBreaker circuitBreaker, Accessible accessible, Map params, Handler<Map> successHandler, Handler<Throwable> failureHandler) {circuitBreaker.execute(future ->vertx.executeBlocking(f -> {try {f.complete(accessible.invoke(params));} catch (Throwable throwable) {f.fail(throwable);}}, result -> {if (result.succeeded()) {future.complete(result.result());} else {future.fail(result.cause());}})).setHandler(result -> {if (result.succeeded()) {successHandler.handle((Map) result.result());} else {logger.error("CB[{}] execution failed, cause: ", circuitBreaker.name(), result.cause());failureHandler.handle(result.cause());}});
}

它的使用很简单:

Utils.withCircuitBreaker(vertx, circuitBreaker, accessible, body.getMap(), result -> Utils.fireJsonResponse(response, 200, result), throwable -> Utils.fireSingleMessageResponse(response, 500, throwable.getMessage()));

各位可依葫芦画瓢将其改为自己的形式,其中的重点在于以“vertx.executeBlocking”方式来执行Handler的代码。

测试

在稍微正规的队伍中,自动化测试应该已经是一个标准实践了,并且Vert.x对于测试也提供了支持。

不过,我不喜欢。原因有几个:

  • Vert.x Unit是基于JUnit,而我已经有钟情的测试框架:Spock。相比起JUnit而言,后者简直可以说是Java测试领域的战斗机。
  • 好的单元测试本来就是要尽量少的依赖所用框架,注意这一点之后,尽力将类设计得好测试,这样的结果就是普通的单元测试类编写。既然有让人爽的工具用,也就没有必要去用Vert.x Unit了。
  • 对于集成测试,直接模拟实际的环境,再加上合适的timer,目前看来也还不错。而且Vert.x Unit中也一样需要用timer,这样一来,也就没有必要专门用它了。

为了证明我所言非虚,大家可以去看看dgate和dfx的测试代码。这里给出两个例子:

  • 集成测试
  • 单元测试

都是基于Spock写的,各位可以体验其酸爽度。

运行时外部配置

在本系列第一篇里,我就提出了一个钟意的工程结构组成,但里面没有提到“运行时外部配置文件”这一常见的实践。

经过若干项目的锤炼之后,目前对于这种运行时的外部配置文件,我基本形成了一个固定套路:Groovy DSL + Groovy ConfigSlurper。它俩简直是完成这一任务的绝配,比起Vert.x的提供的json配置文件要爽太多。

看看Gradle的build文件,你就可以知道这种DSL的灵活度可以到什么程度,更何况Groovy的语法对于Java开发者极其友好。

或许有人会觉得Groovy不酷,甚至有点鄙夷,言必称Scala、Clojure、Kotlin、Go或者Rust。对此,哥只想说:作为开发者,最让人鄙夷的是交不出活,客户才不关心你用什么语言呢!

配置DSL的例子:dgate配置

dgate是我写的一个基于vertx的轻量级网关,所有的配置全部通过配置文件来定义,无需数据库。关于它的详细介绍,可以参见其文档。为了说明上一节采用Groovy DSL的灵活度,这里展示几个dgate的配置例子。

静态Mock

利用dgate的mock功能,分离开的前后端开发人员可以并行工作,只需将mock响应配置到dgate的配置文件中就好。

"/summary" {expected {statusCode = 200payload {eqLocations = []opRateInLast30Days = []myOrgs = [["name": "org1", "admin": false]]}}
}

动态Mock

动态Mock为那些返回动态结果(如某些情况下成功,某些情况下失败)的URL模拟提供了便利。

"/login" {required = ["sub", "password"]methods = [HttpMethod.GET, HttpMethod.POST]expected {statusCode = 200payload = {JWTAuth jwtAuth = Utils.createAuthProvider(Vertx.vertx())JWTTokenGenerator tokenGenerator = new JWTTokenGenerator(jwtAuth)[token: tokenGenerator.token(["sub": "……", "name": "……", "role": "normal"], 200)]}}
}

上例将模拟一个实际的动态JWT,这样的好处在于,方便前端/移动端开发直接去完成刷新token或重新登录的过程,而不需要再针对此场景做其他特殊处理。

请注意,为了产生动态结果,此处的payload使用的是闭包,而不像前一例用的是Map。此时,闭包的返回值为Mock响应的结果。

以上的例子已经充分展现了将Groovy DSL作为运行时外部配置的能力,可以说是完胜Vert.x自带的json配置方式。

好啦,本期内容就此结束,请保持关注,期待下期继续!



本系列其他文章:

  • Vert.x入坑须知(1)
  • Vert.x入坑须知(2)

Vert.x入坑须知(3)相关推荐

  1. Vert.x入坑须知(2)

    当初创建简书账号的时候曾立下宏愿,希望保持周更,无奈现实残酷,整个5月都处于忙忙碌碌的状态,居然令这个本来并不算太宏伟的目标难以为继,最终导致5月份交了白卷![好吧,我承认,是我意志不够坚定,太懒了, ...

  2. 剑与远征服务器维护,剑与远征:海岛版本入坑须知注意点,少走弯路!

    哈喽,大家好!欢迎大家收看,不肝不游戏!我是疯子~ 最近疯子后台私信收到挺多小伙伴,想要一些新手向的攻略.等等!别问"这游戏还有人玩"的睿智提问,<剑与远征>能玩到现在 ...

  3. 我的世界java萌新须知_《原神》萌新入坑须知(全网最全,50个玩原神必备诀窍)...

    1.收集神瞳要标点. 如果你记忆力不好,也不够肝,那么在收集每一个风神瞳和岩神瞳的时候要标点,但是地图标点有100个上限,所以,131个岩神瞳收集,建议在米哈游社区的模拟器上标点.1.1版本有查找器, ...

  4. 万象物语一直显示服务器更新,《万象物语》新手入门攻略 入坑必看指南

    一.入坑须知 不管是这个游戏哪方面吸引了你决定入坑,想长期玩下去并享受到游戏的乐趣,请将这个游戏作为『休闲策略』游戏来对待. ※由于游戏内容尚未完善,大量玩法还在开发中,无体力的设定以及抽奖概率.运营 ...

  5. 新兵入坑 ——回顾NOIP2018

    新兵入坑--回顾NOIP2018 在这金秋时节,一年一度的NOIP来了,经过一年的学习,顺利通过初赛后,终于要展现新兵真正的技术了. 11月10日,所有竞赛班的同学乘大巴前往广州二中,一顿美味的午餐过 ...

  6. 发布开源框架到CocoaPods入坑指南

    个人原文博客地址: 发布开源框架到CocoaPods入坑指南 在开发过程中一定会用到一些第三方框架, 只要安装了CocoaPods, 然后通过pod install命令, 就可以集成框架到项目中了 可 ...

  7. 资源 |“从蒙圈到入坑”,推荐新一波ML、DL、RL以及数学基础等干货资源

    向AI转型的程序员都关注了这个号☝☝☝ 编译 | AI科技大本营(rgznai100) 参与 | suiling 此前营长曾发过一篇高阅读量.高转发率,高收藏量的文章<爆款 | Medium上6 ...

  8. 魔兽世界多玩服务器位置,选择服务器也有大学问?新手入坑《魔兽世界》该在哪里“扎根”...

    <魔兽世界:暗影国度>开服至今已经五个多月了,圈内圈外都在讨论新版本的话题,不少萌新与老玩家都选择了在这个版本中加入探索暗影界的行列.但面对茫茫多的区服,许多玩家都犯起了"选择困 ...

  9. 2020《图像分割》从入坑到出坑指南

    本文经授权转载自机器之心(almosthuman2014),来源:medium,作者:Jakub Czakon,编译:小舟.Racoon.张倩,未经授权禁止二次转载与摘编. 本文长度为2400字,建议 ...

最新文章

  1. java正则表达式 匹配%号_java正则表达式匹配带有括号的电话号为什么匹配不上...
  2. 2020人工神经网络第一次作业-参考答案第八部分
  3. java pl0 四元式,【编译原理】c++实现自下而上语法分析及中间代码(四元式)生成...
  4. Modbus教程| Modbus协议,ASCII和RTU帧,Modbus工作
  5. 美国实现Believe me I can fly, Believe me I can touch sky (2)
  6. L2-033 简单计算器 (25 分)-PAT 团体程序设计天梯赛 GPLT
  7. jms架构_JMS架构和JMS API架构
  8. Python网络爬虫与信息提取 - requests库入门
  9. java 编写a-z输出,有1-26个数字和a-z字母,用Java多线程实现先输出2和数字再输出2个字...
  10. 在eNSP通过云桥接到本机使用tftp服务器上传下载文件
  11. 【无标题】免费论文查重的方法;知网也可以免费查重啦
  12. Android开发笔记(一百八十一)使用CameraX拍照
  13. Python中print函数细节——默认换行
  14. 将OpenCV抓拍的图片进行x264编码并保存到文件
  15. 2019年:两成开发者月薪超1.7万,算法工程师最紧缺
  16. StyleGAN3重磅发布!皮肤、毛发不再粘屏幕,还能360度旋转!英伟达最新开源
  17. dbca识别不到已经存在的数据库
  18. android8.1新建分区并挂载,Android8.1 MTK Vendor分区大小调整无效分析
  19. 《各领域机器学习数据集汇总(附下载地址)》
  20. AppScan(4)安装证书和绕过登录深入扫描

热门文章

  1. icloud邮箱添加发件服务器地址,如何使用Mac创建iCloud电子邮件地址 | MOS86
  2. Arduino接收航模遥控器RC接收机的PWM数据
  3. 河南在中国数学类学会的人员分布
  4. matlab中使用阈值二值化,腐蚀,膨胀,反色等操作进行图像处理,去噪声,网纹、摩尔纹等
  5. Deeplav V3总结
  6. android桌面单词,让解锁屏幕从此变的有意义
  7. Docker 创建 Bamboo6.7.1 以及与 Crowd3.3.2 实现 SSO 单点登录
  8. IDEA自动生成实体类
  9. Airtest新增iOS、Windows录屏功能,真香
  10. 大二暑假_SSM项目_培训教育板块