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

FeignException错误信息中撇号被转义为\u0027问题排查

Feign对接SonarQube时异常信息单引号被转义为\u0027问题解决

问题场景

使用Feign客户端对接SonarQube接口拉取数据,在测试传入错误组件名的异常场景时,发现异常信息中的撇号(单引号)被自动转义为Unicode编码\u0027。

  • 项目依赖版本:spring-cloud-starter-openfeign:3.0.1
  • 直接通过浏览器访问对应SonarQube接口,返回的JSON错误信息使用普通单引号,可确认转义逻辑发生在Feign处理环节。
  • 问题影响:单元测试断言异常消息时,匹配带普通单引号的字符串会失败,只有匹配带\u0027转义序列的字符串才能通过。

复现代码

void measuresSearchHistoryUnknownTest() {
    assertThatExceptionOfType(FeignException.NotFound.class)
            .isThrownBy(() -> sonarFeignClient.measuresSearchHistory(
                    "badProject",
                    String.join(",",
                            EnumUtils.getJsonValue(SonarMetric.BLOCKER_VIOLATIONS),
                            EnumUtils.getJsonValue(SonarMetric.CRITICAL_VIOLATIONS)
                    ),
                    1,
                    10
            )).withMessageContaining("Component key 'badProject' not found");
//                )).withMessageContaining("Component key \\u0027badProject\\u0027 not found");
}

报错日志

Expecting throwable message:
  <"[404] during [GET] to [*******/sonar/api/measures/search_history?component=badProject&metrics=blocker_violations%2Ccritical_violations&p=1&ps=10] [SonarFeignClient#measuresSearchHistory(String,String,int,int)]: [{"errors":[{"msg":"Component key \u0027badProject\u0027 not found"}]}]">
to contain:
  <"Component key 'badProject' not found">
but did not.

Throwable that failed the check:

feign.FeignException$NotFound: [404] during [GET] to [*******/sonar/api/measures/search_history?component=badProject&metrics=blocker_violations%2Ccritical_violations&p=1&ps=10] [SonarFeignClient#measuresSearchHistory(String,String,int,int)]: [{"errors":[{"msg":"Component key \u0027badProject\u0027 not found"}]}]

根因

Spring Cloud OpenFeign 3.0.1版本绑定的feign-core核心包,在构造Feign异常对象、拼接错误响应体到异常消息时,默认使用的JSON序列化逻辑会对单引号等特殊字符做Unicode转义,没有保留原始字符格式。

解决方案

方案1:自定义Feign错误解码器(推荐)

自定义ErrorDecoder替换默认实现,读取错误响应体后主动替换转义字符,保证异常消息格式和接口原始返回一致:

import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import org.springframework.context.annotation.Bean;
import java.nio.charset.StandardCharsets;

public class FeignConfig {
    @Bean
    public ErrorDecoder feignErrorDecoder() {
        return (methodKey, response) -> {
            String body = Util.toString(response.body().asReader(StandardCharsets.UTF_8));
            // 替换转义的单引号为原始字符
            String unescapedBody = body.replace("\\u0027", "'");
            String message = String.format("[%d] during [%s] to [%s] [%s]: [%s]",
                    response.status(),
                    response.request().httpMethod().name(),
                    response.request().url(),
                    methodKey,
                    unescapedBody);

            if (response.status() == 404) {
                return new FeignException.NotFound(message, response.request(), unescapedBody.getBytes(StandardCharsets.UTF_8), response.headers());
            }
            return new FeignException(response.status(), message, response.request(), unescapedBody.getBytes(StandardCharsets.UTF_8), response.headers());
        };
    }
}

将该配置类指定到对应的FeignClient上即可生效:

@FeignClient(name = "sonarClient", url = "${sonar.url}", configuration = FeignConfig.class)
public interface SonarFeignClient {
    // 接口方法定义
}

注意:自定义异常构造时需要传入原始响应体的字节数组,避免后续逻辑需要读取错误响应内容时出现流已关闭、内容为空的问题。

方案2:全局配置Jackson关闭字符转义

如果项目中所有Feign客户端都需要关闭这类转义,可以直接全局配置Feign使用的ObjectMapper,禁用特殊字符的Unicode转义规则:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    // 关闭非ASCII字符转义
    objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false);
    return objectMapper;
}

临时方案(仅适配测试场景)

如果不需要修改生产代码的异常逻辑,可以在单元测试中先对异常消息做转义替换后再做断言,不需要匹配转义后的字符串。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:06:22