Как внедрить пользовательскую проверку весны внутри кода swagger?

Мы можем использовать документацию openApi и генерировать наши классы ввода Java с помощью spring swagger-codegen. Кроме того, мы можем вводить аннотации javax.validation, когда ввод генерируется для общих ограничений, таких как длина, обязательность и т. д.

Я хотел бы перейти на следующий уровень настройки и иметь возможность аннотировать сгенерированные классы ввода пользовательскими аннотациями проверки, которые связаны с аннотацией @Constraint из Spring. Таким образом, мы можем повторно использовать конкретную проверку для нашего проекта.

Я надеюсь, что для этого есть готовое решение. Каков ваш предпочтительный способ создания классов ввода с пользовательскими аннотациями проверки?


person sa_vedem    schedule 30.08.2019    source источник
comment
Вы нашли какой-нибудь красивый способ для этого?   -  person Namelles.One    schedule 28.11.2019


Ответы (1)


Я не нашел готового решения. Но openapi-generator предоставляет простой способ изменения сгенерированного кода путем редактирования шаблонов усов. Вот как я решил точно такую ​​​​же проблему, как у вас.

По сути, я создал настраиваемое поле в спецификациях OpenAPI, где в моем случае я указал пользовательскую аннотацию ограничения (@EvenLong). Я назвал это поле x-ограничениями:

...
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 в качестве плагина 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 (или любой другой каталог, который вы используете), а затем добавьте в него свои изменения.

Первый шаблон усов — это 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}}

Второй шаблон усов — model.mustache, который отображает импорт java для моделей java, сгенерированных из спецификаций openapi. Поэтому я добавил импорт всех классов из моего 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

person Matúš Bartko    schedule 05.01.2021
comment
Спасатель жизни! Я протестировал его с помощью kotlin-spring, и файлы немного изменились. Вам не нужно переопределять все файлы из этого каталога. Даже при использовании Maven нет необходимости переопределять все. Спасибо! Вы должны создать учебник об этом. - person Selast Lambou; 15.02.2021