struts2構建網站的國際化問題解決

一、字符集和編碼設置

數據庫採用8859-1的字符集存儲。

jsp頁面:
<%@ page language="java" contentType="text/html; charset=8859_1"%>


struts2的struts.properties設置:struts.i18n.encoding=8859_1

web.xml的過濾器也設置過。用org.springframework.web.filter.CharacterEncodingFilter過濾器。

二、現象

錄入中文正常。

顯示中文有的Struts2標籤有亂碼,有的標籤正常顯示。具體如下:
1、s:property標籤通過設置escape="false"能正常顯示中文,否則亂碼。
property value="label" escape="false"/>
2、s:select s:checkboxlist標籤能正常顯示中文
3、s:textfield 標籤接收中文顯示亂碼。


注:action裏面直接用值棧的方式傳遞到jsp。沒用用session,request。
在之前的一個struts1的項目中採用同樣的數據庫和設置方式,能正常顯示和處理中文。
如果設置都換成utf-8編碼則數據庫中原有的數據還要改變編碼,而還有另一個系統要用到這裏面的數據,故不能採用。

我想難道是struts2標籤有問題。

三、可能的解決方案
1. struts2的struts.properties設置:struts.i18n.encoding= ******

2. 使用的數據庫的字符集: iso-8859-1 ,在處理java代碼時,對所有的含中文 配置文件其編碼都是iso-8859-1 ,
java 代碼編譯時 -encoding "ISO8859-1" 。這樣在使用struts2 時 就出現了亂碼,主要是 <s:property 標籤,經過對struts2源碼的分析該標籤輸出時默認對輸出內容做了htmlEncode 操作。
解決該問題:
1 將默認的執行 htmlEncode 操作,改爲對輸出內容不進行htmlEncode操作:
struts2-core-2.0.6 中 :
package org.apache.struts2.components ;
Property.java 中的
private boolean escape = true;
改爲:
private boolean escape = false;

其次,將prepare 方法改爲:

Java代碼
    private String prepare(String value) {  
            if (escape) {  
                return TextUtils.htmlEncode(value,false);  
             } else {  
                return value;  
             }  
         }   

Java代碼 複製代碼 收藏代碼

    private String prepare(String value) {  
            if (escape) {  
                return TextUtils.htmlEncode(value,false);  
            } else {  
                return value;  
            }  
        }  



struts2-core-2.1.6 中:
package org.apache.struts2.components
將 Property.java 中的
private boolean escape = true;
改爲:
private boolean escape = false;

其次,將prepare 方法改爲:
Java代碼

    private String prepare(String value) {  
             String result = value;  
            if (escape) {  
                 result = TextUtils.htmlEncode(result,false);  
             }  
            if (escapeJavaScript) {  
                 result = TextUtils.escapeJavaScript(result);  
             }  
            return result;  
         }   

Java代碼 複製代碼 收藏代碼

    private String prepare(String value) {  
         String result = value;  
            if (escape) {  
             result = TextUtils.htmlEncode(result,false);  
            }  
            if (escapeJavaScript) {  
             result = TextUtils.escapeJavaScript(result);  
            }  
            return result;  
        } 

private String prepare(String value) {
     String result = value;
        if (escape) {
         result = TextUtils.htmlEncode(result,false);
        }
        if (escapeJavaScript) {
         result = TextUtils.escapeJavaScript(result);
        }
        return result;
    }


再其次:
package org.apache.struts2.views.jsp;
將 PropertyTag.java 中的
private boolean escape = true;
改爲:
private boolean escape = false;

這樣就OK了~!

進一步說明: 對於需要使用 htmlEncode 的時候,那麼就使用 <s:property 標籤的 escape="true" (防止用戶在輸入內容時頁面出現js注入錯誤)
但是以上的修改方法還是有一個問題:我們來看看xwork-2.1.2 中的
package com.opensymphony.xwork2.util;
TextUtils.java
Java代碼
    public final static String htmlEncode(String s) {  
           return htmlEncode(s, true);  
        }  
      
       /**
         * Escape html entity characters and high characters (eg "curvy" Word quotes).
         * Note this method can also be used to encode XML.
         * @param s the String to escape.
         * @param encodeSpecialChars if true high characters will be encode other wise not.
         * @return the escaped string
         */  
       public final static String htmlEncode(String s, boolean encodeSpecialChars) {  
            s = noNull(s);  
      
            StringBuilder str = new StringBuilder();  
      
           for (int j = 0; j < s.length(); j++) {  
               char c = s.charAt(j);  
      
               // encode standard ASCII characters into HTML entities where needed  
               if (c < '\200') {  
                   switch (c) {  
                   case '"':  
                        str.append("&quot;");  
      
                       break;  
      
                   case '&':  
                        str.append("&amp;");  
      
                       break;  
      
                   case '<':  
                        str.append("&lt;");  
      
                       break;  
      
                   case '>':  
                        str.append("&gt;");  
      
                       break;  
      
                   default:  
                        str.append(c);  
                    }  
                }  
               // encode 'ugly' characters (ie Word "curvy" quotes etc)  
               else if (encodeSpecialChars && (c < '\377')) {  
                    String hexChars = "0123456789ABCDEF";  
                   int a = c % 16;  
                   int b = (c - a) / 16;  
                    String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);  
                    str.append("&#x" + hex + ";");  
                }  
               //add other characters back in - to handle charactersets  
               //other than ascii  
               else {  
                    str.append(c);  
                }  
            }  
      
           return str.toString();  
        }   

Java代碼 複製代碼 收藏代碼

    public final static String htmlEncode(String s) {  
            return htmlEncode(s, true);  
        }  
      
        /**
         * Escape html entity characters and high characters (eg "curvy" Word quotes).
         * Note this method can also be used to encode XML.
         * @param s the String to escape.
         * @param encodeSpecialChars if true high characters will be encode other wise not.
         * @return the escaped string
         */  
        public final static String htmlEncode(String s, boolean encodeSpecialChars) {  
            s = noNull(s);  
      
            StringBuilder str = new StringBuilder();  
      
            for (int j = 0; j < s.length(); j++) {  
                char c = s.charAt(j);  
      
                // encode standard ASCII characters into HTML entities where needed  
                if (c < '\200') {  
                    switch (c) {  
                    case '"':  
                        str.append("&quot;");  
      
                        break;  
      
                    case '&':  
                        str.append("&amp;");  
      
                        break;  
      
                    case '<':  
                        str.append("&lt;");  
      
                        break;  
      
                    case '>':  
                        str.append("&gt;");  
      
                        break;  
      
                    default:  
                        str.append(c);  
                    }  
                }  
                // encode 'ugly' characters (ie Word "curvy" quotes etc)  
                else if (encodeSpecialChars && (c < '\377')) {  
                    String hexChars = "0123456789ABCDEF";  
                    int a = c % 16;  
                    int b = (c - a) / 16;  
                    String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);  
                    str.append("&#x" + hex + ";");  
                }  
                //add other characters back in - to handle charactersets  
                //other than ascii  
                else {  
                    str.append(c);  
                }  
            }  
      
            return str.toString();  
        } 

public final static String htmlEncode(String s) {
        return htmlEncode(s, true);
    }

    /**
     * Escape html entity characters and high characters (eg "curvy" Word quotes).
     * Note this method can also be used to encode XML.
     * @param s the String to escape.
     * @param encodeSpecialChars if true high characters will be encode other wise not.
     * @return the escaped string
     */
    public final static String htmlEncode(String s, boolean encodeSpecialChars) {
        s = noNull(s);

        StringBuilder str = new StringBuilder();

        for (int j = 0; j < s.length(); j++) {
            char c = s.charAt(j);

            // encode standard ASCII characters into HTML entities where needed
            if (c < '\200') {
                switch (c) {
                case '"':
                    str.append("&quot;");

                    break;

                case '&':
                    str.append("&amp;");

                    break;

                case '<':
                    str.append("&lt;");

                    break;

                case '>':
                    str.append("&gt;");

                    break;

                default:
                    str.append(c);
                }
            }
            // encode 'ugly' characters (ie Word "curvy" quotes etc)
            else if (encodeSpecialChars && (c < '\377')) {
                String hexChars = "0123456789ABCDEF";
                int a = c % 16;
                int b = (c - a) / 16;
                String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);
                str.append("&#x" + hex + ";");
            }
            //add other characters back in - to handle charactersets
            //other than ascii
            else {
                str.append(c);
            }
        }

        return str.toString();
    }


也就是說,我們即使 使用 <s:property 標籤的 escape="true" 任然會有一定問題。這裏我們首先複習一下:

ASCII 的表示內容如下:
0 – 31 控制符號
32 空格
33-47 常用符號
48-57 數字
58-64 符號
65-90 大寫字母
91-96 符號
97-127 小寫字母


ISO8859 如下:
編號 0 – 127 與 ASCII 保持兼容
編號128 – 159 共32個編碼保留給擴充定義的 32 個擴充控制碼
160 爲空格
161 -255 的 95 個數字用於新增加的字符代碼
編碼的佈局與 ASCII 的設計思想如出一轍,由於在一張碼錶中只能增加 95 種字符的代碼,所以 ISO8859 實際上不是一張碼錶,而是一系列標準,包括 14 個字符碼錶。
例如,西歐的常用字符就包含在 ISO8859-1字符表中。在 ISO8859-7種則包含了 ASCII 和現代希臘語字符。


現在我想大家一定已經都很明白了,爲什麼修改後的代碼:
Java代碼
    else if (encodeSpecialChars && (c < '\377')) {  
                     String hexChars = "0123456789ABCDEF";  
                    int a = c % 16;  
                    int b = (c - a) / 16;  
                     String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);  
                     str.append("&#x" + hex + ";");  
                 }   

Java代碼 複製代碼 收藏代碼

    else if (encodeSpecialChars && (c < '\377')) {  
                    String hexChars = "0123456789ABCDEF";  
                    int a = c % 16;  
                    int b = (c - a) / 16;  
                    String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);  
                    str.append("&#x" + hex + ";");  
                } 

else if (encodeSpecialChars && (c < '\377')) {
                String hexChars = "0123456789ABCDEF";
                int a = c % 16;
                int b = (c - a) / 16;
                String hex = "" + hexChars.charAt(b) + hexChars.charAt(a);
                str.append("&#x" + hex + ";");
            }


才能將中文顯示正確。


但是同時也是有隱患的,所以也就讓我有了別的想法:
乾脆先進行轉碼好了
struts2-core-2.0.6 中 :
package org.apache.struts2.components ;
Property.java 中的
Java代碼
    private String prepare(String value) {  
            if (escape) {  
                return TextUtils.htmlEncode(new String(value.getBytes("iso-8859-1"),"gbk"));  
             } else {  
                return value;  
             }  
         }  

Java代碼 複製代碼 收藏代碼
private String prepare(String value) {
        if (escape) {
            return TextUtils.htmlEncode(new String(value.getBytes("iso-8859-1"),"gbk"));
        } else {
            return value;
        }
    }
    private String prepare(String value) {  
            if (escape) {  
                return TextUtils.htmlEncode(new String(value.getBytes("iso-8859-1"),"gbk"));  
            } else {  
                return value;  
            }  
        } 


注:進行該修改 可不對
package org.apache.struts2.components
Property.java 中的
private boolean escape = true;
進行修改,讓其默認進行 htmlEncode

struts2-core-2.1.6 中:
package org.apache.struts2.components
Property.java 中的
Java代碼
    private String prepare(String value) {  
             String result = value;  
            if (escape) {  
                 result = TextUtils.htmlEncode(new String(result.getBytes("iso-8859-1"),"gbk"));  
             }  
            if (escapeJavaScript) {  
                 result = TextUtils.escapeJavaScript(result);  
             }  
            return result;  
         }  

Java代碼
private String prepare(String value) {
     String result = value;
        if (escape) {
         result = TextUtils.htmlEncode(new String(result.getBytes("iso-8859-1"),"gbk"));
        }
        if (escapeJavaScript) {
         result = TextUtils.escapeJavaScript(result);
        }
        return result;
    }
    private String prepare(String value) {  
         String result = value;  
            if (escape) {  
             result = TextUtils.htmlEncode(new String(result.getBytes("iso-8859-1"),"gbk"));  
            }  
            if (escapeJavaScript) {  
             result = TextUtils.escapeJavaScript(result);  
            }  
            return result;  
        } 


注:進行該修改 可不對:
package org.apache.struts2.components
Property.java 中的
private boolean escape = true;

package org.apache.struts2.views.jsp;
PropertyTag.java 中的
private boolean escape = true;
進行修改,讓其默認進行 htmlEncode 操作,便可以顯示正確的中文。

其他相關包說明:
xwork-2.0.1.jar
struts2-core-2.0.6.jar
struts2-spring-plugin-2.0.6.jar
struts2-tiles-plugin-2.0.6.jar

xwork-2.1.2.jar
struts2-core-2.1.6.jar
struts2-spring-plugin-2.1.6.jar
struts2-tiles-plugin-2.1.6.jar
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章