如何通过注解实现条件校验 支持单API接口适配多类型配置请求
实现方案
完全可以通过框架原生注解实现需求,无需手动编写校验逻辑,推荐使用以下最优方案:
方案1:Jackson多态反序列化 + 原生参数校验(推荐)
通过Jackson的多态注解自动根据configType将请求体反序列化为对应子类实例,配合@Valid即可自动触发子类的字段校验,全程类型安全,扩展性极强。
步骤1:定义抽象父类配置
import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import jakarta.validation.constraints.NotNull; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "configType", visible = true ) @JsonSubTypes({ @JsonSubTypes.Type(value = FileConfig.class, name = "FILE"), @JsonSubTypes.Type(value = LdapConfig.class, name = "LDAP") }) public abstract class BaseConfig { @NotNull private String configType; // getter、setter省略 }
步骤2:定义不同类型的子类配置,各自绑定校验规则
// 文件配置子类 import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; public class FileConfig extends BaseConfig { @Valid @NotNull private FileSettings settings; public static class FileSettings { @NotBlank private String type; @NotBlank private String location; // getter、setter省略 } // getter、setter省略 }
// LDAP配置子类 import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; public class LdapConfig extends BaseConfig { @Valid @NotNull private LdapSettings settings; public static class LdapSettings { @NotBlank private String ou; @NotBlank private String attribute; // getter、setter省略 } // getter、setter省略 }
步骤3:合并后的接口写法
@POST @Path("/configurations") @Consumes(MediaType.APPLICATION_JSON) public Response createConfig(@Valid BaseConfig config) { // 此处config已经是反序列化完成的子类实例,直接判断类型处理逻辑即可 if (config instanceof FileConfig fileConfig) { // 处理文件配置逻辑 } else if (config instanceof LdapConfig ldapConfig) { // 处理LDAP配置逻辑 } // 后续新增配置类型仅需新增子类+配置@JsonSubTypes即可 }
方案2:单类条件校验(不推荐)
如果不想拆分多类,可以使用Hibernate Validator提供的@ScriptAssert注解实现单类内的条件校验,缺点是无类型安全,校验规则可维护性差:
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.ScriptAssert; import java.util.Map; @ScriptAssert( lang = "javascript", script = "_this.configType == 'FILE' ? (_this.settings.type != null && _this.settings.location != null) : (_this.settings.ou != null && _this.settings.attribute != null)", message = "配置参数与configType不匹配" ) public class UnifiedConfig { @NotBlank private String configType; @NotNull private Map<String, Object> settings; // getter、setter省略 }
内容的提问来源于stack exchange,提问作者Danilo Körber
相关产品推荐
相关产品推荐

