springmvc3.0使用@ResponseBody返回参数乱码

—— 解决springmvc3的JSON返回数据乱码
标签: 乱码 springmvc
2017-12-06 阅读(135)

使用@ResponseBody注解返回的json数据乱码。用户网络上大多数贴都是springmvc3.0以上版本,试了很多办法都不行。只能来点简单粗暴的办法。



发现原因

使用<mvc:annotation-driven />,Spring的StringHttpMessageConverter默认配置是ISO-8859-1的。如下图源代码片段所示:

代码片段.jpg

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
    private final List<Charset> availableCharsets = new ArrayList(Charset.availableCharsets().values());
    private boolean writeAcceptCharset = true;
    ...
}


调试返回情况如下图:

2.jpg

{data: "", message: "????", success: 0}



解决办法

快刀斩乱麻

第一步:

查看spring的StringHttpMessageConverter的源码,自定义StringHttpMessageConverter类,继承AbstractHttpMessageConverter<String>修改默认编码为UTF-8。

package com.weizhixi.converter;

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;

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;

/**
 * Created by cxq on 2017/12/6.
 */
public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private final List<Charset> availableCharsets = new ArrayList(Charset.availableCharsets().values());
    private boolean writeAcceptCharset = true;

    public StringHttpMessageConverter() {
        super(new MediaType[]{new MediaType("text", "plain", DEFAULT_CHARSET), MediaType.ALL});
    }

    public void setWriteAcceptCharset(boolean writeAcceptCharset) {
        this.writeAcceptCharset = writeAcceptCharset;
    }

    public boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }

    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));
    }

    protected Long getContentLength(String s, MediaType contentType) {
        if(contentType != null && contentType.getCharSet() != null) {
            Charset charset = contentType.getCharSet();

            try {
                return Long.valueOf((long)s.getBytes(charset.name()).length);
            } catch (UnsupportedEncodingException var5) {
                throw new InternalError(var5.getMessage());
            }
        } else {
            return null;
        }
    }

    protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
        if(this.writeAcceptCharset) {
            outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
        }

        MediaType contentType = outputMessage.getHeaders().getContentType();
        Charset charset = contentType.getCharSet() != null?contentType.getCharSet():DEFAULT_CHARSET;
        FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset));
    }

    protected List<Charset> getAcceptedCharsets() {
        return this.availableCharsets;
    }
}


第二步:

弃用<mvc:annotation-driven />,加上2个配置。注意messageConverters使用刚刚自定义的StringHttpMessageConverter。

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>

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

以上处理完毕!


尝试再访问下:

正常返回.jpg

{data: "", message: "请先登录", success: 0}

已经正常返回了。



原创文章,转载请注明出处:https://www.weizhixi.com/user/index/article/id/21.html

分类:
点击(175) 阅读(135) 举报