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

时间:2015-03-25 10:14:02

标签: swagger codegen

我使用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();
  }

我添加了#34;魔法"在" echo"方法并重新生成代码,只看到它消失了。避免丢失自定义代码的一种方法是修改codegen模板以生成接口而不是类。然后我可以在实现的类中拥有所有自定义代码。

我试图找出是否有办法保存自定义"魔法"甚至在重新生成代码之后,或者有更好的方法来处理这种情况,而不是更改模板以生成接口而不是类。

3 个答案:

答案 0 :(得分:2)

Swagger Codegen的最新版本允许您在代码生成期间指定要在.swagger-codegen-ignore(类似于.gitignore)中覆盖的文件 not

请拉出最新的Swagger Codegen大师试一试。

更新:2018年5月,Swagger Codegen的约50名顶级贡献者和模板创建者决定将Swagger Codegen分叉,以维护一个名为OpenAPI Generator的社区驱动版本。有关详细信息,请参阅Q&A

答案 1 :(得分:1)


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

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

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且具有完全合格的Java类名的键,该键是从ExampleApiService派生的,则您已经实现了自己的终结点代码,可以安全地覆盖以后的代码世代

为完成该示例,此规范将在(附加生成的 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>

好看,
无论您现在是什么!

答案 2 :(得分:0)

您可以在.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/*