院前修复程序或“嘿招摇! 我的错误在哪里?”

您是否曾在修补程序中对主服务器进行过调整? 不? 但是我成功了!

这个故事是关于我如何忘记更新文档的故事。 结果,我(第二次)为Swagger编写了一个插件。 以及我如何被带走,以至于我忘记了请病假,并继续接受治疗!


还有更多关于Optional 而非 Java 8的信息。

我们使用Swagger创建交互式文档。

因此,当您在API中创建方法时,则:

0.添加必要的注释,例如@RequestMapping等。

1.添加@ErrorCodes(我们自己的注释),并列出此方法可能在响应中返回的字符串错误代码。

2.添加@ApiOperation并在notes字段中复制有关这些错误的信息。

3.添加其余注释...

看起来像这样(删除不必要和简化):

@ApiOperation( value = "Some description.", notes = "List of possible error codes:" + "<ul>" + " <li>sms.verification.code.fail</li>" + "</ul>") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) {... } 

当我添加@ErrorCodes时,第2点是我失败的根源,但忘了在@ApiOperation中列出字符串错误代码。 我对自己感到满意,但有些不安,所以我向代码审查提交了“拉取请求”。 在这里,他们告诉我我忘了笔记! 他们还解释说Swagger不会从@ErrorCodes获取信息,这就是为什么您必须手动注册它。 那天晚上,一切都愉快地结束了。 纠正了他的缺陷,请病假。

继续前进可能是正常的。 在其他人的架子上放一个复选标记,就像他们说的一样,Max,请注意,注意...

但是我没有成功。 整个晚上和第二天早上都花时间教Swagger阅读我们的注释,并在注释中独立添加这些相同的代码。

步骤1.有人在这里...


通过粗略的搜索,我设法发现有人已经尝试使用其注释将Swagger交朋友。 还有一个指向SpringFox文档的链接,其中说您可以编写一个插件!

幸福的幸福已经遮盖了我很多,我什至忘记了普通的感冒和病假! 在我未来的文章“如何不三次退出公司”中,我分享了三个挽救溺水者的故事。 其中之一是关于我如何设法为Chrome + Firefox编写了一个插件,该插件多次加速了Jenkins的工作。 我写得真有趣! 毕竟,这是一个微型项目! 我的启动非常非常简单,但是有真正的人使用它。 然后我又摆脱了常规,找到了灵感。 倦怠不见了。 但我会在以后的文章中更好地讨论这一点。 同时,回到Swagger插件。

动作2。有效!


编写工作很容易。 我以SpringFox官方文档中的插件为例,删除了所有不必要的内容并添加了正确的内容。

插件。 版本1
 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { /** * Appends note of operation. Adds error codes to note of operation. * <code> * <h3>List of possible errors:</h3> * <ul> * <li>error.code.1</li> * <li>error.code.2</li> * <li>error.code.3</li> * </ul> * </code> * @param context operation context */ @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod(); // Check method is annotated by @ErrorCodes ErrorCodes errorCodes = findAnnotation(operationMethod, ErrorCodes.class); if (errorCodes == null) { return; } StringBuilder errorCodesNote = new StringBuilder(); errorCodesNote.append("<h3>List of possible errors:</h3>"); errorCodesNote.append("<ul>"); for (String errorCode: errorCodes.values()) { errorCodesNote.append("<li>").append(errorCode).append("</li>"); } errorCodesNote.append("</ul>"); // Write new version of notes. context.operationBuilder().notes(errorCodesNote.toString()).build(); } @Override public boolean supports(DocumentationType delimiter) { return SwaggerPluginSupport.pluginDoesApply(delimiter); } } 


我开始使用未为@ApiOperation中的注释指定值的方法进行测试。

 @ApiOperation(value = "Some description.") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) { ... } 

启动并...结果! 太好了,它有效! 注释中出现了sms.verification.code.fail字符串代码!



步骤3,它可以工作,但是不起作用。


然后我在笔记中添加了一些单词,然后得到了以下代码:

 @ApiOperation(value = "Some description.", notes = "Some initial note.") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) { ... } 

再次发射。 结果是...出乎意料。 SpringFox插件在生成文档(O_o)时会覆盖注释值!

我查看context.operationBuilder()。Notes(字符串)的工作方式,并在其中看到以下内容:

 public OperationBuilder notes(String notes) { this.notes = (String)BuilderDefaults.defaultIfAbsent(notes, this.notes); return this; } 

嗯...好的,那么我们将获取便笺的当前值并添加错误代码。 仍然需要获取@ApiOperation批注,获取所需的值并添加到我正在形成的自己中。

因此,最终版本( 可在gist.github.com上找到

插件。 版本2
 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { /** * Appends note of operation. Adds error codes to note of operation. * <code> * <h3>List of possible errors:</h3> * <ul> * <li>error.code.1</li> * <li>error.code.2</li> * <li>error.code.3</li> * </ul> * </code> * @param context operation context */ @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod(); // Check method is annotated by @ApiOperation ApiOperation apiOperation = findApiOperationAnnotation(operationMethod).orNull(); if (apiOperation == null) { return; } // Check method is annotated by @ErrorCodes ErrorCodes errorCodes = findAnnotation(operationMethod, ErrorCodes.class); if (errorCodes == null) { return; } // Prepend notes by using current value of notes in @ApiOperation StringBuilder errorCodesNote = new StringBuilder(apiOperation.notes()); errorCodesNote.append("<h3>List of possible errors:</h3>"); errorCodesNote.append("<ul>"); for (String errorCode: errorCodes.values()) { errorCodesNote.append("<li>").append(errorCode).append("</li>"); } errorCodesNote.append("</ul>"); // Write new version of notes. context.operationBuilder().notes(errorCodesNote.toString()).build(); } @Override public boolean supports(DocumentationType delimiter) { return SwaggerPluginSupport.pluginDoesApply(delimiter); } } 


现在事实证明了!



第4步。非Java 8的Optional怎么样?


在开始使用插件时,我无法理解Optional的问题,在搜索注释时会返回Optional。 此类没有用于java.util.Optional的标准方法。 例如,没有ifPresent方法,但是有一个orNull方法。
事实证明,SpringFox使用了Guava中的 Optional

TL; DR


我为SpringFox编写了一个插件,它是一个Spring组件,在文档生成阶段被调用以从我们的@ErrorCodes批注中读取值。

插件代码
 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { /** * Appends note of operation. Adds error codes to note of operation. * <code> * <h3>List of possible errors:</h3> * <ul> * <li>error.code.1</li> * <li>error.code.2</li> * <li>error.code.3</li> * </ul> * </code> * @param context operation context */ @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod(); // Check method is annotated by @ApiOperation ApiOperation apiOperation = findApiOperationAnnotation(operationMethod).orNull(); if (apiOperation == null) { return; } // Check method is annotated by @ErrorCodes ErrorCodes errorCodes = findAnnotation(operationMethod, ErrorCodes.class); if (errorCodes == null) { return; } // Prepend notes by using current value of notes in @ApiOperation StringBuilder errorCodesNote = new StringBuilder(apiOperation.notes()); errorCodesNote.append("<h3>List of possible errors:</h3>"); errorCodesNote.append("<ul>"); for (String errorCode: errorCodes.values()) { errorCodesNote.append("<li>").append(errorCode).append("</li>"); } errorCodesNote.append("</ul>"); // Write new version of notes. context.operationBuilder().notes(errorCodesNote.toString()).build(); } @Override public boolean supports(DocumentationType delimiter) { return SwaggerPluginSupport.pluginDoesApply(delimiter); } } 

Source: https://habr.com/ru/post/zh-CN420841/


All Articles