java.lang.IllegalArgumentException: Not enough variable values available to expand 'phone' at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:367) at org.springframework.web.util.HierarchicalUriComponents$QueryUriTemplateVariables.getValue(HierarchicalUriComponents.java:1055) at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:262) at org.springframework.web.util.HierarchicalUriComponents.lambda$expandQueryParams$5(HierarchicalUriComponents.java:443) at java.util.Map.forEach(Map.java:630) at org.springframework.web.util.HierarchicalUriComponents.expandQueryParams(HierarchicalUriComponents.java:439) at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:429) at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:51) at org.springframework.web.util.UriComponents.expand(UriComponents.java:172) at org.springframework.web.util.DefaultUriBuilderFactory$DefaultUriBuilder.build(DefaultUriBuilderFactory.java:376) at org.springframework.web.util.DefaultUriBuilderFactory.expand(DefaultUriBuilderFactory.java:202) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:414)

这是个占位符的问题。

RestTemplate在请求的 url 中存在{phone}这个值,默认到参数中找对应的值做替换。

解析 url 中存在的特殊值

正则表达式"\\{([^/]+?)\\}"命中了{phone},那么程序回去寻找参数中的phone进行替换。

    private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
    @Nullable
    static String expandUriComponent(@Nullable String source, UriTemplateVariables uriVariables,
            @Nullable UnaryOperator<String> encoder) {
        if (source == null) {
            return null;
        if (source.indexOf('{') == -1) {
            return source;
        if (source.indexOf(':') != -1) {
            source = sanitizeSource(source);
        Matcher matcher = NAMES_PATTERN.matcher(source);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String match = matcher.group(1);
            String varName = getVariableName(match);
            Object varValue = uriVariables.getValue(varName);
            if (UriTemplateVariables.SKIP_VALUE.equals(varValue)) {
                continue;
            String formatted = getVariableValueAsString(varValue);
            formatted = encoder != null ? encoder.apply(formatted) : Matcher.quoteReplacement(formatted);
            matcher.appendReplacement(sb, formatted);
        matcher.appendTail(sb);
        return sb.toString();

从 uriVariables 中寻值

如果找不到 phone,则会提示异常IllegalArgumentException

* URI template variables backed by a variable argument array. private static class VarArgsTemplateVariables implements UriTemplateVariables { private final Iterator<Object> valueIterator; public VarArgsTemplateVariables(Object... uriVariableValues) { this.valueIterator = Arrays.asList(uriVariableValues).iterator(); @Override @Nullable public Object getValue(@Nullable String name) { if (!this.valueIterator.hasNext()) { throw new IllegalArgumentException("Not enough variable values available to expand '" + name + "'"); return this.valueIterator.next();

我们这边抛出异常,是因为有部分历史数据中用户的手机号中设置成138${phone}这种值,在写入的时候没有做合法性校验。

URL把花括号{}中的内容当成了占位符,而又没有传入占位符对应的值,才导致报错。