Spring3.0 使用@ResponseBody处理json出现乱码

   本来是使用的Jackson来处理普通对象到json对象的转换工作 ,无奈在对象中的属性为空时Jackson默认是将为空的属性也转换,然后就报错。犹豫 而且当前场景无法使用Jackson自带的注解等方式排除null属性,于是乎我便痛下狠心,用json-lib自己转换直接返回json字符串。结果异常是没了,但是乱码又出现了。。。

  根据之前的经验,我发现出现的乱码都是“???”一堆的问号,直觉告诉我又是ISO8859-1在作祟。于是乎,查了查源码,果然在 StringHttpMessageConverter中发现了端倪。

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {

	public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");

	private final List<Charset> availableCharsets;

	private boolean writeAcceptCharset = true;

	public StringHttpMessageConverter() {
		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 {
		MediaType contentType = inputMessage.getHeaders().getContentType();
		Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
		return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
	}

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

	@Override
	protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
		if (writeAcceptCharset) {
			outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets());
		}
		MediaType contentType = outputMessage.getHeaders().getContentType();
		Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
		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;
	}

}

   (⊙o⊙)… 也不知道 为啥SpringMVC的开发者将ISO-8859-1设置为默认编码格式。得亏 SpringMVC提供了配置方式来解决这个问题。开源的东西的优势立马就体现出来了。

  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
        <property name="messageConverters">  
             <list>  
                 <bean class = "org.springframework.http.converter.StringHttpMessageConverter">  
                    <property name = "supportedMediaTypes">  
                          <list>  
                              <value>text/html;charset=UTF-8</value>  
                         </list>  
                    </property>  
                 </bean>  
            </list>  
        </property>  
</bean> 

 

 看了网上不少都说必须 将以上配置放在<context:component-scan/>前面  我就有点儿丈二和尚摸不到头脑了  这都是不沾边的东西 有嘛关系吗?

 

   具体要说的话应该是跟<mvc:annotation-driven/>关系比较大 (如果你不使用这种注解方式 就更容易了) 需要我们将上面的配置放在<mvc:annotation-driven/>之前。下面是鄙人做的小测试。

/**
 * @Author: Sonicery_D
 * @Date: 2014-10-10
 */
public class ExtBeanFactoryProcessor implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
			throws BeansException {
		String[] beanNames = beanFactory.getBeanNamesForType(AnnotationMethodHandlerAdapter.class);
		for(String name : beanNames){
			System.out.println("---------------"+name+"-----start----");
			AnnotationMethodHandlerAdapter adapter = (AnnotationMethodHandlerAdapter)beanFactory.getBean(name);
			HttpMessageConverter<String>[] converters = (HttpMessageConverter<String>[])adapter.getMessageConverters();
			for(HttpMessageConverter<String> converter : converters){
				for(MediaType type :converter.getSupportedMediaTypes()){
					if(type==null ||type.getCharSet() == null){
						System.out.println("encoding:null");
					}else{
						System.out.println("encoding:"+type.getCharSet().name());
					}
				}
			}
			System.out.println("---------------"+name+"-----end----");
		}
	}

}

 放在<mvc:annotation-driven/>之前:

---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0-----start----
encoding:UTF-8
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0-----end----
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#1-----start----
- Hibernate Validator 4.1.0.Final
encoding:null
encoding:null
encoding:ISO-8859-1
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:UTF-8
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#1-----end----
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#2-----start----
encoding:null
encoding:null
encoding:ISO-8859-1
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#2-----end----

 放在<mvc:annotation-driven/>之后

---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0-----start----
- Hibernate Validator 4.1.0.Final
encoding:null
encoding:null
encoding:ISO-8859-1
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:UTF-8
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0-----end----
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#1-----start----
encoding:UTF-8
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#1-----end----
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#2-----start----
encoding:null
encoding:null
encoding:ISO-8859-1
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
encoding:null
---------------org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#2-----end----

哈哈  结果显而易见。

你可能感兴趣的:(@ResponseBody)