0、RestTemplate返回数据中文问号乱码

问题描述:

spring-web 版本:

spring-web-3.1.2.RELEASE

使用 spring-web 的 RestTemplate 提交xml数据post请求,响应数据中,中文字符问号乱码:

<msg>??????!</msg>

请求代码:

public void testResquestPostXML() throws Exception{
    String url = "http://127.0.0.1/yandype/yandype_response.action";	
    //设置请求头
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_XML);
    // 请求体
    HttpEntity<String> formEntity = new HttpEntity<String>(getXmlStr().toString(), headers);
    // 执行请求
    RestTemplate restTemplate = new RestTemplate()
    ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, formEntity, String.class);
    String xmlStr = responseEntity.getBody();
    System.out.println("响应报文:\n" + xmlStr);
}

public StringBuffer getXmlStr(){
		StringBuffer xmlString = new StringBuffer();
		xmlString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
		         .append("<xml>")
		         .append("<request>")
		         .append("<R1>A</R1>")
		         .append("<R2>B</R2>")
		         .append("</request>")
		         .append("<data>")
		         .append("<D1>1202004071029301212125</D1>")
		         .append("<D2>1</D2>")
		         .append("</data>")
		         .append("</xml>");
		return xmlString;
}

产生原因:

查了类似的问题,发现都是说StringHttpMessageConverter() 消息转换器编码问题。设置,编码即可:

public static void setRestTemplateEncode(RestTemplate restTemplate) {
    if (null != restTemplate) {
    List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
    for (int i = 0; i < messageConverters.size(); i++) {
        HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
        if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
            messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        }
    }
   }
}

不知是当前 spring-web-3.1.2 版本原因,还是其它细节问题。设置上面的代码没有生效。请求响应的数据还是中文乱码问号。

然后,参考了这位兄弟的博客:

https://blog.csdn.net/weixin_33994429/article/details/92278767

在 xml 里面配置下 RestTemplate 试下看:

<!-- 解决 restTemplate 中文乱码 -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
	<property name="messageConverters">
		<list>
			<bean class="org.springframework.http.converter.FormHttpMessageConverter">
				<property name="supportedMediaTypes">
					<list>
                            		<value>application/x-www-form-urlencoded;charset=UTF-8</value>
                            		<value>multipart/form-data;charset=UTF-8</value>
                            		<value>text/plain;charset=UTF-8</value>
                            		<value>application/xml;charset=UTF-8</value>
					</list>
				</property>
				<property name="partConverters">
					<list>
						<ref bean="stringHttpMessageConverter" />
						<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
						<bean class="org.springframework.http.converter.ResourceHttpMessageConverter" />
						<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
						<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
						<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
					</list>
				</property>
			</bean>
			<ref bean="stringHttpMessageConverter" />
		</list>
	</property>
</bean>

<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
	<property name="supportedMediaTypes">
		<list>
			<value>text/html;charset=UTF-8</value>
			<value>text/plain;charset=UTF-8</value>
			<value>multipart/form-data;charset=UTF-8</value>
			<value>application/xml;charset=UTF-8</value>
		</list>
	</property>
</bean>

 

这时,在测试程序中把 new RestTemplate() 注释掉,使用@Autowired RestTemplate restTemplate;  注入 RestTemplate 再测试请求发现响应数据中,中文字符正常了。

根据 xml 配置,我手动配置一个 RestTemplate 注解配置类:

package com.yandype.config;

import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.web.client.RestTemplate;


/**
 * 
 * 扩展 RestTemplate 支持访问 https,这里使用httpclient的factory
 * 
 *   @Configuration 可理解为用spring的时候xml里面的<beans>标签
 *   @Bean 可理解为用spring的时候xml里面的<bean>标签
 */
@Configuration
public class RestTemplateConfig {

	@Bean
	public RestTemplate restTemplate() throws KeyStoreException,
			NoSuchAlgorithmException, KeyManagementException {
		// 忽略掉对服务器端证书的校验(信任所有)
		SSLContext sslContext = SSLContexts.custom()
				.loadTrustMaterial(null, new TrustStrategy() {
							@Override
							public boolean isTrusted(X509Certificate[] chain,
									String authType)throws CertificateException {
								return true;
							}
						}).build();
        // SSLConnectionSocketFactory 中设置允许所有主机名称就可以忽略主机名称验证
		SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
        // 自定义 HttpClient 客户端设置配置参数
		CloseableHttpClient httpClient = HttpClients.custom()
				.setSSLSocketFactory(csf).build();
        // requestFactory 可以保证长连接可控制能够建立的连接数还能细粒度的控制到某个 server 的连接数
		HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
		requestFactory.setHttpClient(httpClient);
		RestTemplate restTemplate = new RestTemplate(requestFactory);
		setRestTemplateEncode(restTemplate);
		return restTemplate;
	}
	
	@SuppressWarnings("unchecked")
	public void setRestTemplateEncode(RestTemplate restTemplate) {
	    if (restTemplate != null){
	    	// <bean class="org.springframework.http.converter.StringHttpMessageConverter">
	    	StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
	    	// <list>
	        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
	        supportedMediaTypes.add(MediaType.TEXT_HTML);
	        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
	        supportedMediaTypes.add(MediaType.MULTIPART_FORM_DATA);
	        supportedMediaTypes.add(MediaType.APPLICATION_XML);
	        // <property name="supportedMediaTypes">
			stringConverter.setSupportedMediaTypes(supportedMediaTypes);
	    	
			// <bean class="org.springframework.http.converter.FormHttpMessageConverter">
	    	FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
	    	// <list>
	    	List<MediaType> formSupportedMediaTypes = new ArrayList<MediaType>();
	    	formSupportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
	    	formSupportedMediaTypes.add(MediaType.MULTIPART_FORM_DATA);
	    	formSupportedMediaTypes.add(MediaType.TEXT_PLAIN);
	    	formSupportedMediaTypes.add(MediaType.APPLICATION_XML);
	    	// <property name="supportedMediaTypes">
			formHttpMessageConverter.setSupportedMediaTypes(formSupportedMediaTypes);
			// <list>
	    	List<HttpMessageConverter<?>> formPartConverters = new ArrayList<HttpMessageConverter<?>>();
	    	formPartConverters.add(stringConverter);
	    	formPartConverters.add(new ByteArrayHttpMessageConverter());
	    	formPartConverters.add(new ResourceHttpMessageConverter());
	    	formPartConverters.add(new SourceHttpMessageConverter());
	    	formPartConverters.add(new Jaxb2RootElementHttpMessageConverter());
	    	formPartConverters.add(new MappingJacksonHttpMessageConverter());
	    	// <property name="partConverters">
			formHttpMessageConverter.setPartConverters(formPartConverters);
	    	
			// <list>
	        List<HttpMessageConverter<?>> partConverters = new ArrayList<HttpMessageConverter<?>>();
			partConverters.add(formHttpMessageConverter);
	        partConverters.add(stringConverter);
	        
	        // <property name="messageConverters">
	        restTemplate.setMessageConverters(partConverters);
	    }
	}
	
	@Bean
	public ObjectMapper objectMapper(){
		return new ObjectMapper();
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值