如何将IBM大型机IBM-37编码的XML消息转为UTF-8适配SpringBoot?
解决IBM-37编码XML转UTF-8的Feign实现方案
核心问题:大型机返回的响应采用IBM-37(CP037) EBCDIC编码,Feign默认以UTF-8解码,导致乱码。以下是两种可行的实现方法:
方法一:自定义Feign解码器手动转换编码
通过实现Feign的Decoder接口,拦截响应字节流,先以IBM-37解码,再转换为UTF-8格式。
1. 实现自定义Decoder
import feign.Response; import feign.Util; import feign.decoder.Decoder; import feign.decoder.StringDecoder; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class IBM37Decoder extends Decoder { private final Decoder defaultDecoder; public IBM37Decoder() { this.defaultDecoder = new StringDecoder(); } @Override public Object decode(Response response, Type type) throws IOException { if (String.class.equals(type)) { // 读取响应原始字节 byte[] responseBytes = Util.toByteArray(response.body().asInputStream()); // 用IBM-37解码为字符串 String ebcdicStr = new String(responseBytes, Charset.forName("IBM-37")); // 转换为UTF-8(Java字符串内部为UTF-16,此步骤确保编码标准化) return new String(ebcdicStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); } // 非String类型交给默认解码器处理 return defaultDecoder.decode(response, type); } }
2. 配置Feign客户端使用自定义Decoder
RESoapClient soapClient = Feign.builder() .client(new ApacheHttp5Client()) .decoder(new IBM37Decoder()) // 替换默认解码器 .target(SoapClient.class, "http://10.10.10.10:8000/B2B/Broker/api/v1");
方法二:配置Apache HttpClient5默认编码
通过自定义Apache HttpClient5实例,设置响应的默认字符编码为IBM-37,让HttpClient自动完成解码转换。
1. 创建自定义HttpClient
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.config.CharCodingConfig; import java.nio.charset.Charset; CloseableHttpClient httpClient = HttpClients.custom() .setDefaultCharCodingConfig(CharCodingConfig.custom() .setCharset(Charset.forName("IBM-37")) // 设置默认响应编码 .build()) .build();
2. 绑定到Feign客户端
RESoapClient soapClient = Feign.builder() .client(new ApacheHttp5Client(httpClient)) // 传入自定义HttpClient .target(SoapClient.class, "http://10.10.10.10:8000/B2B/Broker/api/v1");
注意:如果响应头
Content-Type明确指定了编码,HttpClient会优先使用响应头的编码配置,此方法仅在响应未指定编码时生效。
补充:请求头优化
可在Feign接口的请求头中添加Accept-Charset,明确告知服务器返回IBM-37编码的响应:
public interface SoapClient { @RequestLine("POST") @Headers({ "SOAPAction: operationSaveReq", "Content-Type: text/xml;charset=UTF-8", "Accept: text/xml", "Accept-Charset: IBM-37, UTF-8" }) String operationSaveReq(String soapBody); }
内容的提问来源于stack exchange,提问作者marcelotrajano
相关产品推荐
相关产品推荐

