JSP,html与javascript

来源:互联网 发布:线列步兵知乎 编辑:程序博客网 时间:2024/05/15 02:31
你寫了一個JSP網頁,使用Big5編碼:
<%@ page contentType="text/html; charset=Big5"     pageEncoding="Big5"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=Big5"><title>JSP 網頁</title></head><body>    名稱:<input type="text" name="name" value="${name}"></body></html>

其中${name}會是資料庫中撈取出來的名稱,放在請求範圍屬性中再轉發至這個JSP頁面,如果實際上資料庫中的名稱是「王大犇」,在伺服端的JVM中撈取出來的名稱也確認是正確的顯示,但再經由這個JSP網頁,卻會是亂碼:


這是自然地,因為你的網頁採Big5編碼,對瀏覽器而言,看到的HTML是:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Big5">
<title>JSP 網頁</title>
</head>
<body>
    名稱:<input type="text" name="name" value="王大?">
</body>
</html>

在 
Big 5 網頁難字 中介紹過,你可以將特殊字元用實體編號表示,所以你可以在伺服端JVM中使用StringEscapeUtils.escapeHtml()之類的程式庫,將「王大犇」處理為「&#29579;&#22823;&#29319;」:
request.setAttribute("name", StringEscapeUtils.escapeHtml("王大犇"));

如此看到的就會是正確的字元:


這是因為瀏覽器看到:
名稱:<input type="text" name="name" value="&#29579;&#22823;&#29319;">

再將「&#29579;&#22823;&#29319;」轉為實際的「王大犇」。然而,如果你這麼撰寫:
<%@ page contentType="text/html; charset=Big5"     pageEncoding="Big5"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <script type="text/javascript">        window.onload = function() {            document.getElementById('name').value = '${name}';        };    </script><meta http-equiv="Content-Type" content="text/html; charset=Big5"><title>JSP 網頁</title></head><body>    名稱:<input id="name" type="text" name="name"></body></html>

如果${name}是將「王大犇」處理為「&#29579;&#22823;&#29319;」的結果,那你會看到:


這個問題在 JavaScript 編碼基礎 中略談過,瀏覽器對於收到的HTML會進行剖析,這是實體編號被剖析為對應字元的時間點,這也是為什麼:
名稱:<input type="text" name="name" value="&#29579;&#22823;&#29319;">

最後會看到「王大犇」,瀏覽器完成HTML剖析後,會
建立JavaScript環境中對應的DOM物件,如果你直接將字串指定給DOM的特性,那就會以實際的字串值設定給DOM特性,而不會再經由剖析,不過 JavaScript 編碼基礎 提過,innerHTML特性是個例外,指定給innerHTML的字串,會嘗試再進行HTML剖析,所以如果你這麼撰寫:
<%@ page contentType="text/html; charset=Big5"     pageEncoding="Big5"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <script type="text/javascript">        window.onload = function() {            var span = document.createElement('span');            span.innerHTML = '${name}';            document.getElementById('name').value = span.innerHTML;        };    </script><meta http-equiv="Content-Type" content="text/html; charset=Big5"><title>JSP 網頁</title></head><body>    名稱:<input id="name" type="text" name="name"></body></html>

那你就會看到正確的「王大犇」。

你會想,誰會那麼無聊,使用JSP將字串產生為JavaScript,再用JavaScript指定給輸入欄位呢?有的時候,尤其是維護舊系統為主的公司,有些部份是你可以修改的,但有些剖份是你不能修改的(例如也許是另一個部份負責的子系統),就會遇到類似的情況。

例如,也許另一個子系統傳回的字串一徑作實體編號,
你的JSP中,使用Ajax進行查詢,像是某個查詢人名,另一個子系統直接將查得的人名作實體編號傳回以下結果:
&#29579;&#22823;&#29319;

如果你這麼撰寫:
        request.onreadystatechange = function() {
            if(request.readyState === 4) {
                if(request.status === 200) {
                    document.getElementById('name').value = request.responseText;
                }
            }
        };

那文字欄位就會出現「&#29579;&#22823;&#29319;」,但如果你這麼撰寫:
<%@ page contentType="text/html; charset=Big5"     pageEncoding="Big5"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <script type="text/javascript">    window.onload = function() {        var xhr = window.XMLHttpRequest &&               (window.location.protocol !== 'file:'                   || !window.ActiveXObject) ?               function() {                   return new XMLHttpRequest();               } :               function() {                  try {                     return new ActiveXObject('Microsoft.XMLHTTP');                  } catch(e) {                     throw new Error('XMLHttpRequest not supported');                  }               };        var request = xhr();        request.onreadystatechange = function() {            if(request.readyState === 4) {                if(request.status === 200) {                    var span = document.createElement('span');
span.innerHTML = request.responseText;
document.getElementById('name').value = span.innerHTML; } } }; request.open('GET', 'response'); request.send(null); }; </script> <meta http-equiv="Content-Type" content="text/html; charset=Big5"><title>JSP 網頁</title></head><body> 名稱:<input id="name" type="text" name="name"><br></body></html>

那就可以得到正確的顯示結果。事實上,這些作法,只不過是
 Servlet 中文處理(TomcatBig 5 網頁難字JSP 的轉譯JavaScript 編碼基礎 等基礎觀念的綜合應用,許多程式設計人員在這些基礎不足下,自然就無法變化應用。

再看一個學員來信的例子:
問:若db的資料內容若有單引號或雙引號,撈出來會造成html顯示不正常,怎麼解決呢?

如果有個輸入欄位:
<input type="text" value="${data}">

如果資料庫中的資料有雙引號,例如123"456結果就會是:
<input type="text" value="123"456">

這個HTML當然有問題,也許你會想,那就這樣:
<input type="text" value='${data}'>

如果資料庫中的資料有雙引號,例如123"456結果就會是:
<input type="text" value='123"456'>

但現在的情況中,資料庫中的資料是雙引號或單引號都有,如果資料實際上是123'456,你怎麼辦?

簡單的解決方式之一可以用JSTL,例如:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Hello World!</h1>
        <%
            String text1 = "test'test";
            String text2 = "test\"test";
        %>
        <input type="text" value="<c:out value="<%= text1 %>"/>"><br>
        <input type="text" value="<c:out value="<%= text2 %>"/>">
    </body>
</html>

<c:out>預設escapeXML是true,所以可解決問題,但這位學員又有問題了:
問:不過還真的有一好沒兩好,當我們想要 document.getElementById('xxx').value 給值的時候,卻會老老實實的顯示html內碼
ex.會顯示 123&#039;456 或 123&#034;456

我不太知道他要用<c:out>產生值給
JavaScript的原因,但要同時滿足兩個需求也非不行:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
        <%
            String text1 = "test'test";
            String text2 = "test\"test";
        %>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
        <script type="text/javascript">
            window.onload = function() {
                document.getElementById('i3').value =
                           document.getElementById('i1').value;

                document.getElementById('i4').value =
                           document.getElementById('i2').value;


            };
        </script>
    </head>
    <body>
        <h1>Hello World!</h1>
        <input id="i1" type="hidden" value="<c:out value="<%= text1 %>"/>"><br>
        <input id="i2" type="hidden" value="<c:out value="<%= text2 %>"/>"><br>

        <input id="i3" type="text"><br>
        <input id="i4" type="text">
    </body>
</html>

使用hidden欄位也可以,或者你也可以像先前用動態產生DOM元素的方式,這都是先前例子的再變化應用。
0 0