swagger codegen 在生成的文件中覆盖我的自定义代码

Posted

技术标签:

【中文标题】swagger codegen 在生成的文件中覆盖我的自定义代码【英文标题】:swagger codegen is overwriting my custom code in generated files 【发布时间】:2015-05-28 22:56:15 【问题描述】:

我使用 swagger codegen 生成 jaxrs 服务器端类和客户端 java 类。

这是我用来生成类的命令

java -jar modules/swagger-codegen-distribution/target/swagger-codegen-distribution-2.1.2-M1.jar   -i /Users/me/Workspace/swagger-codegen/samples/yaml/echo.yaml   -l jaxrs   -o samples/server/echo/java

生成的服务器代码有一个占位符来写我的“魔法”。

public Response echo(@ApiParam(value = ""  )@HeaderParam("headerParam") String headerParam,
    @ApiParam(value = "",required=true) @QueryParam("message") String message)
      throws NotFoundException 
      // do some magic!
      return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
  

我在“echo”方法中添加了“魔法”并重新生成了代码,结果却发现它消失了。避免丢失自定义代码的一种方法是修改 codegen 模板以生成接口而不是类。然后我可以在实现的类中拥有所有自定义代码。

我正在尝试找出是否有一种方法可以在重新生成代码后保留自定义“魔法”,或者是否有比更改模板生成接口而不是类更好的方法来处理这种情况。

【问题讨论】:

另见grokbase.com/t/gg/swagger-swaggersocket/153s7d49nr/… 【参考方案1】:

Swagger Codegen的最新master允许您在代码生成过程中指定文件在.swagger-codegen-ignore(类似于.gitignore)中被覆盖。

请拉最新的Swagger Codegen高手试试看。

更新:2018 年 5 月,Swagger Codegen 的大约 50 位***贡献者和模板创建者决定分叉 Swagger Codegen 以维护一个名为 OpenAPI Generator 的社区驱动版本。更多信息请参考Q&A。

【讨论】:

将文件添加到 .swagger-codegen-ignore 后合并新端点样板代码的工作流程是什么? 它确实应该生成一个带有方法的类,而不仅仅是函数。然后我们可以干净地继承它。【参考方案2】:

您可以在.swagger-codegen-ignore文件中指定要忽略的文件

这是.swagger-codegen-ignore 文件的示例自我解释自动生成的代码

# Swagger Codegen Ignore
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

您可以在下面添加一些行来忽略,例如我想忽略文件夹 impl 中的所有文件,所以我添加了以下行来做到这一点

**/impl/*

【讨论】:

【参考方案3】:

你好, 也许四年后答案来得有点晚,但迟到总比不来好。

如果你有一个正确的 swagger 文件(不仅仅是一个片段),如下所示

openapi: "3.0.0"
:
paths:
  /example:
    get:
      operationId: showIt
:

然后您运行代码生成,在此说明中针对 jaxs-jersey-server 没有任何代码生成特定配置值(您可以从 Swagger editor),你会得到大量的 java 类,如下所示:

io.swagger.api.          ExampleApi
io.swagger.api.          ExampleApiService
io.swagger.api.factories.ExampleApiServicefactory
io.swagger.api.impl.     ExampleApiServiceImpl

在 REST 端点实现 ExampleApiServiceImpl 中,您或多或少会看到以下内容:

package io.swagger.api.impl;

:
import ... ;
:

@javax.annotation.Generated(...)
public
class   ExampleApiServiceImpl
extends ExampleApiService

    // ...
    @Override
    public
    Response showIt( /* additional parameters , */ SecurityContext securityContext)
    throws NotFoundException
    
        // do some magic!
        return Response.ok()
                       .entity(new ApiResponseMessage( ApiResponseMessage.OK
                                                     , "magic!"
                                                     )
                              )
                       .build();
    
    // ...

你现在交换魔法评论了吗

        // do some magic!

可能通过以下方式

        String className = this.getClass().getSimpleName();
        System.out.println("Entered REST endpoint: path=|" + className.substring(0, className.length() - 14) + "| operationId=|showId|");

如果您在完成mvn clean package jetty:run 后从浏览器调用端点,您应该会看到一条日志消息。但这不是一个好主意,正如您意识到的那样,因为在下一代之后,您的更改就消失了。

在这种情况下,手动更改生成的代码绝不是一个好主意,因为这必须有很好的文档记录,以便未来的同事(可能在几个月或几年后)即使是你)即使在星期一晚上的星期日半睡半醒,也会在下一次代码生成后再次进行更改。 但是我 20 多年使用不同代码生成器的经验只能说明这一点:算了! 出于同样的原因,在第一代之后阻止进一步的生成并不是真正面向目标的,因为这也必须被广泛记录。否则,调试时间超过调试时间可能会解决新功能不起作用的问题。

但这都不是必需的。 在生成的类 io.swagger.api.ExampleApi 中会发现如下构造函数(好吧,就是2019-05-17的状态,不知道是不是一样(或类似的)四年前)

package io.swagger.api;

:
import ... ;
:

@Path("/example")

@javax.annotation.Generated(...)
public class ExampleApi

   private final ExampleApiService delegate;

   public ExampleApi(@Context ServletConfig servletContext)
   
      // ...
      if (servletContext != null) 
         String implClass = servletContext.getInitParameter("ExampleApi.implementation");
         if (implClass != null && !"".equals(implClass.trim()))
         
            try
            
               delegate = (ExampleApiService) Class.forName(implClass).newInstance();
            
            catch (Exception e)
            
               throw new RuntimeException(e);
            
          
      
      // ...
    
// ...

重要的代码是servletContext.getInitParameter("...")。如果您现在在 servlet 配置中指定名称为 ExampleApi.implementation 的键以及从 ExampleApiService 派生的完整限定 java 类名,那么您已经实现了自己的端点代码,该端点代码可以安全地覆盖未来的代码生成。

为了完成示例,此规范将在(附加生成,oouuch,抱歉,您不能拥有所有内容)web.xml 文件中。该文件包含以下内容:

    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        ...
        <load-on-startup>1</load-on-startup>
    </servlet>

在这个 xml 片段中,您必须在句点(代表其他 servlet 配置设置)之后插入以下内容:

        <init-param>
            <param-name>ExampleApi.implementation</param-name>
            <param-value>my.swagger.api.MyExample</param-value>
        </init-param>

好看, 不管你现在是什么!

【讨论】:

您能否就我的问题提供一些意见***.com/q/58521289/1700711 这实际上也适用于 maven openapi codegen 插件! .openapi-generator-ignore 将在 target/generated-sources 目录中生成并且可以/不应更新,因此这是 mvn 用户的最佳解决方案。

以上是关于swagger codegen 在生成的文件中覆盖我的自定义代码的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 swagger-codegen 中定义新的 mustache 模板变量吗?

Swagger Codegen OneOf 生成不正确

java:swagger-codegen生成CSharp(C#) Client

将生成的 Flask 应用程序代码(Swagger-Codegen)粘合到后端实现的最简洁方法

如何避免swagger codegen接口中的默认方法实现?

swagger-codegen 或 openapi-generator PHP 版本