Quarkus 是一个开源的全栈 Java 框架,专为构建云原生容器化应用程序而设计。由于Quarkus是为云应用程序构建的,因此它被设计为轻量级和快速,并支持快速启动时间。精心设计的容器化应用程序有助于实现可靠的 REST API,以创建和访问数据。
对于开发人员来说,数据验证始终是事后才想到的,但对于保持数据的一致性和有效性非常重要。REST API 需要验证它收到的数据,而 Quarkus 为验证 REST API 请求对象提供了丰富的内置支持。在某些情况下,我们需要对数据对象进行自定义验证。本文介绍了如何使用 Quarkus 框架创建自定义验证器。
REST API 示例
让我们考虑下面的一个简单的例子,其中我们有一个 House 数据对象和一个 REST API 来创建一个新的 House。
需要验证以下字段:
number:不应为空。
street:不应为空。
state:应仅为加利福尼亚州 (CA) 和内华达州 (NV)。
class House {
String number;
String street;
String city;
String state;
String type;
}
和 REST API:
@Path("/house")
public class HouseResource {
@POST
public String createHouse(House house) {
// Additional logic to process the house object
return "Valid house created";
}
}
配置 Quarkus 验证器
Quarkus 提供了 Hibernate 验证器来执行数据验证。这是一个 Quarkus 扩展,需要添加到项目中。
对于 Maven 项目,将依赖项添加到:pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
对于基于 Gradle 的项目,请使用以下内容:build.gradle
implementation("io.quarkus:quarkus-hibernate-validator")
内置验证器
常用的验证器可作为注释使用,这些注释可以很容易地添加到数据对象中。在我们的 House 数据对象中,我们需要确保 number 属性不应为空,并且街道不应为空。我们将使用注释和:@NotNull@NotBlank
class House {
@NotNull
int number;
@NotBlank(message = "House street cannot be blank")
String street;
String city;
String state;
String type;
}
要在 REST API 中验证数据对象,必须包含注释。这样,就不需要手动验证,任何验证错误都将导致向调用方返回 400 HTTP 响应:@Valid
@Path("/house")
public String createHouse(@Valid House house) {
return "Valid house received";
}
自定义验证
在几种情况下,默认验证是不够的,我们必须为我们的数据实施某种形式的自定义验证。在我们的示例中,众议院数据仅在加利福尼亚州 (CA) 和内华达州 (NV) 受支持。让我们为此创建一个验证器:
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD
})
@Constraint(validatedBy = StateValidator.class)
public @interface ValidState {
String message() default "State not supported";
Class<? extends Payload>[] payload() default {};
Class<?>[] groups() default {};
}
进入细节:
验证者的名称是 。在类验证中,这可以用作 。ValidState@ValidState
默认错误消息将添加到该方法中。message()
此批注由批注验证,并使用批注进行链接。StateValidator.class@Constraint
注释指示注释可能在 Java 程序中出现的位置。在上述情况下,它只能应用于 。@TargetFields
描述批注的保留策略。在上面的示例中,注释在运行时被保留。@Retention
类中的验证逻辑:StateValidator
public class StateValidator implements ConstraintValidator<ValidState, String> {
List<String> states = List.of("CA", "NV");
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && states.contains(value);
}
}
自定义验证器可以包含在 House 类中:@ValidState
class House {
@NotNull
int number;
@NotBlank(message = "House street cannot be blank")
String street;
String city;
@ValidState
String state;
String type;
测试
在软件开发中,单元测试是一个至关重要的组件,它提供了许多好处,例如提高代码质量和在开发周期的早期检测缺陷。Quarkus框架提供了各种工具来帮助开发人员进行单元测试。
对自定义验证器进行单元测试很简单,因为 Quarkus 允许我们注入验证器并对 House 对象执行手动验证:
@QuarkusTest
public class HouseResourceTest {
@Inject
Validator validator;
@Test
public void testValidState() {
House h = new House();
h.state = "CA";
h.number = 1;
h.street = "street1";
Set<ConstraintViolation<House>> violations = validator.validate(h);
System.out.println("Res " + violations);
assertEquals(violations.size(), 0);
}
@Test
public void testInvalidState() {
House h = new House();
h.state = "WA";
h.number = 1;
Set<ConstraintViolation<House>> violations = validator.validate(h);
assertEquals(violations.size(), 1);
assertEquals(violations.iterator().next().getMessage(), "State not supported");
}
}
结论
Quarkus 是一个健壮、编写良好的框架,它提供了各种内置验证并支持添加自定义验证。验证器提供了一种干净便捷的方式来执行 REST API 验证,这反过来又支持 DRY 方法。验证在微服务架构中发挥着越来越重要的作用,因为每个服务都定义并要求验证它所处理的数据。上述文章介绍了使用内置和自定义验证器的过程。