简体   繁体   English

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

[英]How to inject custom spring validation inside swagger codegen?

We are able to use openApi documentation and generate our Java Input classes using the spring swagger-codegen.我们能够使用 openApi 文档并使用 spring swagger-codegen 生成我们的 Java Input 类。 Also, we can inject the javax.validation annotations when input is generated for common constraints like length, mandatory etc.此外,我们可以在为长度、强制等常见约束生成输入时注入 javax.validation 注释。

I would like to take this to the next customization level and be able to annotate the generated Input classes with custom validation annotations that are hooked up with @Constraint annotation from Spring.我想将其提升到下一个自定义级别,并能够使用与 Spring 中的 @Constraint 注释相关联的自定义验证注释来注释生成的 Input 类。 This way we can reuse specific validation for our project.这样我们就可以为我们的项目重用特定的验证。

I'm hoping there is an out of the box solution for this.我希望有一个开箱即用的解决方案。 What is your preferred way of generating Input classes with custom validation annotations?您使用自定义验证注释生成输入类的首选方法是什么?

I did not find "out of the box solution".我没有找到“开箱即用的解决方案”。 But openapi-generator provides a simple way of modifying generated code by editing mustache templates.但是 openapi-generator 提供了一种通过编辑 mustache 模板来修改生成代码的简单方法。 That is how I solved exactly same problem as you have.这就是我解决与您完全相同的问题的方法。

Basically I created custom field in OpenAPI specs where I specified custom constraint annotation (@EvenLong in my case).基本上我在 OpenAPI 规范中创建了自定义字段,我在其中指定了自定义约束注释(在我的例子中为 @EvenLong)。 I called this field "x-constraints":我称这个字段为“x 约束”:

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

Then I told openapi-generator where to look for my custom/modified mustache templates.然后我告诉 openapi-generator 在哪里寻找我的自定义/修改过的胡子模板。 I used openapi-generator as maven plugin so I added templateDirectory property to plugin definition in pom.xml:我使用 openapi-generator 作为 maven 插件,所以我在 pom.xml 中的插件定义中添加了 templateDirectory 属性:

...
<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>
...

and finally I edited 2 mustache templates so that my @EvenLong annotation ends up in output code.最后我编辑了 2 个小胡子模板,以便我的 @EvenLong 注释最终出现在输出代码中。

What you do is copy needed files from https://github.com/OpenAPITools/openapi-generator/tree/v4.3.1/modules/openapi-generator/src/main/resources/JavaSpring to ${project.basedir}/src/main/resources/openapi/templates (or whatever directory you are using) and then add your changes to it.您要做的是将所需文件从https://github.com/OpenAPITools/openapi-generator/tree/v4.3.1/modules/openapi-generator/src/main/resources/JavaSpring复制到 ${project.basedir}/src /main/resources/openapi/templates(或您使用的任何目录),然后将您的更改添加到其中。

First mustache template is beanValidationCore.mustache which renders content itself from x-constraints field.第一个 mustache 模板是beanValidationCore.mustache ,它从 x-constraints 字段呈现内容本身。

I added {{ vendorExtensions.x-constraints }} so beanValidationCore.mustache looks like this我添加了 {{ 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}}

Second mustache template is model.mustache which renders java imports for java models generated from openapi specs.第二个 mustache 模板是model.mustache ,它为从 openapi 规范生成的 java 模型呈现 java 导入。 So I added import of all classes from my validators java package (where @EvenLong is) .所以我从我的验证器 java 包(@EvenLong 所在的位置)中添加了所有类的导入。 Add import com.foo.bar.validators.*;添加 import com.foo.bar.validators.*; to model.mustache.模型.小胡子。 Mine looks like this:我的看起来像这样:

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}}

That's it!就是这样!

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

在 github 上查看我的 Baeldung 文章,其中包含详细说明和正在运行的代码库: https ://www.baeldung.com/java-swagger-custom-validation

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM