轉:resin3.1處理utf-8格式的jsp時存在的問題

來源:互聯網
上載者:User

轉自: http://cnxiaowei.javaeye.com/blog/262766

 

 

今天要發布一個N久以前做過的項目, 要用Resin(題外話:現在基本已經拋棄Resin, 用Tomcat為主了)遇到了同樣的問題, 原因就是這篇文章裡面描述的UTF-8 BOM問題. 

 

一下是原文:

===================================================================================

 

以前一直使用resin-3.0.x作為伺服器,最近想升級到resin3.1,於是在官網上下載了resin3.1.7a,解壓配置一切正常,但把應用重新部署上去的時候就出了問題,以前一直正常的頁面,現在卻報錯:

 

500 Servlet Exception

 

<script type="text/javascript"></script>[show] /index.jsp:1: contentType 'text/vnd.wap.wml; charset=utf-8' conflicts withprevious value of contentType 'text/html; charset=UTF-8'.  Check the .jspand any included .jsp files for conflicts.1:  <%@page contentType="text/vnd.wap.wml; charset=utf-8"%>2:  <%@page import="java.util.*"%>3:  <%!

 

 

    根據上面的提示,意思似乎是我在jsp裡面第一行設定的contentType是'text/vnd.wap.wml; charset=utf-8,和前面設定的'text/html; charset=UTF-8'不同導致衝突,但這個檔案的第一行就是<%@page contentType="text/vnd.wap.wml;charset=utf-8" %>,根本沒有設定過'text/html; charset=UTF-8',這個提示真是讓人很摸不著頭腦。

    後來想到可能是UTF8檔案格式的問題,就用UE開啟檔案,另存了一次,選的是不帶BOM的UTF8格式的檔案,這次就可以正常顯示了。但伺服器上那麼多檔案,不可能一個一個的改,還得想其他的辦法解決。在網上找了很久都沒有任何頭緒,似乎遇到這個問題的人很少。

    最後實在是沒辦法,只好把原始碼下載下來研究一下看了,還真的找出了原因所在。

    因為resin在處理jsp檔案的時候,會首先讀取前面的幾個位元組來判斷檔案的格式,如果第一個位元組是0xef、第二個位元組是0xbb、第三個位元組是0xbf,那麼就認為這個檔案是UTF8格式,於是就自作主張的把ContentType設定成了text/html; charset=UTF-8,然後在後面的處理過程中,因為jsp程式裡面會有設定ContentType的指令,遇到這個指令會發現和之前的text/html; charset=UTF-8不同,因此就拋出了異常。而如果沒有BOM格式的UTF8,前面就不會有那三個位元組的標識,所以就不會被處理了。

    相關代碼:

Java代碼 
  1.    case 0xef:  
  2.      if ((ch = stream.read()) != 0xbb) {  
  3. stream.unread();  
  4. stream.unread();  
  5.      }  
  6.      else if ((ch = stream.read()) != 0xbf) {  
  7. throw error(L.l("Expected 0xbf in UTF-8 header.  UTF-8 pages with the initial byte 0xbb expect 0xbf immediately following.  The 0xbb 0xbf sequence is used by some application to suggest UTF-8 encoding without a directive."));  
  8.      }  
  9.      else {  
  10. _parseState.setContentType("text/html; charset=UTF-8");  
  11. _parseState.setPageEncoding("UTF-8");  
  12. stream.setEncoding("UTF-8");  
  13.      }  
  14.      break;  

 

    判斷衝突的代碼:

 

Java代碼 
  1. else if (CONTENT_TYPE.equals(name)) {  
  2.     String oldContentType = _parseState.getContentType();  
  3.       
  4.     if (oldContentType != null && ! value.equals(oldContentType))  
  5.       throw error(L.l("contentType '{0}' conflicts with previous value of contentType '{1}'.  Check the .jsp and any included .jsp files for conflicts.", value, oldContentType));  
  6.       
  7.     _parseState.setContentType(value);  
  8.     String charEncoding = parseCharEncoding(value);  
  9.     if (charEncoding != null)  
  10. parseState.setCharEncoding(charEncoding);  
  11.   }  

 

真不明白為什麼resin要這麼做呢,如果是web網站可能影響不大,contentType本來就是text/html,但如果是wap或者其他contentType的網站這麼“智能”的編碼判斷方式問題就比較麻煩了。

 

 

附:UTF-8 編碼的檔案可以分為no BOM 和 BOM兩種格式(轉載)

何謂BOM? "EF BB BF" 這三個位元組就叫BOM,BOM的全稱叫做"Byte Order Mard".在utf-8檔案中常用BOM來表明這個檔案是UTF-8檔案,而BOM的本意實在utf16中用來表示高低位元組序列的。
在位元組流之前有BOM表示採用低位元組序列(低位元組在前面),而utf8不用考慮位元組序列,所以其實有無BOM都可以。

微軟的記事本 Word 等只能正確開啟含BOM的UTF8檔案,然後UltraEdit卻恰恰相反,回把BOMutf8檔案 誤認為ascii編碼。

UTF-8的BOM是 EFBBBF,因為UE載入UTF-8檔案會轉成Utf16,上述的EFBBBF 在Utf16中是FFFE(Unicode-LE的BOM),UltraEdit不認識BOM又加多一個BOM,所以有2個FFFE。
檔案就被它破壞了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.