posts - 10, comments - 9, trackbacks - 0, articles - 17

          亂碼問題詳解

          Posted on 2008-12-15 17:09 wesley1987 閱讀(483) 評論(0)  編輯  收藏 所屬分類: struts學(xué)習(xí)項(xiàng)目
          轉(zhuǎn)自網(wǎng)上的一篇很詳細(xì)的關(guān)于servlet中各種出現(xiàn)亂碼的問題即解決方案:
          http://www.diybl.com/course/3_program/java/javajs/200829/99730.html

          (1)前言:
          解決web程序的國際化問題,必須在任何地方使用UTF-8對字符進(jìn)行編碼。(包括:數(shù)據(jù)庫設(shè)置為:UTF-8,web頁面也要設(shè)置為:UTF-8)
          這樣做的好處在于可以解決在web上不止中文字符編碼問題,所有的字符編碼都統(tǒng)一使用UTF-8,實(shí)現(xiàn)了語言的國際化。同時(shí)在保存數(shù)據(jù)到
          數(shù)據(jù)庫時(shí)候也省去了編碼轉(zhuǎn)換的問題。
          在JSP或JSF應(yīng)用中使用到Servlet,我們通過使用Servlet過濾器進(jìn)行編碼轉(zhuǎn)換,也就是制定編碼轉(zhuǎn)換為UFT-8。

          (2)Servlet和JSP過濾器Filter簡介:
          servlet API的2.3版本中最重要的一個(gè)新功能就是能夠?yàn)閟ervlet和JSP頁面定義過濾器。過濾器提供了某些早期服務(wù)器所支持的非標(biāo)準(zhǔn)“servlet鏈接”的一種功能強(qiáng)大且標(biāo)準(zhǔn)的替代品。
          過濾器是一個(gè)程序,它先于與之相關(guān)的servlet或JSP頁面運(yùn)行在服務(wù)器上。過濾器可附加到一個(gè)或多個(gè)servlet或JSP頁面上,并且可以檢查進(jìn)入這些資源的請求信息。在這之后,過濾器可以作如下的選擇:
          - 以常規(guī)的方式調(diào)用資源(即,調(diào)用servlet或JSP頁面)。
          - 利用修改過的請求信息調(diào)用資源。
          - 調(diào)用資源,但在發(fā)送響應(yīng)到客戶機(jī)前對其進(jìn)行修改
          - 阻止該資源調(diào)用,代之以轉(zhuǎn)到其他的資源,返回一個(gè)特定的狀態(tài)代碼或生成替換輸出。
          過濾器提供了幾個(gè)重要好處。
               首先,它以一種模塊化的或可重用的方式封裝公共的行為。你有30個(gè)不同的serlvet或JSP頁面,需要壓縮它們的內(nèi)容以減少下載時(shí)間嗎?沒問題:構(gòu)造一個(gè)壓縮過濾器(參閱第11節(jié)),然后將它應(yīng)用到30個(gè)資源上即可。
              其次,利用它能夠?qū)⒏呒壴L問決策與表現(xiàn)代碼相分離。這對于JSP特別有價(jià)值,其中一般希望將幾乎整個(gè)頁面集中在表現(xiàn)上,而不是集中在業(yè)務(wù)邏輯上。例如,希望阻塞來自某些站點(diǎn)的訪問而不用修改各頁面(這些頁面受到訪問限制)嗎?沒問題:建立一個(gè)訪問限制過濾器(參閱第8節(jié))并把它應(yīng)用到想要限制訪問的頁面上即可。
              最后,過濾器使你能夠?qū)υS多不同的資源進(jìn)行批量性的更改。你有許多現(xiàn)存資源,這些資源除了公司名要更改外其他的保持不變,能辦到么?沒問題:構(gòu)造一個(gè)串替換過濾器(參閱第10節(jié)),只要合適就使用它。
              但要注意,過濾器只在與servlet規(guī)范2.3版兼容的服務(wù)器上有作用。如果你的Web應(yīng)用需要支持舊版服務(wù)器,就不能使用過濾器。
          建立一個(gè)過濾器涉及下列五個(gè)步驟:
          1、建立一個(gè)實(shí)現(xiàn)Filter接口的類。這個(gè)類需要三個(gè)方法,分別是:doFilter、init和destroy。doFilter方法包含主要的過濾代碼,init方法建立設(shè)置操作,而destroy方法進(jìn)行清楚。
          2、在doFilter方法中放入過濾行為。doFilter方法的第一個(gè)參數(shù)為ServletRequest對象。此對象給過濾器提供了對進(jìn)入的信息(包括表單數(shù)據(jù)、cookie和HTTP請求頭)的完全訪問。第二個(gè)參數(shù)為ServletResponse,通常在簡單的過濾器中忽略此參數(shù)。最后一個(gè)參數(shù)為FilterChain,如下一步所述,此參數(shù)用來調(diào)用servlet或JSP頁。
          3、調(diào)用FilterChain對象的doFilter方法。Filter接口的doFilter方法取一個(gè)FilterChain對象作為它的一個(gè)參數(shù)。在調(diào)用此對象的doFilter方法時(shí),激活下一個(gè)相關(guān)的過濾器。如果沒有另一個(gè)過濾器與servlet或JSP頁面關(guān)聯(lián),則servlet或JSP頁面被激活。
          4、對相應(yīng)的servlet和JSP頁面注冊過濾器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素。
          5、禁用激活器servlet。防止用戶利用缺省servlet URL繞過過濾器設(shè)置。

          doFilter方法:

          1 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          2  throws ServletException, IOException
          3 {
          4  HttpServletRequest req = (HttpServletRequest)request;
          5  System.out.println(req.getRemoteHost() + " tried to access " +req.getRequestURL() +" on " + new Date() + ".");
          6  chain.doFilter(request,response);
          7 }


          在web.xml中進(jìn)行部署
          分別是:filter和filter-mapping。filter元素向系統(tǒng)注冊一個(gè)過濾對象,filter-mapping元素指定該過濾對象所應(yīng)用的URL。

          <filter>
          <filter-name>ChangeCodeFilter</filter-name>
          <display-name>ChangeCodeFilter</display-name>
          <description></description>
          <filter-class>com.cnc.SetCharacterEncodingFilter</filter-class>
          </filter>
          <filter-mapping>
          <filter-name>SetCharacterEncodingFilter</filter-name>
          <url-pattern>/SetCharacterEncodingFilter</url-pattern>
          </filter-mapping>

          1.filter元素
          filter元素位于部署描述符文件(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六個(gè)可能的子元素:
           :icon  這是一個(gè)可選的元素,它聲明IDE能夠使用的一個(gè)圖象文件。
           : filter-name  這是一個(gè)必需的元素,它給過濾器分配一個(gè)選定的名字。
           : display-name  這是一個(gè)可選的元素,它給出IDE使用的短名稱。
           : description  這也是一個(gè)可選的元素,它給出IDE的信息,提供文本文檔。
           : filter-class  這是一個(gè)必需的元素,它指定過濾器實(shí)現(xiàn)類的完全限定名。
           : init-param  這是一個(gè)可選的元素,它定義可利用FilterConfig的getInitParameter方法讀取的初始化參數(shù)。單個(gè)過濾器元素可包含多個(gè)init-param元素。
          2.filter-mapping元素
            filter-mapping元素位于web.xml文件中filter元素之后serlvet元素之前。它包含如下三個(gè)可能的子元素::
            filter-name 這個(gè)必需的元素必須與用filter元素聲明時(shí)給予過濾器的名稱相匹配。
            url-pattern  此元素聲明一個(gè)以斜杠(/)開始的模式,它指定過濾器應(yīng)用的URL。所有filter-mapping元素中必須提供url-pattern或servlet-name。但不能對單個(gè)filter-mapping元素提供多個(gè)url-pattern元素項(xiàng)。如果希望過濾器適用于多個(gè)模式,可重復(fù)整個(gè)filter-mapping元素。
          :servlet-name  此元素給出一個(gè)名稱,此名稱必須與利用servlet元素給予servlet或JSP頁面的名稱相匹配。不能給單個(gè)filter-mapping元素提供多個(gè)servlet-name元素項(xiàng)。如果希望過濾器適合于多個(gè)servlet名,可重復(fù)這個(gè)filter-mapping元素。

          (3)在Rational Application Developer 中的建立字符轉(zhuǎn)換過濾器:
          1.新建-web-過濾器:SetCharacterEncodingFilter
          會在web.xml中產(chǎn)生如上代碼:

          2.在過濾器的doFilter方法中添加如下代碼:

          public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException {
            arg0.setCharacterEncoding(
          "UTF-8"); //設(shè)定字體編碼為UTF-8
            arg2.doFilter(arg0, arg1);// 傳遞控制到下一個(gè)過濾器
           }

          3.在web.xml中進(jìn)行部署
          在web.xml的過濾器-編輯器中選擇:servlet 映射 - 添加 - Faces Servlet
          會在web.xml中產(chǎn)生如下代碼:
          <filter-mapping>
          <filter-name>SetCharacterEncodingFilter</filter-name>
          <servlet-name>Faces Servlet</servlet-name>
          </filter-mapping>

          (4)其他參考信息
          tomcat下中文的徹底解決
          (一)    JSP頁面上是中文,但是看的是后是亂碼:
          解決的辦法就是在JSP頁面的編碼的地方<%@ page language="java" contentType="text/html;charset=GBK" %>,因?yàn)镴sp轉(zhuǎn)成Java文件時(shí)的編碼問題,默認(rèn)的話有的服務(wù)器是ISO-8859-1,如果一個(gè)JSP中直接輸入了中文,Jsp把它當(dāng)作ISO8859-1來處理是肯定有問題的,這一點(diǎn),我們可以通過查看Jasper所生成的Java中間文件來確認(rèn)
          (二)    當(dāng)用Request對象獲取客戶提交的漢字代碼的時(shí)候,會出現(xiàn)亂碼:
          解決的辦法是:要配置一個(gè)filter,也就是一個(gè)Servelet的過濾器,代碼如下:

          import java.io.IOException;
          import javax.servlet.Filter;
          import javax.servlet.FilterChain;
          import javax.servlet.FilterConfig;
          import javax.servlet.ServletException;
          import javax.servlet.ServletRequest;
          import javax.servlet.ServletResponse;
          import javax.servlet.UnavailableException;
          /**
           * Example filter that sets the character encoding to be used in parsing the
           * incoming request
           
          */
          public class SetCharacterEncodingFilter implements Filter {
              
          /**
               * Take this filter out of service.
               
          */
              
          public void destroy() {
              }
              
          /**
               * Select and set (if specified) the character encoding to be used to
               * interpret request parameters for this request.
               
          */
              
          public void doFilter(ServletRequest request, ServletResponse response,
              FilterChain chain)
          throws IOException,ServletException {
              request.setCharacterEncoding(
          "GBK");
              
          // 傳遞控制到下一個(gè)過濾器
              chain.doFilter(request, response);
              }
              
          public void init(FilterConfig filterConfig) throws ServletException {
              }
          }

           

           

          配置web.xml

          <
          filter>
          <filter-name>Set Character Encoding</filter-name>
          <filter-class>SetCharacterEncodingFilter</filter-class>
          </filter>
          <filter-mapping>
          <filter-name>Set Character Encoding</filter-name>
          <url-pattern>/*</url-pattern>
          </filter-mapping>

          如果你的還是出現(xiàn)這種情況的話你就往下看看是不是你出現(xiàn)了第四中情況,你的Form提交的數(shù)據(jù)是不是用get提交的,一般來說用post提交的話是沒有問題的,如果是的話,你就看看第四中解決的辦法。
          還有就是對含有漢字字符的信息進(jìn)行處理,處理的代碼是:
          package dbJavaBean;
          public class CodingConvert
          {  
           public CodingConvert()
           {
            //
           }
           public String toGb(String uniStr){
               String gbStr = "";
               if(uniStr == null){
             uniStr = "";
               }
               try{
             byte[] tempByte = uniStr.getBytes("ISO8859_1");
             gbStr = new String(tempByte,"GB2312");
               }
            catch(Exception ex){
              }
               return gbStr;
           }
            
           public String toUni(String gbStr){
               String uniStr = "";
               if(gbStr == null){
             gbStr = "";
               }
               try{
             byte[] tempByte = gbStr.getBytes("GB2312");
             uniStr = new String(tempByte,"ISO8859_1");
               }catch(Exception ex){
              }
              return uniStr;
           }
          }
          你也可以在直接的轉(zhuǎn)換,首先你將獲取的字符串用ISO-8859-1進(jìn)行編碼,然后將這個(gè)編碼存放到一個(gè)字節(jié)數(shù)組中,然后將這個(gè)數(shù)組轉(zhuǎn)化成字符串對象就可以了,例如:
          String str=request.getParameter(“girl”);
          Byte B[]=str.getBytes(“ISO-8859-1”);
          Str=new String(B);
          通過上述轉(zhuǎn)換的話,提交的任何信息都能正確的顯示。
          (三)    在Formget請求在服務(wù)端用request. getParameter(“name”)時(shí)返回的是亂碼;按tomcat的做法設(shè)置Filter也沒有用或者用request.setCharacterEncoding("GBK");也不管用問題是出在處理參數(shù)傳遞的方法上:如果在servlet中用doGet(HttpServletRequest request, HttpServletResponse response)方法進(jìn)行處理的話前面即使是寫了:
          request.setCharacterEncoding("GBK");
          response.setContentType("text/html;charset=GBK");
          也是不起作用的,返回的中文還是亂碼!!!如果把這個(gè)函數(shù)改成doPost(HttpServletRequest request, HttpServletResponse response)一切就OK了。
          同樣,在用兩個(gè)JSP頁面處理表單輸入之所以能顯示中文是因?yàn)橛玫氖莗ost方法傳遞的,改成get方法依舊不行。
          由此可見在servlet中用doGet()方法或是在JSP中用get方法進(jìn)行處理要注意。這畢竟涉及到要通過瀏覽器傳遞參數(shù)信息,很有可能引起常用字符集的沖突或是不匹配。
          解決的辦法是:
          1) 打開tomcat的server.xml文件,找到區(qū)塊,加入如下一行:
          URIEncoding=”GBK”
          完整的應(yīng)如下:
          <Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK"/>
          2)重啟tomcat,一切OK。
          需要加入的原因大家可以去研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html下的這個(gè)文件就可以知道原因了。需要注意的是:這個(gè)地方如果你要是用UTF-8的時(shí)候在傳遞的過程中在Tomcat中也是要出現(xiàn)亂碼的情況,如果不行的話就換別的字符集。
          (四)    JSP頁面上有中文,按鈕上面也有中文,但是通過服務(wù)器查看頁面的時(shí)候出現(xiàn)亂碼:
               解決的辦法是:首先在JSP文件中不應(yīng)該直接包含本地化的消息文本,而是應(yīng)該通過<bean:message>標(biāo)簽從Resource Bundle中獲得文本。應(yīng)該把你的中文文本放到Application.properties文件中,這個(gè)文件放在WEB-INF/classes/*下,例如我在頁面里有姓名,年齡兩個(gè)label,我首先就是要建一個(gè)Application.properties,里面的內(nèi)容應(yīng)該是name=”姓名” age=”年齡”,然后我把這個(gè)文件放到WEB-INF/classes/properties/下,接下來根據(jù)Application.properties文件,對他進(jìn)行編碼轉(zhuǎn)化,創(chuàng)建一個(gè)中文資源文件,假定名字是Application_cn.properties。在JDK中提供了native2ascii命令,他能夠?qū)崿F(xiàn)字符編碼的轉(zhuǎn)換。在DOS環(huán)境中找到你放置Application.properties的這個(gè)文件的目錄,在DOS環(huán)境中執(zhí)行一下命令,將生成按GBK編碼的中文資源文件Application_cn.properties:native2ascii ?encoding gbk Application.properties Application_cn.properties執(zhí)行以上命令以后將生成如下內(nèi)容的Application_cn.properties文件:name=\u59d3\u540d age=\u5e74\u9f84,在Struts-config.xml中配置:<message-resources parameter="properties.Application_cn"/>。到這一步,基本上完成了一大半,接著你就要在JSP頁面上寫<%@ page language="java" contentType="text/html;charset=GBK" %>,到名字的那個(gè)label是要寫<bean:message key=”name”>,這樣的化在頁面上出現(xiàn)的時(shí)候就會出現(xiàn)中文的姓名,年齡這個(gè)也是一樣,按鈕上漢字的處理也是同樣的。
          (五)    寫入到數(shù)據(jù)庫是亂碼:
          解決的方法:要配置一個(gè)filter,也就是一個(gè)Servelet的過濾器,代碼如同第二種時(shí)候一樣。
          如果你是通過JDBC直接鏈接數(shù)據(jù)庫的時(shí)候,配置的代碼如下:jdbc:mysql://localhost:3306/workshopdb?useUnicode=true&characterEncoding=GBK,這樣保證到數(shù)據(jù)庫中的代碼是不是亂碼。
          如果你是通過數(shù)據(jù)源鏈接的化你不能按照這樣的寫法了,首先你就要寫在配置文件中,在tomcat 5.0.19中配置數(shù)據(jù)源的地方是在C:\Tomcat 5.0\conf\Catalina\localhost這個(gè)下面,我建立的工程是workshop,放置的目錄是webapp下面,workshop.xml的配置文件如下:
          <!-- insert this Context element into server.xml -->
          <Context path="/workshop" docBase="workshop" debug="0"
          reloadable="true" >
            <Resource name="jdbc/WorkshopDB"
                         auth="Container"
                         type="javax.sql.DataSource" />
            <ResourceParams name="jdbc/WorkshopDB">
              <parameter>
                <name>factory</name>
                <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
              </parameter>
              <parameter>
                <name>

          maxActive</name>
                <value>100</value>
              </parameter>
              <parameter>
                <name>maxIdle</name>
                <value>30</value>
              </parameter>
             
              <parameter>
                <name>maxWait</name>
                <value>10000</value>
              </parameter>
                <parameter>
               <name>username</name>
               <value>root</value>
              </parameter>
              <parameter>
               <name>password</name>
               <value></value>
              </parameter>
              <!-- Class name for mm.mysql JDBC driver -->
              <parameter>
                 <name>driverClassName</name>
                 <value>com.mysql.jdbc.Driver</value>
          </parameter>
             <parameter>
                <name>url</name>
           <value><![CDATA[jdbc:mysql://localhost:3306/workshopdb?useUnicode=true&characterEncoding=GBK]]></value>
              </parameter>
            </ResourceParams>
          </Context>
          粗體的地方要特別的注意,和JDBC直接鏈接的時(shí)候是有區(qū)別的,如果你是配置正確的化,當(dāng)你輸入中文的時(shí)候到數(shù)據(jù)庫中就是中文了,有一點(diǎn)要注意的是你在顯示數(shù)據(jù)的頁面也是要用<%@ page language="java" contentType="text/html;charset=GBK" %>這行代碼的。需要注意的是有的前臺的人員在寫代碼的是后用Dreamver寫的,寫了一個(gè)Form的時(shí)候把他改成了一個(gè)jsp,這樣有一個(gè)地方要注意了,那就是在Dreamver中Action的提交方式是request的,你需要把他該過來,因?yàn)樵趈sp的提交的過程中緊緊就是POST和GET兩種方式,但是這兩種方式提交的代碼在編碼方面還是有很大不同的,這個(gè)在后面的地方進(jìn)行說明.


          文章出處:http://www.diybl.com/course/3_program/java/javajs/200829/99730_3.html

          主站蜘蛛池模板: 丰镇市| 洛宁县| 白水县| 平舆县| 蓬安县| 喀喇| 华坪县| 盖州市| 日照市| 上林县| 永年县| 武城县| 鄯善县| 宁安市| 绍兴县| 巴中市| 保靖县| 望城县| 田阳县| 资溪县| 兰西县| 红桥区| 汽车| 拉孜县| 洞口县| 建始县| 兰西县| 开江县| 深州市| 陇西县| 嫩江县| 丰台区| 嘉禾县| 江陵县| 福贡县| 绍兴市| 来宾市| 富宁县| 澜沧| 秀山| 巢湖市|