当前位置: 首页 > 知识库问答 >
问题:

如何基于注释属性创建自定义验证消息?

赵辉
2023-03-14

我正在使用Hibernate@NotNull验证器,我正在尝试创建自定义消息来告诉用户哪个字段在空时产生了错误。类似这样的东西:

notNull.custom = The field {0} can't be null.

(这将在我的ValidationMessages.properties文件中)。

其中,{0}应该是通过以下方式传递给验证程序的字段名:

@NotNull(field="field name")

我有办法做到吗?

共有2个答案

朱祺
2023-03-14

如果您的需求可以通过插入Hibernate消息来满足,那么您可以像这样创建/命名您的*属性文件:

ValidationMessages.properties

在这里面:

javax.validation.constraints.NotNull.message = CUSTOMIZED MESSAGE WHEN NOTNULL is violated!

默认情况下,Hibernate搜索名为ValidationMessagesResourceBundle。还可能涉及区域设置:ValidationMessages\u enValidationMessages\u de

Hibernate将通过interpolatedMessage参数提供您自定义的消息,因此将显示所有ConstraintViolationExc0019相关信息(包括您的消息)。因此您的消息将是真正异常的一部分。将提供一些笨重的信息!

如果您想创建自定义异常(无默认ConstraintViolationException行为),请查看以下内容:

使用<代码> GANGIKAOD概念,考虑以下内容

  public void saveOrUpdate(IEntity<?> entity) {
      try {
          if(entity.getId == null) {
            em.persist(entity);
          } else {
            em.merge(entity)l
          }
      } catch(ConstraintViolationException cve) {
          throw new ConstraintViolationEx(constructViolationMessage(cve.getConstraintViolations()));
      }
  }

 private String constructMessage(Set<ConstraintViolation<?>> pConstraintViolations) {
    StringBuilder customMessages = new StringBuilder();
    for(ConstraintViolation<?> violation : pConstraintViolations) {
        String targetAnnotation = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
        if(supportsCustomMessage(targetAnnotation)) {
            applyMessage(violation, targetAnnotation, customMessages);
        } else {
            // do something with not customized constraints' messages e.g. append it to existing container
        }
    }
    return customMessages.toString();
 }

 private void applyMessage(ConstraintViolation<?> pViolation, String pTargetAnnotation, StringBuilder pCustomMessages) {
     String targetClass = pViolation.getRootBean().getClass().getName();
     String targetField = pViolation.getPropertyPath().toString();
     pCustomMessages.append(MessageFormat.format(getMessageByAnnotation(pTargetAnnotation), targetClass, targetField));
     pCustomMessages.append(System.getProperty("line.separator"));
 }


 private String getBundleKey() {
     return "ValidationMessages"; //FIXME: hardcoded - implement your true key
 }

 private String getMessageByAnnotation(String pTargetAnnotation) {
     ResourceBundle messages = ResourceBundle.getBundle(getBundleKey());
     switch(pTargetAnnotation) {
     case "NotNull":
         return messages.getString(pTargetAnnotation + ".message");
     default:
         return "";
     }
 }

 private boolean supportsCustomMessage(String pTargetAnnotation) {
     return customizedConstraintsTypes.contains(pTargetAnnotation);
 }

产生的结果:

test.model.exceptions.ConstraintViolationEx
    test.model.Person : name cannot be null
    test.model.Person : surname cannot be null

一个hibernateConstraintViolation提供了关于根类受限字段的相关信息。如您所见,它适用于所有hibernate支持的约束,因此您需要检查当前注释是否可以由支持自定义CustomMessage(

您需要做的就是实现不受支持的约束逻辑。例如,它可以附加它的原因消息或插入默认消息(真正的异常会进入*日志文件)

宇文曦
2023-03-14

要自定义注释消息,需要在isValid()方法中禁用现有的违规消息,并生成新的违规消息并添加它。

constraintContext.disableDefaultConstraintViolation();
constraintContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();

在下面给出的示例中,我根据“无效日期”、“不能大于今天日期”和“日期格式是否正确”创建了一个用于输入日期验证的注释。

@CheckDateIsValid(displayPattern = "DD/MM/YYYY", programPattern = "dd/MM/yyyy", groups = Order2.class)
    private String fromDate;

注释界面-

public @interface CheckDateIsValid {

    String message() default "default message";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String displayPattern();

    String programPattern();
}

注释实现类-

    public class CheckDateIsValidValidator implements ConstraintValidator<CheckDateIsValid, String> {
    @Value("${app.country.timeZone}")
    private String timeZone;
    private String displayPattern;
    private String programPattern;

    @Override
    public void initialize(CheckDateIsValid constraintAnnotation) {
        this.displayPattern = constraintAnnotation.displayPattern();
        this.programPattern = constraintAnnotation.programPattern();
    }

    @Override
    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
        try {
            // disable existing violation message
            constraintContext.disableDefaultConstraintViolation();

            if (object == null) {
                return true;
            }

            final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(programPattern);
            LocalDateTime time = LocalDate.parse(object, formatter).atStartOfDay();

            ZoneOffset zoneOffSet = ZoneOffset.of(timeZone);
            OffsetDateTime todayDateTime = OffsetDateTime.now(zoneOffSet);

            if (time == null) {
                customMessageForValidation(constraintContext, "date is not valid");
                return false;
            } else if (todayDateTime.isBefore(time.atOffset(zoneOffSet))) {
                customMessageForValidation(constraintContext, "can't be greater than today date");
                return false;
            }

            return time != null;
        } catch (Exception e) {
            customMessageForValidation(constraintContext, "date format should be like " + displayPattern);
            return false;
        }
    }

    private void customMessageForValidation(ConstraintValidatorContext constraintContext, String message) {
        // build new violation message and add it
        constraintContext.buildConstraintViolationWithTemplate(message).addConstraintViolation();
    }
}
 类似资料:
  • 我有一个自定义注释,如下所示 我定义了一个方面来包装实际的方法调用 注释的用法如下所示 到目前为止,这工作得很好,我可以在TestableAspect#InvkeAndLog中实现我的登录。 现在我需要验证eg的索引值不大于10。 我可以在运行时通过更改方面实现来实现,如下所示 但这需要至少调用一次API,而且效率不高。是否有一种方法可以在spring启动应用程序启动时执行此操作?

  • 问题内容: 注释如何与Java一起使用?以及如何创建这样的自定义注释: 基本上,我需要保留的POJO在持久化时像这样进行序列化: 这样,实际的生成/持久对象是这样的: 任何想法如何实现这一点? 问题答案: 如果创建自定义注释,则必须使用此处的 API 示例进行处理。您可以参考如何声明注释。 这是Java中的示例注释声明的样子。 并被称为。 表示您想在运行时保留注释,并且可以在运行时访问它。 表示您

  • 我创建了一个自定义验证属性,我想将其用于 API 控制器 DTO。此属性需要来自已配置选项的值,这就是我在构造函数中注入这些值的原因,以便我以后可以在 和 方法中使用选项服务。 不幸的是,当我想在DTO中将其用作属性时 我收到错误信息 没有给出对应于'MyValidationAttribute.MyValidationAttribute(IOptionsMonitor)'所需形式参数'myOpti

  • 我想用java为创建自定义注释。我想用这个注释比较两个字符串值,比较后会返回一个

  • 我正在开发spring mvc应用程序,我应该在spring mvc validator的基础上应用验证。第一步,我为类和设置控制器添加了注释,效果很好。现在我需要实现自定义验证器来执行复杂的逻辑,但我想使用现有的注释并添加额外的检查。 我的用户类: 我的验证器: 我的控制器: 那么,有可能同时使用自定义验证器和注释吗?如果是,怎么做?

  • 我在代码中使用Lombok自动生成getter和setter代码。我想添加其他个人注释并使用它。 例如,我想添加一个方法来验证列表中是否存在一个键: 创建注释后,我将执行以下操作: