前言
swagger ui是一个采纳注解驱动的接口文档工具,目前已反对规范的open api v3标准协定,所以不仅能够在java我的项目里应用,每个语言都有相应的open api实现。我的项目集成swagger后,能够生成导出open api v3格式化的元数据集,有了这个接口元数据,你能够在任何反对v3协定的ui上展现你的api信息。在前后端拆散的我的项目中,swagger ui的呈现,大大提高了前后端联调的效率。swagger ui在解析注解标注的元数据信息时,特地场景下会抛异样,而且抛的异样没有直观的有价值的异样信息,所以深刻的debug了一番,尽管最初问题解决很简略,然而过程十分波折。故将bug定位过程记录在此。
- 影响的Swagger版本:1.5.x
- Swagger core:https://github.com/swagger-api/swagger-core
- OpenApi v3标准:https://github.com/OAI/versions/3.0.0.md
异样信息
这个异样只会在加载swagger-ui的页面时会抛出,每次刷新页面,获取一次api接口就会触发一次异样。
异样剖析
@JsonProperty("x-example")public Object getExample() { if (example == null) { return null; } try { if (BaseIntegerProperty.TYPE.equals(type)) { return Long.valueOf(example); } else if (DecimalProperty.TYPE.equals(type)) { return Double.valueOf(example); } else if (BooleanProperty.TYPE.equals(type)) { if ("true".equalsIgnoreCase(example) || "false".equalsIgnoreCase(defaultValue)) { return Boolean.valueOf(example); } } } catch (NumberFormatException e) { LOGGER.warn(String.format("Illegal DefaultValue %s for parameter type %s", defaultValue, type), e); } return example;}
如上是异样相干的代码。从异样信息表象来看,是一个强转导致的问题,代码试图将一个空的字符串转换成数值类型导致异样抛出。并且是getExample时抛出的异样,这里须要理解swagger ui的加载过程和基础架构能力间接定位。swagger中的example是为了在生成的api doc中,给出相干字段的调用示例,并在触发接口调用时,默认主动填充example的值。这里显然是哪个中央的example设置不合理导致的异样。那么,接下来要做的就是找到这个空字符串的原始代码。
debug找到实在起因
借助IDEA的debug性能,点击异样前面的create breakpoint,在触发异样的中央打上断点。触发异样,进入断点,获取到了要害信息
一个被形容为app id的字段,用这个信息全局搜寻,失去如下的后果:
有三个相干的Model实体,首先,这三个Model的appId字段都没有设置过example属性,所以,到这一步,能够先下一个小的论断,不是咱们设置的example导致的问题,默认在不设置的状况下,example的默认值就是空字符串。而后必定只有其中一个有问题,因为异样只会触发一次。在不晓得后果状况下,顺次对这三个Model的appId字段加上正确的example形容,经测试,只有GetAppBannerRequestDTO加上时,异样才隐没,罪魁祸首就是它了。然而,为什么呢?其余两个Model为啥就没有问题呢?在博主穿插测验后,发现了最终的起因。
论断及注意事项
当Model作用于申请的接管参数时,并且申请的类型为GET,那么Swagger Ui会主动收集Model所有属性的examole参数,因为这个参数是字符串类型,所以会做一个类型转换动作。当字段类型为数值类型,又有没手动设置example的值,那么Swagger框架拿到的是个空字符串,强转空字符串就抛异样了。而如果申请是POST,就不会触发这段逻辑,所以同为携带数值类型DTO的ImgReplaceRequestDTO没有问题。如果不是接管参数,作为响应参数,也不会触发这段逻辑,故而AppBannerResponseVO也就没有问题了。所以,须要留神的就是当DTO作用于GET申请的接管参数时,切记给所有的数值类型加上正确的example属性
后记
博主认为这里属于一个设计缺点,而不是咱们的应用问题。在获取example的逻辑里,第一段代码就判断了example是否为null。这表明了example有可能为空,然而默认值却设置了一个空字符串。代表不手动将example设置为null,这段判null返回的逻辑就永远跑不到,而且没人会这么做,手动给example设置为null。况且,在触发异样的这种场景下,框架不能强制使用者设置example这种操作。在github仓库追踪这块代码发现,目前Swagger ui曾经迈入了3.x版本,全面基于open api v3协定标准设计。所以,这部分代码齐全不一样了。而存档的1.5x版本这个问题仍旧。
上面是3.x的解决形式,尽管example的默认值还是“”。然而通过NotBlank判断了下,所以不会触发异样了
为啥不间接降级3.x?
3.x版本既然曾经修复了,为啥不间接降级到3.x版本呢?可能有人会有这个疑难。Swagger3.x版本属于一个大跨度的迭代版本,和之前的版本齐全不兼容,3.x次要面向了open api v3标准协定设计实现,注解实体等模型都是一一对应的。而在这个版本之前的1.5x系列版本是Swagger本人设计的api模型。所以代码层下面齐全不兼容,降级的工作量会十分大。不过,新我的项目还是举荐应用3.x版本,这个版本的api数据更通用。能够依据api的数据生成各种语言的客户端包。就像proto生成客户端包一样。