將一個字符串存入數據庫并顯示出來是一項簡單任務,當字符串長度較短(新聞級別)時確實如此.
然而量變引起質變,當字符串長度增加到一定程度(小說級別)時,原有的對簡短字符串的處理流程就需要做出一些變化了.下文將討論這些變化的細節.
一.Web系統的基本情況以下是某Web系統的基本情況:
前臺JS框架:
jQuery1.7.2 它確實貼心,比Dojo強,write less do more真不是空話
前后臺信息傳遞方式:全部為
Ajax異步處理 拒絕form提交
控制器:
Spring3 MVC 很好 SpringMVC終將動搖Struts1/2的低位
Mapping:
Hibernate3.2(C),SpringDAO(RUD)
后臺DB:
MySql5.2 它確實小巧方便,如果Oracle DB2跑在我的T410上那就開不了別的程序了
二.長文本向后臺的傳遞Web前臺向后臺傳遞數據的方式有get和post兩種,它們之間有一些差別.就本文涉及的場景來說,差別主要在數據量的大小上,GET方式對傳輸的數據有大小限制,通常不能大于2KB;而使用POST方式傳遞的數據量比GET方式大得多,理論上不受限制.因此我采用了POST方式.
傳遞代碼如下:
var url='wisdom/add.do';
$.post(
url,
{title:encodeURIComponent($(
"#title").val()),concept:encodeURIComponent(
$("#concept").val())},
function(data,textStatus){
var status=$(data).find("status").text();
if(status=="ok"){
...
}
else{
var text=$(data).find("text").text();
alert(text);
}
}
); 以上代碼中,concept就是在textarea中的長文本,理論上長度是無限的,但實際應用中會受到數據庫字段的限制.
三.服務器的設置POST提交有長度限制,當超過時將會出錯,可以配置
maxPostSize參數來改變大小。<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxPostSize="0"/>
當設置為零時,就沒有長度限制了.
四.長文本在DB中的存儲首先需要考慮的數據庫的字段,一般的varchar肯定是不夠了;clob/blob容量是夠,但查詢時需要取出來轉化一下,而這樣速度上就受限了;一向比較貼心的MySql提供了一個LONGTEXT類型,它可以容納4294967295byte的文字,而在使用上又如同文本一樣,這成了我的首選,在后來的實際測試中,我發現它存儲80萬個漢字是沒有問題的,100萬也行,這就已經滿足我的需求了,因此更大的測試沒有再進行.
這個Web系統CRUD處理中,C是通過Hinernate完成的,因此在hbm.xml中進行設置就好了.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.ibm.heyang.domain">
<class name="Wisdom" table="collections_wisdom">
<id name="id" column="ID" >
<generator class="increment"/>
</id>
<property name="title" column="title" not-null="true"/>
<property name="concept" type="text">
<column name="concept" not-null="true" length = "16777216" />
</property>
<property name="conceptLength" column="conceptLength" />
<property name="addUserId" column="addUserId" />
<property name="modifyTime" column="modifyTime"/>
</class>
</hibernate-mapping>
以上粗體部分就是大文本字段的設置細節.
由于Hibernate是采用PreparedStatement,因此concept不需要進行轉義和其它特殊處理.這給檢索也帶來了不少方便.
五.長文本的檢索由于插入數據庫的文本就是原文,所以檢索就是常規的檢索,無須贅述.
六.長文本向前臺的傳遞前的包裝在這個Web系統中,后臺向前臺傳遞的數據是以XML的型式往回傳的,前臺JS得到后再解析出來.
但長文本有一個特殊的地方就是內容無限制,比如違反XML規則的字符如<>等,這里就需要把它放在CDATA塊里包起來后再向前傳遞.
如下:
StringBuilder sb=new StringBuilder();
sb.append("<title><![CDATA[");
sb.append(StringUtils.isBlank(title)?"-":title);
sb.append("]]></title>");
sb.append("<concept><![CDATA[");
sb.append(concept);
sb.append("]]></concept>");
如果不這樣處理一下,前臺js就可能解析XML出錯.
七.長文本的顯示將長文本顯示給用戶看可以采用textarea顯示和網頁顯示,如果是前者那就沒有特殊處理,直接放進去就行了,文本格式和存儲前會一樣,只是用戶看起來不方便,需要用滾動條拖來拖去;而網頁方式就好多了,用戶舒適度好很多,但要求我們進行一些特殊的處理.
首先是CSS設置,這是為了保證文本不把DIV撐開,設置如下:
#concept{
width:900px;
max-width:900px;
min-width:900px;
display:inline-block;
padding-top:10px;
color:#7a7a7a;
font-size:14px;
font-weight:normal;
text-align:left;
word-wrap: break-word;
word-break: normal;
-moz-binding: url('./wordwrap.xml#wordwrap');/*FF only*/
word-break:break-all;
white-space: moz-pre-wrap;
}
其次,需要對文本處理一下,這樣做的目的是把<>轉義,另外把\n轉化成<br>,空格轉化成 等,如果不這樣做,文字會亂,閱讀起來很覺不便.
以下是轉化函數:
function makeText2Html(originalText){
originalText=originalText.replace("<","<");
originalText=originalText.replace(">",">");
originalText=originalText.replace(/\n/g,"<br/>");
originalText=originalText.replace(/\t/g," ");
originalText=originalText.replace(" "," ");
return originalText;
}
以下是把XML中的長文本放到頁面中:
$("#concept").html(getFormatedText($(data).find("concept").text()));
如果IE ONly的話,也可以把文本用<pre>標簽包起來,這樣就不用makeText2Html的輔助了.
以上就是對長文本的存儲和顯示的一些處理,由于作者水平有限,上文只是我的孔見,不當之處還請指出.