推薦使用Apache commons-lang的StringUtils來增強Java字符串處理功能,也一直在項目中大量使用StringUtils和StringEscapeUtils這兩個實用類。
最近在數據庫里發現某個表的內容全都成了HTML entity表示,中文也全被轉換成了”我”這樣的格式,而在頁面上顯示一切正常。最終發現造成這個后果的原因是在將字符串保存到 數據庫之前,用StringEscapeUtils.escapeHtml對其進行了處理。
字符串過濾是在許多Web應用開發中需要考慮的問題。比如用戶輸入一個左尖括號(<),在輸出HTML代碼對其進行顯示的話,應該 用”<”來表示。是在用戶將表單提交后就做轉換呢,還是在從數據庫取出內容向用戶展示時再轉換?這個問題需要仔細考慮。在入庫前轉換,看似 一勞永逸,然而如果用戶需要編輯這個內容,你需要原路退回,做個逆向的轉換,這看起來比較麻煩。所以大部分的轉換都是在從數據庫中取出數據之后做 的,struts的bean:write標簽 的filter屬性就是控制這個開關的(默認為true)。
而某些內容是不會被編輯的,比如一般的電子郵件,這類就可以在用戶提交表單之時轉換,一勞永逸。於是我使用了StringEscapeUtils.escapeHtml來做這個工作。
如果是英文內容,沒有任何問題,然而它將一個中文字符轉換成了8個字符。在UTF-8的編碼 中,每個漢字占用三個字節,每個英文字符占用一個字節。這樣的轉換造成了大量的空間浪費。
簡單的辦法是自己寫一個escapeHtml方法,替換左右尖括號就可以了。雖然還有一些HTML entity未被轉換,可能造成輸出的網頁不符合web標准,但是大部分瀏覽器都可以正常顯示也就夠了。
對要輸出的網頁內容編碼,網上搜的方法。
public static String htmlEncode(String source) { if (source == null) { return ""; } String html = ""; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < source.length(); i++) { char c = source.charAt(i); switch (c) { case '<': buffer.append("<"); break; case '>': buffer.append(">"); break; case '&': buffer.append("&"); break; case '"': buffer.append("""); break; case 10: case 13: break; default: buffer.append(c); } } html = buffer.toString(); return html; }