如何在 swagger codegen 中注入自定义 spring 验证?

问题描述 投票:0回答:2

我们能够使用 openApi 文档并使用 spring swagger-codegen 生成 Java 输入类。此外,我们可以在为常见约束(如长度、强制等)生成输入时注入 javax.validation 注释。

我希望将其提升到下一个自定义级别,并能够使用与 Spring 的 @Constraint 注释挂钩的自定义验证注释来注释生成的输入类。这样我们就可以为我们的项目重用特定的验证。

我希望有一个开箱即用的解决方案。您使用自定义验证注释生成输入类的首选方法是什么?

java swagger-2.0 swagger-codegen spring-validator swagger-codegen-maven-plugin
2个回答
11
投票

我没有找到“开箱即用的解决方案”。但 openapi-generator 提供了一种通过编辑 Mustache 模板来修改生成代码的简单方法。这就是我解决与你完全相同的问题的方法。

基本上,我在 OpenAPI 规范中创建了自定义字段,在其中指定了自定义约束注释(在我的例子中为 @EvenLong)。我称这个字段为“x-constraints”:

...
components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
          x-constraints: "@EvenLong"
        name:
          type: string
        tag:
          type: string
...

然后我告诉 openapi-generator 在哪里寻找我的自定义/修改的胡子模板。我使用 openapi-generator 作为 Maven 插件,因此我将 templateDirectory 属性添加到 pom.xml 中的插件定义中:

...
<plugin>
   <groupId>org.openapitools</groupId>
   <artifactId>openapi-generator-maven-plugin</artifactId>
   <version>4.3.1</version>
   <executions>
      <execution>
         <goals>
            <goal>generate</goal>
         </goals>
         <configuration>
            <inputSpec>
               ${project.basedir}/src/main/resources/openapi/specs/petstore.yaml
            </inputSpec>
            <templateDirectory>
              ${project.basedir}/src/main/resources/openapi/templates
            </templateDirectory>
            <generatorName>spring</generatorName>
            <apiPackage>sk.matusko.tutorial.openapicustomvalidations.api</apiPackage>
            <modelPackage>sk.matusko.tutorial.openapicustomvalidations.model</modelPackage>
            <configOptions>
               <interfaceOnly>true</interfaceOnly>
            </configOptions>
         </configuration>
      </execution>
   </executions>
</plugin>
...

最后我编辑了 2 个胡子模板,以便我的 @EvenLong 注释最终出现在输出代码中。

您要做的是将所需文件从 https://github.com/OpenAPITools/openapi-generator/tree/v4.3.1/modules/openapi-generator/src/main/resources/JavaSpring 复制到 ${project.basedir }/src/main/resources/openapi/templates (或您正在使用的任何目录),然后添加您的更改。

第一个 Mustache 模板是 beanValidationCore.mustache,它从 x-constraints 字段渲染内容本身。

我添加了 {{vendorExtensions.x-constraints }} 所以 beanValidationCore.mustache 看起来像这样

{{ vendorExtensions.x-constraints }}
{{#pattern}}@Pattern(regexp="{{{pattern}}}") {{/pattern}}{{!
minLength && maxLength set
}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}},max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
minLength set, maxLength not
}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{!
minLength not set, maxLength set
}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
@Size: minItems && maxItems set
}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}},max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems set, maxItems not
}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems not set && maxItems set
}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
@Email: useBeanValidation set && isEmail && java8 set
}}{{#useBeanValidation}}{{#isEmail}}{{#java8}}@javax.validation.constraints.Email{{/java8}}{{/isEmail}}{{/useBeanValidation}}{{!
@Email: performBeanValidation set && isEmail && not java8 set
}}{{#performBeanValidation}}{{#isEmail}}{{^java8}}@org.hibernate.validator.constraints.Email{{/java8}}{{/isEmail}}{{/performBeanValidation}}{{!
check for integer or long / all others=decimal type with @Decimal*
isInteger set
}}{{#isInteger}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isInteger}}{{!
isLong set
}}{{#isLong}}{{#minimum}}@Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L) {{/maximum}}{{/isLong}}{{!
Not Integer, not Long => we have a decimal value!
}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}}

第二个 Mustache 模板是 model.mustache,它为从 openapi 规范生成的 java 模型呈现 java 导入。因此,我添加了验证器 java 包(其中 @EvenLong 所在)中所有类的导入。 添加导入 com.foo.bar.validators.*;模型.胡子。我的看起来像这样:

package {{package}};

import java.util.Objects;
{{#imports}}import {{import}};
{{/imports}}
import org.openapitools.jackson.nullable.JsonNullable;
{{#serializableModel}}
import java.io.Serializable;
{{/serializableModel}}
{{#useBeanValidation}}
import javax.validation.Valid;
import com.foo.bar.validators.*;
import javax.validation.constraints.*;
{{/useBeanValidation}}
{{#performBeanValidation}}
import org.hibernate.validator.constraints.*;
{{/performBeanValidation}}
{{#jackson}}
{{#withXml}}
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
{{/withXml}}
{{/jackson}}
{{#withXml}}
import javax.xml.bind.annotation.*;
{{/withXml}}
{{^parent}}
{{#hateoas}}
import org.springframework.hateoas.RepresentationModel;
{{/hateoas}}
{{/parent}}

{{#models}}
{{#model}}
{{#isEnum}}
{{>enumOuterClass}}
{{/isEnum}}
{{^isEnum}}
{{>pojo}}
{{/isEnum}}
{{/model}}
{{/models}}

就是这样!

这是我的详细教程https://bartko-mat.medium.com/openapi-generator-to-spring-boot-with-custom-java-validations-623381df9215和代码示例https://github.com /Matusko/open-api-custom-validations


0
投票

幸运的是,从 OpenApiGenerator v6.x 开始,我们不再需要自定义胡子模板来执行此操作。我们现在可以在

myProjectSpec.yaml
文件中使用这两个标签:

x-class-extra-annotation
x-field-extra-annotation

这些都记录在此处

这是一个例子:

schemas:
  MenuItemDto:
    type: object
    x-class-extra-annotation: "@com.foo.constraints.MyCustomConstraint"
    properties:
      id:
        type: integer
        format: int32
      name:
        type: string
        x-field-extra-annotation: "@NotBlank"
      itemPrice:
        type: number
        description: Price.
    required:
      - name
      - itemPrice

当然,我仍然可以修改

model.mustache
文件以添加
MyCustomConstraint
注释的导入,但我宁愿不走这条路,尽管它应该可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.