文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Springboot @Value注入boolean如何设置默认值

2023-06-29 13:57

关注

本文小编为大家详细介绍“Springboot @Value注入boolean如何设置默认值”,内容详细,步骤清晰,细节处理妥当,希望这篇“Springboot @Value注入boolean如何设置默认值”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

@Value注入boolean设置默认值

问题描述

Springboot 中读取配置文件

test:

业务代码如下

@Value("${test:true}")private boolean test;

报错如下

nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'boolean'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value []

问题分析

根据报错可知,主要问题在于 注入时 test 的值是 String 类型,无法转换成 boolean 类型。

@Value("${test:true}")private String test;

于是更改了接收类型,看看获取到的值是否是 true,结果发现 test 值为 “”,而不是设置的默认值

解决方案

报错问题在于只要配置文件中有 test: 所以系统就默认 test 为 “” 而不是按照我所设想的为空所以默认值为 true。

直接删除配置文件中的 test: 即可正常启动。

@Value 源码阅读

在排查问题的过程中也粗略的跟读了一下源码

//org.springframework.beans.TypeConverterSupport#doConvert()private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field) throws TypeMismatchException {     try {         return field != null ? this.typeConverterDelegate.convertIfNecessary(value, requiredType, field) : this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);     } catch (ConverterNotFoundException var6) {         throw new ConversionNotSupportedException(value, requiredType, var6);     } catch (ConversionException var7) {         throw new TypeMismatchException(value, requiredType, var7);     } catch (IllegalStateException var8) {         throw new ConversionNotSupportedException(value, requiredType, var8);     } catch (IllegalArgumentException var9) {     // 最终异常从这里抛出         throw new TypeMismatchException(value, requiredType, var9);     } }

最终赋值在

//org.springframework.beans.TypeConverterDelegate#doConvertTextValue()private Object doConvertTextValue(Object oldValue, String newTextValue, PropertyEditor editor) {    try {        editor.setValue(oldValue);    } catch (Exception var5) {        if (logger.isDebugEnabled()) {            logger.debug("PropertyEditor [" + editor.getClass().getName() + "] does not support setValue call", var5);        }    }    // 此处发现 newTextValue 为 ""    editor.setAsText(newTextValue);    return editor.getValue();}

接下来就是如何将 字符串 true 转换为 boolean 的具体代码:

// org.springframework.beans.propertyeditors.CustomBooleanEditor#setAsText()    public void setAsText(String text) throws IllegalArgumentException {        String input = text != null ? text.trim() : null;        if (this.allowEmpty && !StringUtils.hasLength(input)) {            this.setValue((Object)null);        } else if (this.trueString != null && this.trueString.equalsIgnoreCase(input)) {            this.setValue(Boolean.TRUE);        } else if (this.falseString != null && this.falseString.equalsIgnoreCase(input)) {            this.setValue(Boolean.FALSE);        } else if (this.trueString != null || !"true".equalsIgnoreCase(input) && !"on".equalsIgnoreCase(input) && !"yes".equalsIgnoreCase(input) && !"1".equals(input)) {            if (this.falseString != null || !"false".equalsIgnoreCase(input) && !"off".equalsIgnoreCase(input) && !"no".equalsIgnoreCase(input) && !"0".equals(input)) {                throw new IllegalArgumentException("Invalid boolean value [" + text + "]");            }            this.setValue(Boolean.FALSE);        } else {            this.setValue(Boolean.TRUE);        }    }

tips:windows 中使用 IDEA 去查找类可以使用 ctrl + shift +alt +N的快捷键组合去查询,mac 系统则是 commond + O

Spring解析@Value

初始化PropertyPlaceholderHelper对象

    protected String placeholderPrefix = "${";     protected String placeholderSuffix = "}";    @Nullable    protected String valueSeparator = ":"; private static final Map<String, String> wellKnownSimplePrefixes = new HashMap<>(4);     static {        wellKnownSimplePrefixes.put("}", "{");        wellKnownSimplePrefixes.put("]", "[");        wellKnownSimplePrefixes.put(")", "(");    } public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix,            @Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {         Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");        Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");        //默认值${        this.placeholderPrefix = placeholderPrefix;        //默认值}        this.placeholderSuffix = placeholderSuffix;        String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);        //当前缀为空或跟定义的不匹配,取传入的前缀        if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {            this.simplePrefix = simplePrefixForSuffix;        }        else {            this.simplePrefix = this.placeholderPrefix;        }        //默认值:        this.valueSeparator = valueSeparator;        this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;    }

解析@Value 

protected String parseStringValue(            String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {         StringBuilder result = new StringBuilder(value);        //是否包含前缀,返回第一个前缀的开始index        int startIndex = value.indexOf(this.placeholderPrefix);        while (startIndex != -1) {            //找到最后一个后缀的index            int endIndex = findPlaceholderEndIndex(result, startIndex);            if (endIndex != -1) {                //去掉前缀后缀,取出里面的字符串                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);                String originalPlaceholder = placeholder;                if (!visitedPlaceholders.add(originalPlaceholder)) {                    throw new IllegalArgumentException(                            "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");                }                // 递归判断是否存在占位符,可以这样写${acm.endpoint:${address.server.domain:}}                placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);                // 根据key获取对应的值                String propVal = placeholderResolver.resolvePlaceholder(placeholder);                // 值不存在,但存在默认值的分隔符                if (propVal == null && this.valueSeparator != null) {                    // 获取默认值的索引                    int separatorIndex = placeholder.indexOf(this.valueSeparator);                    if (separatorIndex != -1) {                        // 切掉默认值的字符串                        String actualPlaceholder = placeholder.substring(0, separatorIndex);                        // 切出默认值                        String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());                        // 根据新的key获取对应的值                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);                        // 如果值不存在,则把默认值赋值给当前值                        if (propVal == null) {                            propVal = defaultValue;                        }                    }                }                // 如果当前值不为NULL                if (propVal != null) {                    // 递归获取存在占位符的值信息                    propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);                    // 替换占位符                    result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);                    if (logger.isTraceEnabled()) {                        logger.trace("Resolved placeholder '" + placeholder + "'");                    }                    startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());                }                else if (this.ignoreUnresolvablePlaceholders) {                    // Proceed with unprocessed value.                    startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());                }                else {                    throw new IllegalArgumentException("Could not resolve placeholder '" +                            placeholder + "'" + " in value \"" + value + "\"");                }                visitedPlaceholders.remove(originalPlaceholder);            }            else {                startIndex = -1;            }        }         return result.toString();    }

读到这里,这篇“Springboot @Value注入boolean如何设置默认值”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯