You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Micronaut自定义校验约束:如何为不同违规场景设置自定义消息

Solution: Custom Scenario-Specific Validation Messages in Micronaut

Absolutely! You can define unique, scenario-specific error messages for your CheckDecimal constraint in Micronaut. The ConstraintValidatorContext does have the tools you need—you just need to use its message-building methods to override the default annotation message for each violation case. Here's how to implement it:

Key API Methods to Use

You’ll rely on three critical methods from ConstraintValidatorContext to customize messages:

  • buildConstraintViolationWithTemplate(String message): Creates a custom violation message template (supports variable substitution with ${}).
  • disableDefaultConstraintViolation(): Turns off the default message defined in your @CheckDecimal annotation, so only your custom message is shown.
  • addConstraintViolation(): Finalizes and adds the custom violation to the validation context.

Modified Validator Implementation

Here’s your updated checkDecimalValidator() with tailored messages for each violation scenario:

@Factory
class ValidatorFactory {
    @Singleton
    ConstraintValidator<CheckDecimal, Double> checkDecimalValidator() {
        return { Double value, AnnotationValue<CheckDecimal> annotation, ConstraintValidatorContext context ->
            final parameters = annotation.convertibleValues.asMap()
            final keySet = parameters.keySet()
            if(value == null) {
                return true
            }
            // Validate minimum value
            if(keySet.contains('minimum')) {
                double minimumValidator = parameters.get('minimum')
                if(value < minimumValidator) {
                    context.buildConstraintViolationWithTemplate("数值不能小于 ${minimumValidator}")
                           .addConstraintViolation()
                    context.disableDefaultConstraintViolation()
                    return false
                }
            }
            // Validate maximum value
            if(keySet.contains('maximum')) {
                double maximumValidator = parameters.get('maximum')
                if(value > maximumValidator) {
                    context.buildConstraintViolationWithTemplate("数值不能大于 ${maximumValidator}")
                           .addConstraintViolation()
                    context.disableDefaultConstraintViolation()
                    return false
                }
            }
            // Validate integer part length
            if(keySet.contains('integerLength')) {
                final integerLengthValidator = parameters.get('integerLength')
                final integerLength = value.toString().split(/\./)[0].length()
                if(integerLength > integerLengthValidator) {
                    context.buildConstraintViolationWithTemplate("整数部分长度不能超过 ${integerLengthValidator} 位")
                           .addConstraintViolation()
                    context.disableDefaultConstraintViolation()
                    return false
                }
            }
            // Validate decimal part length
            if(keySet.contains('decimalLength')) {
                final decimalLengthValidator = parameters.get('decimalLength')
                final decimalLength = value.toString().split(/\./)[1].length()
                if(decimalLength > decimalLengthValidator) {
                    context.buildConstraintViolationWithTemplate("小数部分长度不能超过 ${decimalLengthValidator} 位")
                           .addConstraintViolation()
                    context.disableDefaultConstraintViolation()
                    return false
                }
            }
            return true
        } as ConstraintValidator<CheckDecimal, Double>
    }
}

How It Works

  1. For each violation condition (e.g., value below the minimum), we first construct a custom message using the parameter value from your @CheckDecimal annotation (like ${minimumValidator}).
  2. We add this custom violation to the validation context with addConstraintViolation().
  3. We call disableDefaultConstraintViolation() to ensure the default message from your annotation isn’t displayed alongside the custom one.
  4. Return false to mark the field as invalid.

Optional: Internationalization (i18n)

If you need multi-language support, replace hardcoded messages with keys that map to properties files. For example:

// Use a message key instead of hardcoded text
context.buildConstraintViolationWithTemplate("{checkdecimal.minimum.violation}")
       .addConstraintViolation()

Then define the key in your messages.properties file:

checkdecimal.minimum.violation=数值不能小于 {0}

Micronaut will automatically resolve the key and substitute parameter values (you can pass additional parameters via addParameter() if needed).

内容的提问来源于stack exchange,提问作者Nolyurn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 23:54:05