天天看點

springmvc配置一:ajax請求防止傳回中文亂碼配置說明

Spring3.0 MVC @ResponseBody 的作用是把傳回值直接寫到HTTP response body裡。

Spring使用AnnotationMethodHandlerAdapter的handleResponseBody方法, AnnotationMethodHandlerAdapter使用request header中"Accept"的值和messageConverter支援的MediaType進行比對,然後會用"Accept"的第一個值寫入response的"Content-Type"。一般的請求都是通過浏覽器進行的,request header中"Accept"的值由浏覽器生成。

有人跟蹤@ResponseBody 的實作類發現其預設的編碼是 iso-8859-1,

解決辦法,在spring mvc的配置檔案中手工配置bean:

<!-- 啟動Spring

MVC的注解功能,完成請求和注解POJO的映射 -->

<bean

class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"

>

<property

name="messageConverters">

<list>

<bean class =

"org.springframework.http.converter.StringHttpMessageConverter">

<property name =

"supportedMediaTypes">

<value>text/html;charset=UTF-8</value>

</list>

</property>

</bean>

這樣通過配置AnnotationMethodHandlerAdapter類messageConverters屬性來指定編碼。

記住,需要把bean部分加入到<context:component-scan

base-package="com.zlscw.mvc" />前面,

這樣就可以在jquery中直接調用而不出現亂碼了。

-------------------------------------------這篇文章說的很到位

近日用Spring3的MVC寫東西,深感其之于Webwork/Struts2的便利,但是在通過@ResponseBody這個annotation

輸出一個json字元串的時候,發現頁面上獲得的json字元串中文字元出現了亂碼的現象。通過firefox觀察傳回的字元串,中文部分全部變成

了???????的形式,初步判定是傳回時,spring處理@ResponseBody使用了錯誤的編碼。

因為我在web.xml中已經配置了Spring的CharacterEncodingFilter,并且強制将request和response的編碼都指定為utf-8,是以出現亂碼的原因肯定是在Spring内部某處的邏輯了。

把log4j中關于spring的輸出級别調為debug,通過通路出問題的位址,發現Spring在處理@ResponseBody這個

annotation的時

候,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter使用了org.springframework.http.converter.StringHttpMessageConverter進行處理,于是打開了Spring的源碼,看看這個類究竟做了哪些事情。

不看不要緊,一看吓一跳,裡面竟然是這樣定義其預設編碼的:

1publicstaticfinalCharset

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

頓時心生N種不爽:堂堂Spring,竟然還在其中用西歐字元集作為其預設編碼,坑爹啊!(很多spring的類中,涉及編碼的已經都是utf-8了,比如負責JSON視圖的MappingJacksonHttpMessageConverter,就是預設使用UTF-8)。本來想直接修改spring的源碼重新打包一個jar出來,後來看spring的java

doc發現,其父類org.springframework.http.converter.AbstractHttpMessageConverter中的getDefaultContentType方法是可以重寫的:

By default, this returns the first element of the

supportedMediaTypes property, if any. Can be overridden in

subclasses.

心想這下就簡單了,你的DEFAULT_CHARSET不是final麼?那我自己繼承一個出來,按照我的需求定義為utf-8不就得了?代碼如下:

01publicclassUTF8StringHttpMessageConverter

extendsStringHttpMessageConverter { 02 03

privatestaticfinalMediaType

utf8 = newMediaType("text", "plain", 04

Charset.forName("UTF-8")); 05

privatebooleanwriteAcceptCharset

= true; 06 07 @Override08

protectedMediaType getDefaultContentType(String

dumy) { 09 returnutf8; 10 } 11 12

protectedList getAcceptedCharsets() { 13

returnArrays.asList(utf8.getCharSet()); 14 } 15 16

protectedvoidwriteInternal(String

s, HttpOutputMessage outputMessage) 17

throwsIOException { 18

if(this.writeAcceptCharset) { 19

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

20 } 21 Charset charset = utf8.getCharSet(); 22

FileCopyUtils.copy(s,

newOutputStreamWriter(outputMessage.getBody(), 23

charset)); 24 } 25 26

publicbooleanisWriteAcceptCharset()

{ 27 returnwriteAcceptCharset; 28 } 29 30

publicvoidsetWriteAcceptCharset(booleanwriteAcceptCharset)

{ 31 this.writeAcceptCharset = writeAcceptCharset;

32 } 33 34}

然後,在spring的配置檔案中添加如下bean聲明,用自己寫的類替換掉原有的StringHttpMessageConverter:

1"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">

2 "messageConverters"> 3 4

"utf8StringHttpMessageConverter"class="xxx.xxx.UTF8StringHttpMessageConverter"/>

5 6 7

再看通過@ResponseBody傳回的json字元串,終于中文都可以正常顯示了。

-------------------------------------------下面有一些解釋

但我們一般會在标注@ResponseBody的方法上傳回String或byte[]類型的結果,期望的"Content-Type"的值應為"text/plain"或"application/octet-stream"。

這樣導緻了浏覽器不能正确處理傳回的内容。

實際上Spring在用HttpMessageConverter處理的過程中首先會判斷response

header中有沒有寫入"Content-Type",如果沒有寫入的話才會使用request

header中"Accept"的第一個值。

但是由于Spring對HttpServletResponse進行了封裝,實際上使用的是ServletServerHttpResponse,這個類有一個對真正的HttpServletResponse的引用。

判斷response

header的過程中使用的是ServletServerHttpResponse的getHeaders()方法,但該方法并沒有傳回真正的HttpServletResponse中的header。(這應該有問題吧?)

是以我們雖然可以在Controller的方法中加入對HttpServletResponse的引用,然後設定"Content-Type"的值,但是并不會起作用。

來處理@ResponseBody,該類再使用一些HttpMessageConverter來具體處理資訊。

Chrome生成的值為application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,**

是以最後寫入response中"Content-Type"的值為"application/xml"或"application/x-ms-application"。

-------------------------------------------------其實這個注解完全可以不用,直接使用response往輸出流裡面寫。

使用jQuery ajax調用的傳回json,中文亂碼問題

Jquery :

$.ajax({

url: '/test/testAction.do?method=test',

type: 'POST',

dataType: 'json',

timeout: 5000,

async: false,

error: function(){

alert('擷取資料失敗!');

},

success: function(json){

jsObject = eval_r(json);

}

});

return jsObject;

JSONArray json =

JSONArray.fromObject(SysList);//SysList是一個List

// 設定response的ContentType解決中文亂碼

response.setContentType("text/html;charset=UTF-8");

response.getWriter().print(json.toString());

return null;