`

SpringMVC3的ResponseBody返回字符串乱码问题解决

    博客分类:
  • Java
阅读更多

SpringMVC的@ResponseBody注解可以将请求方法返回的对象直接转换成JSON对象,但是当返回值是String的时候,中文会乱码

 

原因是因为其中字符串转换和对象转换用的是两个转换器,而String的转换器中固定了转换编码为"ISO-8859-1"

 

网上也很多种解决方法,有通过配置Bean编码的,也有自己重写转换器的,我这里多次尝试未果,只能自己解决。

 

有两种解决办法:

1.返回字符串时,将字符串结果转换

 

return new String("你好".getBytes(), "ISO-8859-1");

 

2.添加@RequestMapping注解,配置produces的值

 

@RequestMapping(value = "/add", produces = {"application/json;charset=UTF-8"})

 

由于我是为了使用JSONP协议,需要连同callback一起返回,所以我定义的是

 

@RequestMapping(value = "/add", params = {"callback"}, produces = {"text/javascript;charset=UTF-8"})

 

以上提供的方法虽然需要额外配置,但相对灵活,喜欢一次性永久搞定的,还是应该考虑网上的方法,修改源码,或者替换默认的字符串转换器。

但是在使用<mvc:annotation-driven />配置的前提下,貌似网上的方法都不可靠,可能跟版本或者配置有关系

 

这边提供一种修改方法,我这边使用的是3.1的mvc

1.参考网上将默认的StringHttpMessageConverter重写一遍,将其中的编码改为UTF-8

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
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.http.converter.AbstractHttpMessageConverter;
import org.springframework.util.FileCopyUtils;

public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {

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

	private final List<Charset> availableCharsets;

	private boolean writeAcceptCharset = true;

	public UTF8StringHttpMessageConverter() {
		super(new MediaType("text", "plain", DEFAULT_CHARSET), MediaType.ALL);
		this.availableCharsets = new ArrayList<Charset>(Charset.availableCharsets().values());
	}

	/**
	 * Indicates whether the {@code Accept-Charset} should be written to any outgoing request.
	 * <p>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 clazz, HttpInputMessage inputMessage) throws IOException {
		Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());
		return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
	}

	@Override
	protected Long getContentLength(String s, MediaType contentType) {
		Charset charset = getContentTypeCharset(contentType);
		try {
			return (long) s.getBytes(charset.name()).length;
		}
		catch (UnsupportedEncodingException ex) {
			// should not occur
			throw new InternalError(ex.getMessage());
		}
	}

	@Override
	protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
		if (writeAcceptCharset) {
			outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
		}
		Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType());
		FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset));
	}

	/**
	 * Return the list of supported {@link Charset}.
	 *
	 * <p>By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses.
	 *
	 * @return the list of accepted charsets
	 */
	protected List<Charset> getAcceptedCharsets() {
		return this.availableCharsets;
	}

	private Charset getContentTypeCharset(MediaType contentType) {
		if (contentType != null && contentType.getCharSet() != null) {
			return contentType.getCharSet();
		}
		else {
			return DEFAULT_CHARSET;
		}
	}

}

 

2.context配置

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
                                                		  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                                                		  http://www.springframework.org/schema/context 
                                                		  http://www.springframework.org/schema/context/spring-context-3.1.xsd
                                                		  http://www.springframework.org/schema/aop 
                                                		  http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
                                                		  http://www.springframework.org/schema/tx 
                                                		  http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
                                                		  http://www.springframework.org/schema/mvc 
                                                		  http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
                                                		  http://www.springframework.org/schema/context 
                                                		  http://www.springframework.org/schema/context/spring-context-3.1.xsd">


	<mvc:annotation-driven>
		<mvc:message-converters>
			<bean class="yourpackage.UTF8StringHttpMessageConverter" />
		</mvc:message-converters>
	</mvc:annotation-driven>

......
	
</beans>
 

 

分享到:
评论
5 楼 云端月影 2015-06-17  
感谢
4 楼 欣水寓言 2014-04-21  
tw_wangzhengquan 写道
这样就可以了
 <mvc:annotation-driven>  
        <mvc:message-converters>  
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" >  
	            <property name = "supportedMediaTypes">
					<list>
	 					 <value>text/plain;charset=UTF-8</value>
	 				</list>
				</property>
            </bean>  
            <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">  
			    <property name="supportedMediaTypes">  
			        <list>  
			            <value>applicaton/json;charset=UTF-8</value>  
			        </list>  
			    </property>  
			</bean>  
        </mvc:message-converters>  
        <mvc:argument-resolvers>  
        	<!-- 处理pageable的实例化,避免出现无法实例化接口的问题,并使得能够使用PageableDefault注解提供默认初始值 -->  
        	<bean class="org.springframework.data.web.PageableArgumentResolver"></bean>  
    	</mvc:argument-resolvers>  
    </mvc:annotation-driven>  


相信做spring框架的不会连这都想不到,还要你重写?


你用的是什么版本的?spring3这样配置是没有用的,源码里面是写死了编码的,无法这么配置
3 楼 tw_wangzhengquan 2014-03-06  
这样就可以了
 <mvc:annotation-driven>  
        <mvc:message-converters>  
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" >  
	            <property name = "supportedMediaTypes">
					<list>
	 					 <value>text/plain;charset=UTF-8</value>
	 				</list>
				</property>
            </bean>  
            <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">  
			    <property name="supportedMediaTypes">  
			        <list>  
			            <value>applicaton/json;charset=UTF-8</value>  
			        </list>  
			    </property>  
			</bean>  
        </mvc:message-converters>  
        <mvc:argument-resolvers>  
        	<!-- 处理pageable的实例化,避免出现无法实例化接口的问题,并使得能够使用PageableDefault注解提供默认初始值 -->  
        	<bean class="org.springframework.data.web.PageableArgumentResolver"></bean>  
    	</mvc:argument-resolvers>  
    </mvc:annotation-driven>  


相信做spring框架的不会连这都想不到,还要你重写?
2 楼 欣水寓言 2012-07-05  
yingzhor 写道
用<mvc:annotation-driven />配置的前提下,替换掉默认的字符转换期挺靠谱的呀。

默认你的spring-mvc.xml配置文件的schema版本过低?

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

	<mvc:annotation-driven conversion-service="conversion-service" validator="validator">
		<mvc:message-converters>
			<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
			<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
			<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
			<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
			<bean class="com.mycompany.UTF8StringHttpMessageConverter" />
		</mvc:message-converters>
	</mvc:annotation-driven>

</beans>




我参考了你的文章,改了下,现在能用了,但你的配置我用后会报错,我简化了下,已经可以用了,谢谢啦
1 楼 yingzhor 2012-07-05  
用<mvc:annotation-driven />配置的前提下,替换掉默认的字符转换期挺靠谱的呀。

默认你的spring-mvc.xml配置文件的schema版本过低?

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

	<mvc:annotation-driven conversion-service="conversion-service" validator="validator">
		<mvc:message-converters>
			<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
			<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
			<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
			<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
			<bean class="com.mycompany.UTF8StringHttpMessageConverter" />
		</mvc:message-converters>
	</mvc:annotation-driven>

</beans>



相关推荐

    SpringMVC中解决@ResponseBody注解返回中文乱码问题

    本文将详细介绍如何解决SpringMVC中`@ResponseBody`注解返回中文乱码的问题。 首先,我们可以尝试使用`@RequestMapping`注解的`produces`属性来指定响应内容的MIME类型和字符集。例如: ```java @RequestMapping...

    SpringMVC解决乱码

    然而,在使用SpringMVC时,可能会遇到乱码问题,例如在使用@ResponseBody注解时返回的数据出现乱码。在本文中,我们将讨论解决SpringMVC乱码问题的两种方法。 方法一:配置AnnotationMethodHandlerAdapter 在...

    Springmvc如何返回xml及json格式数据

    在Spring MVC中,开发Web应用时,经常需要处理XML和JSON这两种常见...避免一些错误尝试,如直接返回XML字符串或未序列化的对象,这可能会导致乱码或解析问题。通过合理的配置和优化,可以提高数据交换的效率和正确性。

    用ajax传递json到前台中文出现问号乱码问题的解决办法

    具体问题出现在使用了SpringMVC框架的开发场景中,在Controller层使用了@ResponseBody注解来直接返回JSON数据。该注解使得Spring MVC框架会将返回的对象自动转换为JSON格式的字符串。然而,默认情况下,Spring框架...

    Spring MVC 关于controller的字符编码问题

    当涉及到非英文字符,如中文,时,字符编码问题可能会导致乱码。这是因为Spring MVC默认使用ISO-8859-1字符集,而中文字符不在这个字符集中。 在处理字符编码问题时,有几种常见的解决方案: 1. **不使用`@...

    Java面试框架高频问题2019

    - `${}`:字符串替换,可能存在SQL注入风险。 **问题七:当实体类中的属性名和表中的字段名不一样,怎么办?** - 使用`&lt;resultMap&gt;`标签进行映射。 **问题八:模糊查询like语句该怎么写?** - 使用`&lt;if&gt;`标签条件...

    SpringMVC【入门】篇

    3. 文件上传:SpringMVC 支持传统方式和跨服务器方式的文件上传,需要配置 Filter 解决中文乱码问题,并考虑 Tomcat 对某些操作的限制。 4. 异常处理:通过 @ExceptionHandler 注解定义全局异常处理器,实现统一的...

    Spring MVC面试宝典1.pdf

    - **重定向**:在控制器方法中返回一个字符串"redirect:/url"。 - **转发**:返回一个视图名称,SpringMVC会自动进行转发处理。 ##### 3.3 SpringMVC怎么和AJAX相互调用的? SpringMVC支持通过AJAX进行异步请求处理...

    Springmvc完成ajax功能实例详解

    当返回的字符串包含中文字符时,可能会出现乱码问题。为了解决这个问题,我们有两种解决方案: 1. 修改`@RequestMapping`注解,指定响应的字符集,如上面`Ajax1`方法所示。 2. 在Spring MVC配置中,通过`...

    Spring MVC面试题(2022最新版)

    如何解决POST请求中文乱码问题,GET的又如何处理呢? - 对于POST请求,可以在web.xml中配置字符编码过滤器,确保所有请求都使用统一的字符编码: ```xml &lt;filter-name&gt;characterEncodingFilter &lt;filter-class&gt;...

    base64,java与JavaScript实现

    // 如果此方法直接返回String对象,会出现中文乱码问题。 Map, String&gt; result = new HashMap(); String detext = ""; try { detext = new String(Base64.getUrlDecoder().decode(textcomment), CHARSET); } ...

Global site tag (gtag.js) - Google Analytics