如果在Spring的@Responsbody返回的內容中,發現亂碼,需要從以下幾方面來解決。
1. 確保在web.xml中配置Spring的Character Encoding Filter:
Xml代碼 <!-- Servlet Encoding Start --> <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Servlet Encoding End -->
2. 如果在@ResponseBody注釋的方法下的傳回值類型是String,則在結果返回給使用者之前,如果在Spring的設定檔中配置了<mvc:annotation-driven />,則Spring預設會去調用一個叫StringHttpMessageConverter
的類進行內容的輸出。為什麼會出現亂碼呢。
解決方案1: 查看StringHttpMessageConverter的源碼,發下StringHttpMessageConverter類中的預設編碼是ISO-8859-1編碼,改編碼是西歐字元集編碼,顯然不會支援中文。(PS:感覺這是Spring的bug,明顯應該用UTF-8嘛,我已經在Spring官網上中報了這個bug)
Java代碼 public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); private final Charset defaultCharset; private final List<Charset> availableCharsets;
而且從上面的代碼中可以看出,與字元相關的3個變數都是final的,意味著我們不能通過set或者構造器的注入去動態更改上面3個值。
進一步分析源碼可以看出,StringHttpMessageConverter繼承與AbstractHttpMessageConverter<String>,分析該抽象類別得,相關的操作字元編碼的方法可以重寫,於是我們可以自訂一個類繼承StringHttpMessageConverter,然後重寫相關的方法,代碼如下:
Java代碼 /** * */ package com.chuanliu.platform.activity.basic.converter; import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.List; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.util.StreamUtils; /** * 用於處理中文亂碼問題: Spring bug - * * In StringHttpMessageConverter, the default char set is ISO-8859-1(西歐字元集) * * @author Josh Wang(Sheng) * * @email josh_wang23@hotmail.com */ public class UTF8StringHttpMessageConverter extends StringHttpMessageConverter { private static final MediaType UTF8 = new MediaType("text", "plain", Charset.forName("UTF-8"));