某Web系统对长文本的存储和显示的处理
将一个字符串存入数据库并显示出来是一项简单任务,当字符串长度较短(新闻级别)时确实如此.
然而量变引起质变,当字符串长度增加到一定程度(小说级别)时,原有的对简短字符串的处理流程就需要做出一些变化了.下文将讨论这些变化的细节.
一.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方式.
传递代码如下:
三.服务器的设置
POST提交有长度限制,当超过时将会出错,可以配置 maxPostSize参数来改变大小。
四.长文本在DB中的存储
首先需要考虑的数据库的字段,一般的varchar肯定是不够了;clob/blob容量是够,但查询时需要取出来转化一下,而这样速度上就受限了;一向比较贴心的MySql提供了一个LONGTEXT类型,它可以容纳4294967295byte的文字,而在使用上又如同文本一样,这成了我的首选,在后来的实际测试中,我发现它存储80万个汉字是没有问题的,100万也行,这就已经满足我的需求了,因此更大的测试没有再进行.
这个Web系统CRUD处理中,C是通过Hinernate完成的,因此在hbm.xml中进行设置就好了.
由于Hibernate是采用PreparedStatement,因此concept不需要进行转义和其它特殊处理.这给检索也带来了不少方便.
五.长文本的检索
由于插入数据库的文本就是原文,所以检索就是常规的检索,无须赘述.
六.长文本向前台的传递前的包装
在这个Web系统中,后台向前台传递的数据是以XML的型式往回传的,前台JS得到后再解析出来.
但长文本有一个特殊的地方就是内容无限制,比如违反XML规则的字符如<>等,这里就需要把它放在CDATA块里包起来后再向前传递.
如下:
七.长文本的显示
将长文本显示给用户看可以采用textarea显示和网页显示,如果是前者那就没有特殊处理,直接放进去就行了,文本格式和存储前会一样,只是用户看起来不方便,需要用滚动条拖来拖去;而网页方式就好多了,用户舒适度好很多,但要求我们进行一些特殊的处理.
首先是CSS设置,这是为了保证文本不把DIV撑开,设置如下:
其次,需要对文本处理一下,这样做的目的是把<>转义,另外把\n转化成<br>,空格转化成 等,如果不这样做,文字会乱,阅读起来很觉不便.
以下是转化函数:
如果IE ONly的话,也可以把文本用<pre>标签包起来,这样就不用makeText2Html的辅助了.
以上就是对长文本的存储和显示的一些处理,由于作者水平有限,上文只是我的孔见,不当之处还请指出.
然而量变引起质变,当字符串长度增加到一定程度(小说级别)时,原有的对简短字符串的处理流程就需要做出一些变化了.下文将讨论这些变化的细节.
一.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:
var status = $(data).find( " status " ).text();
if (status == " ok " ){
...
}
else {
var text = $(data).find( " text " ).text();
alert(text);
}
}
);
以上代码中,concept就是在textarea中的长文本,理论上长度是无限的,但实际应用中会受到数据库字段的限制.
$.post(
url,
{title:
encodeURIComponent($(
"
#title
"
).val()),concept:
function
(data,textStatus){
encodeURIComponent(
$(
"#concept"
).val())},
var status = $(data).find( " status " ).text();
if (status == " ok " ){
...
}
else {
var text = $(data).find( " text " ).text();
alert(text);
}
}
);
三.服务器的设置
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 >
以上粗体部分就是大文本字段的设置细节.
<! 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出错.
sb.append( " <title><![CDATA[ " );
sb.append(StringUtils.isBlank(title) ? " - " :title);
sb.append( " ]]></title> " );
sb.append( " <concept><![CDATA[ " );
sb.append(concept);
sb.append( " ]]></concept> " );
七.长文本的显示
将长文本显示给用户看可以采用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 ;
}
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中的长文本放到页面中:
originalText = originalText.replace( " < " , " < " );
originalText = originalText.replace( " > " , " > " );
originalText = originalText.replace( / \n / g, " <br/> " );
originalText = originalText.replace( / \t / g, " " );
originalText = originalText.replace( " " , " " );
return originalText;
}
$(
"
#concept
"
).html(getFormatedText($(data).find(
"
concept
"
).text()));
如果IE ONly的话,也可以把文本用<pre>标签包起来,这样就不用makeText2Html的辅助了.
以上就是对长文本的存储和显示的一些处理,由于作者水平有限,上文只是我的孔见,不当之处还请指出.