1. Overview
1.概述
When we want to generate validations with Swagger, we generally use the basic specifications. However, we might need to add Spring custom validation annotations.
当我们要使用 Swagger 生成验证时,我们通常使用基本规范。但是,我们可能需要添加Spring 自定义验证注释。
This tutorial will teach how to generate models and REST APIs using these validations while focusing on the OpenAPI server generator and not the constraint validators.
本教程将教授如何使用这些验证生成模型和REST API,同时关注OpenAPI服务器生成器而不是约束验证器。
2. Setup
2.设置
For the setup, we’ll use a previous Baeldung tutorial to generate a server from an OpenAPI 3.0.0 definition. Next, we’re going to add some custom validation annotations alongside all needed dependencies.
对于设置,我们将使用以前的Baeldung教程来从OpenAPI 3.0.0定义生成一个服务器。接下来,我们将添加一些自定义验证注解,以及所有需要的依赖。
3. PetStore API OpenAPI Definition
3.PetStore API开放API的定义
Let’s suppose we have the PetStore API OpenAPI definition, and we need to add custom validations for both the REST API and the described model, Pet.
假设我们有PetStore API的OpenAPI定义,我们需要为REST API和描述的模型Pet添加自定义验证。
3.1. Custom Validations for the API Model
3.1.API模型的自定义验证
To create pets, we need to make Swagger use our custom validation annotation to test if the pet’s name is capitalized. As a result, for the sake of this tutorial, we’ll just call it Capitalized.
为了创建宠物,我们需要让Swagger使用我们的自定义验证注解来测试宠物的名字是否大写。因此,在本教程中,我们就叫它Capitalized。
Thus, observe the x-constraints specification in the below example. It’ll be enough to let Swagger know we need to generate another type of annotation than the already known ones:
因此,观察下面的例子中的x-constraints规范。这足以让Swagger知道我们需要生成另一种类型的注释,而不是已经知道的那些。
openapi: 3.0.1
info:
version: "1.0"
title: PetStore
paths:
/pets:
post:
#.. post described here
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
x-constraints: "Capitalized(required = true)"
tag:
type: string
3.2. Custom Validations for the REST API Endpoint
3.2.REST API端点的自定义验证
As above, we’ll describe an endpoint to find all pets by name in the same manner. To demonstrate our purpose, let’s suppose our system is case sensitive so that we’ll add the same x-constraints validation again for the name input parameter:
如上所述,我们将描述一个端点,以同样的方式按名称查找所有宠物。为了证明我们的目的,让我们假设我们的系统是区分大小写的,这样我们将再次为name 输入参数添加同样的x-constraints validation。
/pets:
# post defined here
get:
tags:
- pet
summary: Finds Pets by name
description: 'Find pets by name'
operationId: findPetsByTags
parameters:
- <em>name: name</em>
in: query
schema:
type: string
description: Tags to filter by
required: true
x-constraints: "Capitalized(required = true)"
responses:
'200':
description: default response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
4. Creating the Capitalized Annotation
4.创建大写的注解
To enforce a custom validation, we need to create an annotation assuring the functionality.
为了执行自定义验证,我们需要创建一个注解来保证该功能。
First, we make the annotation interface – @Capitalized:
首先,我们制作注释接口–@Capitalized。
@Documented
@Constraint(validatedBy = {Capitalized.class})
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Capitalized{
String message() default "Name should be capitalized.";
boolean required() default true;
// default annotation methods
}
Note that we made the required method for demo purposes – we’ll explain that later.
请注意,我们做了required method是为了演示的目的–我们将在后面解释。
Next, we add the CapitalizedValidator, referred to in the above @Constraint annotation:
接下来,我们添加CapitalizedValidator,在上面的@Constraint注释中提到。
public class CapitalizedValidator implements ConstraintValidator<Capitalized, String> {
@Override
public boolean isValid(String nameField, ConstraintValidatorContext context) {
// validation code here
}
}
5. Generating the Validation Annotations
5.生成验证注释
5.1. Specifying the Mustache Templates Directory
5.1.指定Mustache模板目录
To generate models with the @Capitalized validation annotation, we need specific mustache templates telling Swagger to generate it within the model.
为了生成带有@Capitalized验证注解的模型,我们需要特定的mustache模板来告诉Swagger在模型中生成它。
Thus, in the OpenAPI generator plugin, inside the <configuration>[..]</configuration tags, we need to add a template directory:
因此,在OpenAPI生成器插件中,在<configuration>[…]</configurationtags里面,我们需要添加一个模板目录。
<plugin>
//...
<executions>
<execution>
<configuration
//...
<templateDirectory>
${project.basedir}/src/main/resources/openapi/templates
</templateDirectory>
//...
</configuration>
</execution>
</executions>
//...
</plugin>
5.2. Adding the Mustache Bean Validations Configurations
5.2.添加Mustache Bean的验证配置
In this chapter, we’ll configure Mustache templates to generate the validation specification. To add more details, we will modify the beanValidationCore.mustache, the model.mustache, and the api.muctache files to generate code successfully.
在本章中,我们将配置Mustache模板来生成验证规范。为了增加更多的细节,我们将修改beanValidationCore.mustache,model.mustache和api.muctache文件以成功生成代码。
Firstly, the beanValidationCore.mustache from the swagger-codegen module needs to be modified by adding a vendor extension specification:
首先,需要对beanValidationCore.mustache模块中的swagger-codegen进行修改,添加一个供应商扩展规范。
{{{ vendorExtensions.x-constraints }}}
Secondly, if we have an annotation with an inner property like @Capitalized(required = “true”), then a particular pattern on the second line of the beanValidationCore.mustache file needs to be specified:
其次,如果我们有一个内部属性的注解,如@Capitalized(required = “true”),那么需要指定beanValidationCore.mustache文件第二行的一个特定模式。
{{#required}}@Capitalized(required="{{{pattern}}}") {{/required}}
Thirdly, we need to change the model.mustache specification to contain the necessary imports. For example, we’ll import the @Capitalized annotation and the Capitalized. The imports should be inserted after the package tag of the model.mustache:
第三,我们需要改变model.mustache规范以包含必要的导入。例如,我们将导入 @Capitalized 注解和Capitalized。这些导入应该插入到 model.mustache:的 package 标签之后。
{{#imports}}import {{import}}; {{/imports}} import
com.baeldung.openapi.petstore.validator.CapitalizedValidator;
import com.baeldung.openapi.petstore.validator.Capitalized;
Lastly, to have the annotation generation inside the APIs, we need to add the imports for the @Capitalized annotations in the api.mustache file.
最后,为了让注解在API中生成,我们需要在@Capitalized 注解的api.mustache文件中添加导入。
{{#imports}}import {{import}}; {{/imports}} import
com.baeldung.openapi.petstore.validator.Capitalized;
Additionally, api.mustache depends on the cookieParams.mustache file. Thus, we need to add it in the openapi/templates directory.
此外,api.mustache依赖于cookieParams.mustache文件。因此,我们需要将其添加到openapi/templates目录中。
6. Generate Sources
6.生成来源
To finish, we can use the generated code. We need to run, at a minimum, mvn generate-sources. This will generate the model:
为了完成,我们可以使用生成的代码。我们至少需要运行mvn generate-sources。这将生成模型。
public class Pet {
@JsonProperty("id")
private Long id = null;
@JsonProperty("name")
private String name = null;
// other parameters
@Schema(required = true, description = "")
@<code class="language-java">Capitalized
public String getName() { return name; } // default getters and setter }
And it’ll also generate an API:
而且它还会生成一个API。
default ResponseEntity<List<Pet>> findPetsByTags(
@Capitalized(required = true)
@ApiParam(value = "Tags to filter by")
@Valid @RequestParam(value = "name", required = false) String name) {
// default generated code here
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
7. Testing Using curl
7.使用curl进行测试
After starting up the application, we’ll run some curl commands to test it.
启动应用程序后,我们将运行一些curl命令来测试它。
Additionally, note that constraint violations do throw a ConstraintViolationException. The exception needs to be appropriately handled via @ControllerAdvice to return a 400 Bad Request status.
此外,请注意,违反约束确实会抛出一个ConstraintViolationException。这个异常需要通过@ControllerAdvice进行适当处理,以返回400 Bad Request状态。
7.1. Testing the Pet Model Validation
7.1.测试Pet模型验证
This Pet model has a lowercase name. Thus, a 400 Bad Request should be returned by the app:
这个Pet模型有一个小写的name。因此,应用程序应该返回一个400错误请求。
curl -X 'POST' \
'http://localhost:8080/pet' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 1,
"name": "rockie"
}'
7.2. Testing the Find Pet API
7.2.测试查找Pet的API
In the same manner as above, because the name is lowercase, the application should also return a 400 Bad Request:
与上面的方式相同,由于name 是小写的,应用程序也应该返回一个400坏请求。
curl -I http://localhost:8080/pets/name="rockie"
8. Conclusion
8.结语
In this tutorial, we’ve seen how to enable custom constraint validators to be generated with Spring while implementing a REST API server.
在本教程中,我们看到了如何在实现REST API服务器时,用Spring生成自定义约束条件验证器。
As always, the code can be found over on GitHub.
一如既往,代码可以在GitHub上找到over。