java restful中文乱码_使用RestTemplate访问RESTful服务乱码处理

在接口服务开发中,我们经常用到Spring模板类RestTemplate访问restful服务。但RestTemplate处理中文乱码问题比较麻烦。以我们项目Spring版本4.1.3.RELEASE为例,RestTemplate默认构造方法初始化的StringHttpMessageConverter的默认字符集是 ISO-8859-1,所以导致RestTemplate请求的响应内容会出现中文乱码。处理方法可如下:import java.io.IOException;

import java.nio.charset.StandardCharsets;

import java.util.Collections;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.http.HttpRequest;

import org.springframework.http.client.ClientHttpRequestExecution;

import org.springframework.http.client.ClientHttpRequestInterceptor;

import org.springframework.http.client.ClientHttpResponse;

import org.springframework.http.converter.StringHttpMessageConverter;

import org.springframework.web.client.RestTemplate;

public class RestTemplateUtil {

public static RestTemplate getInstance() {

RestTemplate restTemplate = new RestTemplate();

// 设置编码

restTemplate.getMessageConverters()

.set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

// 打印日志

restTemplate.setInterceptors(

Collections.singletonList(new LoggingClientHttpRequestInterceptor()));

return restTemplate;

}

}

class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

private final static Logger LOGGER = LoggerFactory.getLogger(LoggingClientHttpRequestInterceptor.class);

@Override

public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)

throws IOException {

traceRequest(request, body);

ClientHttpResponse response = execution.execute(request, body);

traceResponse(response);

return response;

}

private void traceRequest(HttpRequest request, byte[] body) throws IOException {

LOGGER.debug("======================request begin========================================");

LOGGER.debug("URI         : {}", request.getURI());

LOGGER.debug("Method      : {}", request.getMethod());

LOGGER.debug("Headers     : {}", request.getHeaders());

LOGGER.debug("Request body: {}", new String(body, "UTF-8"));

LOGGER.debug("=====================request end===========================================");

}

private void traceResponse(ClientHttpResponse response) throws IOException {

//StringBuilder inputStringBuilder = new StringBuilder();

//try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"))) {

//String line = bufferedReader.readLine();

//while (line != null) {

//inputStringBuilder.append(line);

//inputStringBuilder.append('\n');

//line = bufferedReader.readLine();

//}

//}

LOGGER.debug("=========================response begin=======================================");

LOGGER.debug("Status code  : {}", response.getStatusCode());

LOGGER.debug("Status text  : {}", response.getStatusText());

LOGGER.debug("Headers      : {}", response.getHeaders());

// WARNING: comment out in production to improve performance

LOGGER.debug("Response body: {}", "WARNING: comment out in production to improve performance");

LOGGER.debug("====================response end==============================================");

}

}

如果其他Spring版本无法按如上方法解决,可运用类加载机制,从根源上解决问题,即重写org.springframework.http.converter.StringHttpMessageConverter.class,将DEFAULT_CHARSET的值改为Charset.forName("UTF-8")。以spring版本4.1.3.RELEASE为例:/**

* Copyright 2002-2014 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*      http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.springframework.http.converter;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.nio.charset.Charset;

import java.util.ArrayList;

import java.util.List;

import org.springframework.http.HttpInputMessage;

import org.springframework.http.HttpOutputMessage;

import org.springframework.http.MediaType;

import org.springframework.util.StreamUtils;

/**

* Implementation of {@link HttpMessageConverter} that can read and write strings.

*

By default, this converter supports all media types ({@code */*}),

* and writes with a {@code Content-Type} of {@code text/plain}. This can be overridden

* by setting the {@link #setSupportedMediaTypes supportedMediaTypes} property.

*

* @author Arjen Poutsma

* @since 3.0

*/

public class StringHttpMessageConverter extends AbstractHttpMessageConverter {

public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

private final Charset defaultCharset;

private final List availableCharsets;

private boolean writeAcceptCharset = true;

/**

* A default constructor that uses {@code "ISO-8859-1"} as the default charset.

* @see #StringHttpMessageConverter(Charset)

*/

public StringHttpMessageConverter() {

this(DEFAULT_CHARSET);

}

/**

* A constructor accepting a default charset to use if the requested content

* type does not specify one.

*/

public StringHttpMessageConverter(Charset defaultCharset) {

super(new MediaType("text", "plain", defaultCharset), MediaType.ALL);

this.defaultCharset = defaultCharset;

this.availableCharsets = new ArrayList(Charset.availableCharsets().values());

}

/**

* Indicates whether the {@code Accept-Charset} should be written to any outgoing request.

Default is {@code true}.

*/

public void setWriteAcceptCharset(boolean writeAcceptCharset) {

this.writeAcceptCharset = writeAcceptCharset;

}

@Override

public boolean supports(Class> clazz) {

return String.class.equals(clazz);

}

@Override

protected String readInternal(Class extends String> clazz, HttpInputMessage inputMessage) throws IOException {

Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());

return StreamUtils.copyToString(inputMessage.getBody(), charset);

}

@Override

protected Long getContentLength(String str, MediaType contentType) {

Charset charset = getContentTypeCharset(contentType);

try {

return (long) str.getBytes(charset.name()).length;

}

catch (UnsupportedEncodingException ex) {

// should not occur

throw new IllegalStateException(ex);

}

}

@Override

protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {

if (this.writeAcceptCharset) {

outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());

}

Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType());

StreamUtils.copy(str, charset, outputMessage.getBody());

}

/**

* Return the list of supported {@link Charset}s.

By default, returns {@link Charset#availableCharsets()}.

* Can be overridden in subclasses.

* @return the list of accepted charsets

*/

protected List getAcceptedCharsets() {

return this.availableCharsets;

}

private Charset getContentTypeCharset(MediaType contentType) {

if (contentType != null && contentType.getCharSet() != null) {

return contentType.getCharSet();

}

else {

return this.defaultCharset;

}

}

}


版权声明:本文为weixin_32121331原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。