1. 程式人生 > >Web中文亂碼——1、SpringMVC+Jetty編解碼基礎

Web中文亂碼——1、SpringMVC+Jetty編解碼基礎

        我們部門的web專案常用的是spring+jetty。在編解碼過程中,spring本身不會進行干預,而jetty也干預減少。因此,我們從瀏覽器和Servlet之間的互動入手,來看Spring+jetty專案的編解碼過程。

        瀏覽器和Servlet之間的互動過程如下圖所示,主要分成4個部分。


一、瀏覽器傳送請求

        瀏覽器傳送的請求引數會進行URL encode。URL encode區別於encode的主要特點是:前者對中文編碼後會帶百分號。詳細的請各位google吧。

1、表單遞交

        表單遞交時,瀏覽器採用的編碼由header中的Content-type決定,例如在快門中是:

<metacharset="Content-type: application/x-www-form-urlencoded;charset=UTF-8" />
        當沒有指定Content-type時,瀏覽器預設採用ISO-8859-1進行URL encode。

2、Javascript

        IE總是採用作業系統的預設編碼來進行編碼,而Firefox/chrome總是採用utf-8編碼。

二、Servlet接收請求

        Servlet收到請求時,會對其中的引數進行URL decode。Serlvet的行為是受應用伺服器影響的,在使用Jetty時如下。

1、Get請求

        由Jetty決定,可以設定JVM引數org.eclipse.jetty.util.URI.charset,預設是UTF-8。

2、Post請求

        和Jetty無關。在獲取引數值之前,通過HttpServletRequest.setCharacterEncoding(charset)來設定字符集,但必須在第一次呼叫request.getParameter()前設定。若沒設定,則預設ISO-8859-1。

三、Servlet傳送響應

        Servlet傳送的響應時,響應內容自然是java自己定製的,可以是任意字符集。但無論如何,它需要把自己的編碼方式告訴瀏覽器,以便對方正確解析。

3.1、html

        那麼,對於html頁面響應,只需要設定頁面header中的Content-type,預設為ISO-8859-1。
<metacharset="Content-type: application/x-www-form-urlencoded;charset=UTF-8" />

3.2、VM

        velociy頁面最終也相當於是一個html頁面。因此首先也需要設定正確的Content-type,方法和上面一致。

        除此之外,還需要注意velocity本身的編碼設定。

<bean id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
	<property name="resourceLoaderPath">
		<value>WEB-INF/view</value>
	</property>
	<property name="velocityProperties">
		<props>
			<prop key="input.encoding">utf-8</prop>
			<prop key="output.encoding">utf-8</prop>
			<!--<prop key="eventhandler.referenceinsertion.class">org.apache.velocity.app.event.implement.EscapeHtmlReference</prop>-->
		</props>
	</property>
</bean>

        如上所示,input.encoding用於指定Java讀取vm時採用的字符集;而output.encoding用於指定Java將vm輸出到瀏覽器時採用的字符集。

3.3、Java write

        如果直接用HttpServletResponse.getWriter.write(),那就需要採用如下方式來設值

HttpServletResponse.setContentType(“text/html; charset=GBK”)
        在Servlet2.4以後,還可以採用如下方式
HttpServletResponse.setCharacterEncoding(charset)

四、瀏覽器接收響應

        瀏覽器收到響應時,會根據header中的Content-type來decode,預設為ISO-8859-1

五、推薦配置

        當然是推薦在上述可配置的地方全部配置成相同的編碼,比如:UTF-8。

        但即使如此,亂碼還是有可能發生。發生亂碼的各種情形請參考下一篇《Web中文亂碼——2、SpringMVC+Jetty 亂碼

參考:
http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
http://blog.csdn.net/chenyongsuda/article/details/5393458