Jsp中文編碼問題(上)

來源:互聯網
上載者:User

摘要:

  本文首先介紹了一個JSP的源檔案執行過程,即需要經過三個階段,兩次編碼,才能完成一次完整的輸出。特別需要注意的是,在這個過程中,編碼問題貫穿始終。我們知道在JSP/Servlet中,主要有以下四種方式可以設定編碼,即 pageEncoding、contentType、request.setCharacterEncoding 和 response.setCharacterEncoding,在本文中,我們就這四種方式進行深入的介紹和總結。 一. JSP的執行過程與編碼設定概述

  在JSP/Servlet中,主要有以下四種方式可以設定編碼,其中前兩個只能應用於JSP中,而後兩個可以用於 JSP 和 Servlet 中。 pageEncoding=”UTF-8”; contentType=”text/html;charset=UTF-8; request.setCharacterEncoding(“UTF-8”) ; response.setCharacterEncoding(“UTF-8”)。

  pageEncoding是jsp檔案本身的編碼;contentType的charset是指伺服器發送給用戶端時的內容編碼;

  JSP要經過兩次的“編碼”,第一階段會用pageEncoding,第二階段會用utf-8至utf-8,第三階段就是由Tomcat出來的網頁, 用的是contentType。

  事實上,一個JSP的源檔案需要經過三個階段,兩次編碼,才能完成一次完整的輸出,這三個階段是:

  第一階段:轉譯(.jsp -> .Java;pageEncoding -> UTF-8)。將jsp編譯成Servlet(.java)檔案,用到的指令是pageEncoding。在編譯過程中,根據pageEncoding=“XXX”的指示,找到編碼的規則為“XXX”,然後伺服器將JSP檔案編譯成.java檔案時會根據pageEncoding的設定讀取jsp,結果是由指定的編碼方案翻譯成統一的UTF-8編碼的JAVA源碼(即.java)。

  第二階段:編譯(.java -> .class;UTF-8 -> UTF-8)。從Servlet檔案(.java)到Java位元組碼檔案(.class),從UTF-8到UTF-8。在這一階段中,不論JSP編寫時候用的是什麼編碼方案,經過這個階段的結果全部是UTF-8的encoding的java源碼。JAVAC用UTF-8的encoding讀取java源碼,編譯成UTF-8編碼的二進位碼(即.class),這是JVM對常數字串在二進位碼(Java encoding)內表達的規範。這一過程是由JVM的內在規範決定的,不受外界控制。

  第三階段:是Tomcat(或其他container)載入和執行階段二的Java二進位碼,輸出的結果到用戶端的(UTF-8 -> contentType)過程。從伺服器到瀏覽器,在這一過程中用到的指令是contentType。伺服器載入和執行由第二階段產生出來JAVA二進位碼,輸出的結果,也就是在用戶端可見到的結果,在這次輸出過程中,由contentType屬性中的charset來指定,將UTF8形式的二進位碼以charset的編碼形式來輸出。如果沒有人為設定,則預設的是ISO-8859-1的形式。

  特別需要注意的是,pageEncoding 的預設值是 “ISO-8859-1”, contentType 的預設值是 “text/html;ISO-8859-1”。

  注意: 第一、三兩個階段的轉碼個人感覺聯想到Sting轉碼更容易理解些,例如 :new String(name.getBytes(“ISO-8859-1”), “utf-8”)。 二. pageEncoding=”UTF-8”

  pageEncoding=”UTF-8” 的作用是設定JSP編譯成Servlet時使用的編碼。通常,在JSP內部定義的字串(直接在JSP中定義,而不是從瀏覽器提交的資料)出現亂碼時,很多都是由於該參數設定錯誤引起的。例如,你的 JSP檔案中含有中文字元,而在JSP中卻指定pageEncoding=”iso-8859-1”,就會導致中文字元顯示異常。看下面的例子:

<%@ page language="java" pageEncoding="iso-8859-1" import="java.util.*" %><html>  <head>    <title>哈哈</title>  </head>  <body>     中文 <br>  </body></html>                                

在其編譯為Servlet後,其源碼(片段)如下所示:

public void _jspService(HttpServletRequest request, HttpServletResponse response)        throws java.io.IOException, ServletException {      // ...      out.write("<html>\r\n");      out.write("  <head>\r\n");      out.write("    <title>哈哈</title>\r\n");      out.write("  </head>\r\n");      out.write("  <body>\r\n");      out.write("   \t 中文 <br>\r\n");      out.write("  </body>\r\n");      out.write("</html>\r\n");      // ...                                

訪問該頁面,頁面顯示如下:

               

  我們可以看到,由於pageEncoding被指定為”iso-8859-1”,導致其在由伺服器將JSP檔案編譯成.java檔案過程中,在使用“iso-8859-1”讀取jsp並翻譯成統一的UTF-8編碼的JAVA源碼時,所有的中文字元被轉成亂碼,並使得其呈現給使用者的響應也包含亂碼。特別地,該屬性還有一個功能,就是在JSP中不指定contentType參數,也不使用response.setCharacterEncoding方法時,指定對伺服器響應的內容進行編碼。 二. contentType=”text/html;charset=UTF-8”

  contentType=”text/html;charset=UTF-8” 的作用是將上述第二階段所產生的UTF8形式的二進位碼以charset的編碼形式來輸出到用戶端,如果設定不當的話,會出現亂碼。看下面的例子:

<%@ page language="java" contentType="text/html;iso-8859-1" import="java.util.*"     pageEncoding="utf-8"%><html>  <head>    <title>哇哈哈</title>  </head>  <body>     哇哈哈 <br>  </body></html>                                

在其編譯為Servlet後,其源碼(片段)如下所示:

public void _jspService(HttpServletRequest request, HttpServletResponse response)        throws java.io.IOException, ServletException {      // ...      out.write("<html>\r\n");      out.write("  <head>\r\n");      out.write("    <title>哇哈哈</title>\r\n");      out.write("  </head>\r\n");      out.write("  <body>\r\n");      out.write("   \t 哇哈哈 <br>\r\n");      out.write("  </body>\r\n");      out.write("</html>\r\n");      // ...                                

訪問該頁面,頁面顯示如下:

                三. request.setCharacterEncoding(“UTF-8”)

  request.setCharacterEncoding(“UTF-8”)用來指定對瀏覽器發送來的資料以特定的字元集進行重新編碼,常用於對 POST 請求參數進行解碼。具體見下一個部落格 JSP中文編碼問題(下)中 “POST 請求的請求參數為中文情形” 一節。 四. response.setCharacterEncoding(“UTF-8”)

  response.setCharacterEncoding(“UTF-8”)的作用是:在伺服器將響應返回到瀏覽器前,對響應使用指定字元集進行重新編碼。一旦使用了該種方式,即使該響應頁面指定了具體的 contentType,也將失效,即response.setCharacterEncoding()方法會覆蓋contentType的值。看下面的例子:

<%@ page language="java" contentType="text/html;iso-8859-1" import="java.util.*"     pageEncoding="utf-8"%><html>  <head>    <title>哇哈哈</title>  </head>  <body>     哇哈哈 <br>  </body></html>                                

在其編譯為Servlet後,其源碼(片段)如下所示:

public void _jspService(HttpServletRequest request, HttpServletResponse response)        throws java.io.IOException, ServletException {      response.setCharacterEncoding("UTF-8")      // ...      out.write("<html>\r\n");      out.write("  <head>\r\n");      out.write("    <title>哇哈哈</title>\r\n");      out.write("  </head>\r\n");      out.write("  <body>\r\n");      out.write("   \t 哇哈哈 <br>\r\n");      out.write("  </body>\r\n");      out.write("</html>\r\n");      // ...                                

訪問該頁面,頁面顯示如下:

                五. 四種編碼設定方式之間的相互影響以及作用的優先順序

  根據上文內容,我們得出以下三點:

在指定JSP編譯成Servlet時使用的編碼時,優先順序為: pageEncoding=”UTF-8” > contentType=”text/html;charset=UTF-8”

在指定伺服器對響應內容的編碼時,優先順序為:response.setCharacterEncoding(“UTF-8”) > contentType=”text/html;charset=UTF-8” > pageEncoding=”UTF-8”

request.setCharacterEncoding(“UTF-8”) 只用來指定對瀏覽器發送來的請求資料的解碼方式。

  本文內容轉自: JSP中文亂碼問題終極解決方案(上)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.