HTML 5 Web SQL Database初探
【51CTO译文】在《从零开始构建HTML 5页面》一文中,我们了解到HTML 5的一些新增特性并通过实例打造了一个完整的HTML 5页面。但HTML 5标准不只局限于传统的标记语言,它还拥有很多让人期待的API接口,利用这些接口,开发者可以创建更加丰富、更加引人注目的应用程序。之前我们介绍过支持文件拖放上传功能的HTML 5 File API,今天,我们一起来了解HTML 5的Web SQL Database API,使用本地和会话存储实现简单的对象持久化。 对于HTML 5,也许最为有用的就是它新推出的“Web Storage”(Web 存储)API。对简单的关键值对(比如应用程序设置)或简单对象(如应用程序状态)进行存储,使用本地和会话存储能够很好地完成,但是在对琐碎的关系数据进行处理之外,它就力所不及了。而这正是 HTML 5 的“Web SQL Database”API 接口的应用所在。 先提个醒,该文下面的内容需要读者对 JavaScript 和面对对象编程(尤其是匿名内的内部函数)以及SQL具有很好的理解。 打开链接 为了打开一个连接,我们执行以下代码:
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">db = openDatabase(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"ToDo"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"0.1"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, </span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"A list of to do items."</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, 200000); </span></span></p></li></ol> |
以上代码创建了一个数据库对象 db,名称是 Todo,版本编号为0.1。db 还带有描述信息和大概的大小值。用户代理(user agent)可使用这个描述与用户进行交流,说明数据库是用来做什么的。利用代码中提供的大小值,用户代理可以为内容留出足够的存储。如果需要,这个大小是可以改变的,所以没有必要预先假设允许用户使用多少空间。 为了检测之前创建的连接是否成功,你可以检查那个数据库对象是否为null:
|
1 |
<ol class="dp-xml" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">if(!db) </span></p></li><li style="list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;margin:0px !important;padding:0px 3px 0px 10px !important;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"> alert("Failed to connect to database."); </span></p></li></ol> |
绝不可以假设该连接已经成功建立,即使过去对于某个用户它是成功的。为什么一个连接会失败,存在多个原因。也许用户代理出于安全原因拒绝你的访问,也许设备存储有限。面对活跃而快速进化的潜在用户代理,对用户的机器、软件及其能力作出假设是非常不明智的行为。比如,当用户使用手持设备时,他们可自由处置的数据可能只有几兆字节。 执行查询 执行一个查询,你可以使用database.transaction()函数。该函数具有单一参数,负责查询实际执行的函数。 该函数(通常是匿名的)具有一个类型事务的参数。
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">db.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">transaction</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">( </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx) { </span></span></p></li></ol> |
该事务具有一个函数:executeSql。这个函数使用四个参数:表示查询的字符串,插入到查询中问号所在处的字符串数据(很像 Java 的预先准备好的语句),一个成功时执行的函数和一个失败时执行的函数。
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">tx.executeSql(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"SELECT COUNT(*) FROM ToDo"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, [], </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(result){}, </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx, error){}); </span></span></p></li><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><br style="clear:both;width:0px;height:0px;" /><br style="clear:both;width:0px;height:0px;" /><br style="clear:both;width:0px;height:0px;" /><br style="clear:both;width:0px;height:0px;" /></span></p></li></ol><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p><p style="padding:0px;background-color:transparent;text-indent:28px;margin-top:10px;margin-bottom:10px;"><br /></p> |
查询成功时 当查询成功执行时,应用程序跳转至一个具有一对参数的查询,一个是 transaction,另一个是它搜集的 results。对于实际上将你的数据传递至用户,这是非常完美的,比如显示 ToDo 列表。有关这个话题后面再讲。 查询失败失败时 当查询没能执行时执行。由于你将 transaction 对象作为函数的第一个参数进行传递,当出现错误时你可以继续执行查询。例如,如果是因为缺少表格(table)而查询无法运行,这是创建一个表格并在此执行该语句的绝佳时机。从该函数的第二个参数,你可以获得有关该错误的信息(包括描述)。 示例 假设我们想要使用上面的例子,想要查询数据库中的某个表格,如果该表格不存在,我们就创建一个表格。 在这个示例中,我们将调用具有一个函数参数的 db.transaction()。这个参数中,我们调用 tx.executeSql()。如果这个步骤成功,我们不做任何操作(因此是一个null参数)。或者我们将该事务和执行失败的函数一起传递,并再次调用 tx.executeSql()。这一次使用创建查询。
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">db.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">transaction</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">( </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx) { tx.executeSql(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"SELECT COUNT(*) FROM ToDo"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">,<br style="clear:both;width:0px;height:0px;" /> [], </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx, error) { tx.executeSql(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"CREATE TABLE ToDo (id REAL UNIQUE, label TEXT, timestamp REAL)"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">,<br style="clear:both;width:0px;height:0px;" /> [], </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">); } ); } ); </span></span></p></li><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p> </p></li></ol> |
使用所有这些内部方法,可能有点麻烦,所以你也许想在外部创建一个调用 db.transaction() 的函数。比如,我们可以让错误函数是自包含的,并将其命名为“createToDoTable()”。 插入 为了让代码更加简洁和安全,Web SQL Database API 允许你为 transaction.executeSql() 函数提供字符串数据,用以表示调用的 SQL 语句中的变量。我们使用以下的代码进行演示:
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">db.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">transaction</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">( </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx) { tx.executeSql(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"INSERT INTO ToDo (label, timestamp) values(?, ?)"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, <br style="clear:both;width:0px;height:0px;" />[label, new </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">Date</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">().getTime()], </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">); } ); </span></span></p></li><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p> </p></li></ol> |
在这个示例中,第一个参数中的两个问号将被后面数组中对应的项替代。第一个是为该任务设置的标签(也许是我们之前在代码中定义的一个变量),以及调用函数生成的时间戳。 执行该查询,其结果与下面语句类似:
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">INSERT</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;"> </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">INTO</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;"> ToDo (label, </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">timestamp</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">) </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">values</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;"> (</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"Test"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, 1265925077487) </span></span></p></li></ol> |
对结果进行处理 成功执行的函数对结果对象包含集合或行。每一列表示一个结果。该结果包含分配给它的一组值,表示该特定结果的数据库中的每一列的值。通过调用 result.rows.item(i) 可以访问一个行,其中 i 是你想要查询的行的指针。想要从一行中选择一个值,你可以传递给该行一个数组格式的字符串指针,它表示你需要查询的列。例如,如果想要标签(label)列,我们可以调用 row['label']。 以下代码使用结果对象来输出一个查询的结果:
|
1 |
<ol class="dp-sql" style="padding:5px 0px;color:#5c5c5c;list-style-position:initial;list-style-image:initial;word-wrap:break-word;word-break:normal;border:none;background-color:#f7f7f7;margin-top:0px !important;margin-right:0px !important;margin-bottom:1px !important;margin-left:55px;"><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"><span style="margin:0px;padding:0px;border:none;background-color:inherit;">db.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">transaction</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">( </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">(tx) { tx.executeSql(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">"SELECT * FROM ToDo"</span><span style="margin:0px;padding:0px;border:none;background-color:inherit;">, [], </span></span></p></li><li style="list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;margin:0px !important;padding:0px 3px 0px 10px !important;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"> </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">function</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">(tx, result) { </span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">for</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">(var i = 0; i < result.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">rows</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">.length; i++) </span></p></li><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">{ document.write(</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">'<b>'</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;"> + result.</span><span class="keyword" style="margin:0px;padding:0px;border:none;color:#006699;background-color:inherit;font-weight:bold;">rows</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">.item(i)[</span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">'label'</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">] + </span><span class="string" style="margin:0px;padding:0px;border:none;color:blue;background-color:inherit;">'</b><br />'</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">); } }, </span><span class="op" style="margin:0px;padding:0px;border:none;color:#808080;background-color:inherit;">null</span><span style="margin:0px;padding:0px;border:none;color:black;background-color:inherit;">); } ); </span></p></li><li class="alt" style="margin:0px !important;padding:0px 3px 0px 10px !important;color:inherit;list-style:none;word-wrap:break-word;word-break:normal;border:none;background-image:url(http://images.51cto.com/images/art1105/images/0.gif);background-attachment:scroll;background-color:transparent;line-height:18px;background-position:-498px -70px;background-repeat:no-repeat repeat;"><p><br /></p></li></ol> |
结论 […]
View DetailsSmarty
Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是要使PHP程序员同前端人员分离,使程序员改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。 定义 如何使我的PHP脚本从设计中独立出来?这无疑地是在PHP邮件列表上所提问的最多的问题之一。虽然PHP被标榜为“HTML嵌入式语言”,在写过许多PHP和HTML混合式的工程之后,我产生了一个分离表单和内容的想法。而且,在许多公司里规划设计者的角色和程序设计者是分开的。于是,这样的一个模板解决方案产生了…… 例如在一个公司,一个应用程序的开发流程如下:在提交计划文档之后,界面设计者[美工]制作了网站的外观模型,然后把它交给后台程序员。程序员使用PHP实现商业逻辑,同时使用外观模型做成基本架构。然后工程被返回到HTML页面设计者继续完善。就这样工程可能在后台程序员和页面设计者之间来来回回好几次。由于后台程序员不喜欢干预任何有关HTML标签,同时也不需要美工们和PHP代码混在一起;美工设计者只需要配置文件,动态区块和其他的界面部分,不必要去接触那些错综复杂的PHP代码。因此,这时候有一个很好的模板支持就显得很重要了。 纵观现今存在的许多PHP模板解决方案(比如PHPLIB),大多数都只是提供了用模板取代变量和将动态区块的功能有限的格式化的基本方法。但是我们的需求比这个要高的多。我们完全不想要PHP程序员去设计HTML页面,可是这又是不可避免的。例如:如果美工想要在动态区块之间交替不同的背景颜色,他就可能得和程序员预先说好。同样,美工们也应该有自己对于页面设计的配置文件,这同样可以通过变量把他们拉到模板里边去 优点 1. 速度:采用Smarty编写的程序可以获得最大速度的提高,这一点是相对于其它的模板引擎技术而言的。 2. 编译型:采用Smarty编写的程序在运行时要编译成一个非模板技术的PHP文件,这个文件采用了PHP与HTML混合的方式,在下一次访问模板时将WEB请求直接转换到这个文件中,而不再进行模板重新编译(在源程序没有改动的情况下) 3. 缓存技术:Smarty选用的一种缓存技术,它可以将用户最终看到的HTML文件缓存成一个静态的HTML页,当设定Smarty的cache属性为true时,在Smarty设定的cachetime期内将用户的WEB请求直接转换到这个静态的HTML文件中来,这相当于调用一个静态的HTML文件。 4. 插件技术:Smarty可以自定义插件。插件实际就是一些自定义的函数。 5. 模板中可以使用if/elseif/else/endif。在模板文件使用判断语句可以非常方便的对模板进行格式重排。 不适合使用Smarty的地方 需要实时更新的内容。例如像股票显示,它需要经常对数据进行更新,这类型的程序使用smarty会使模板处理速度变慢。 小项目。小项目因为项目简单而美工与程序员兼于一人的项目,使用Smarty会在一定程度上丧失PHP开发迅速的优点。 (PS:不过为了整个项目的规范,请大家尝试去使用模板引擎。其实习惯了,开发速度会更加快,以上是没有用习惯模板引擎的开发者遇到的问题) 诞生过程 早在1999年后期,我们就已经开始为模板引擎写说明文档。在完成这个文档之后,我们开始用C写一个模板引擎,并有希望被包含到PHP里去。在 撞上了许多的技术难题的同时,“什么是模板应该做的,什么不该做”这个问题,也被热烈的讨论着。从这些经验,我们决定应该用PHP将模板引擎写成一个类,让任何觉得合适的人使用它。所以我们写了一个引擎,从此就有了Smarty。(注:这个类以前从来没有公开发表过)。这个类几乎达到了我们所有的要求:常规变量替换,支持包括其他模板,使用配置文件集成设置,嵌入PHP代码,限制'if'语句的作用,还有更多的可以多层嵌套的健壮的动态区块。它用常规表达式做到这一切,于是代码变得相当令人费解。在每次调用的时候,都要去解析那些语法和常规表达式,于是在大型应用的时候,它显然慢了下来。在程序员的眼光看来,最大的问题还是使用PHP脚本建立和处理模板和动态区块的所有必要工作。我们应该如何使他变得更简单? 我们可以想象Smarty应该有怎样的最后表现。我们知道PHP代码如果没有了模板解析的开销将有多快,我们也知道从一般的美工看来PHP语言是多么的“恐怖”,然而这一切可以被一种更简单的模板语法掩饰掉。我们应该怎样把这两种方法的长处结合起来? 于是,Smarty诞生了……
View DetailsVelocity
Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。 应用 当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循MVC架构的web站点,也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提供了便利,同时也为我们在JSP和PHP之外又提供了一种可选的方案。 更多功能 Velocity的能力远不止web站点开发这个领域,例如,它可以从模板(template)产生SQL和PostScript、XML,它也可以被当作一个独立工具来产生源代码和报告,或者作为其他系统的集成组件使用。Velocity也可以为Turbine web开发架构提供模板服务(template service)。Velocity+Turbine提供一个模板服务的方式允许一个web应用以一个真正的MVC模型进行开发。 http://baike.baidu.com/view/77351.htm
View DetailsHibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。 创始人 让时间回到2001年,地点是澳大利亚悉尼的Clarence Street有一家叫做Cirrus Technologies的公司,这是一家做J2EE企业级应用开发和咨询的公司,在会议桌上一个小伙子和老板正在进行着激烈的讨论。 小伙子:"老板,我总觉得现在开发的效率太低了,我用了EJB的Entity bean 1.1时,我总觉得我浪费了好多时间在处理Entity Bean的体系架构上,却没有花时间在核心业务逻辑的开发上,而且CMP给我们的限制太多了"。 老板:"Gavin,别傻了,EJB是业界的标准,也是最流行的技术,而且我们公司是IBM的合作伙伴。如果有问题,问题就是我们还没有适应这样的开发模式"。 小伙子:"不,我觉得肯定有更好的解决的方案。我们可以设计出比Entity Bean更好的方案"。 老板:"哦,Gavin,我知道你很聪明,开发水平也不错。但是开发这样的系统太难了,而且你根本就没有用SQL开发过任何数据库系统。不要想这样一个不现实的目标啦!" 小伙子皱了皱眉,说道:"不,我相信我有能力开发出这个系统。我的想法绝对是可行的。" (注:以上场景纯属虚构,但至少以下内容完全属实:Gavin King开发hibernate的动机有两个:发现CMP太滥;赢得对老板的争执。Gavin King当时没有任何用SQL开发数据库的经验,Gavin King开发hibernate的第一件事是去街上买了本SQL基础的书) 也许Cirrus Technologies的老板做梦也想不到两年以后,这个小伙子开发出的那个产品会成为全世界最流行的O/R Mapping工具,而那个对SQL和数据库一窍不通的小伙子居然会成为全世界J2EE数据库解决方案的领导者。 这就是Gavin King,一个充满激情、脾气很倔、永不言败的人。他的成就也许全世界搞Java的人都知道:他是hibernate的创始人;他是EJB 3.0的Entity bean specification的实际领导人(sun任命的领导人应该是 Linda DeMichiel);他也是那本经典的书hibernate in action的作者;他也参加了XDoclet和Middlegen的开发;他在全世界各种著名的会议(TheServerSide Symposium等)进行演讲和讲座。 2003年9月, Gavin King和hibernate的一些开发者加入了JBoss。这样他们就可以全职进行hibernate的开发,并提供最好的服务和培训。 也许在这里讨论hibernate的成功和影响力这种全世界都知道的事情已经是多余的了。Gavin King的火爆的脾气和自负也是闻名的,看看Gavin King自己有趣的评价:Even when I'm a rude grumpy bastard answering forum posts at 3am, I'm always happy to see people using Hibernate.(有点断章取义之嫌,呵呵,贴出来闹着玩)。看看Gavin King的一些表现吧: 1、2005年3月,JDO的一个vendor Versant在他的Paper里指了好多hibernate的好多所谓的缺点,Gavin King做出了毫不留情的反击。 2、2003年9月,Gavin King在他网站上向全世界发起挑战:谁要是能对一段代码用JDBC开发做到效率比hibernate高好多,就给他100美金。 3、Rod Johnson在2005年的TheServerSide Symposium对JBoss那帮人戴假面具穿小丑衣表示了一下意见:"neither I nor any of my colleagues will be dressing up as film characters"。看看Gavin King的回击吧:"But Rod, you'd make such a great Egghead! Well […]
View Detailshibernate search
Hibernate Search是在apache Lucene的基础上建立的主要用于Hibernate的持久化模型的全文检索工具。像Lucene这样的检索引擎能够给我们的项目在进行检索的时候带来非常高的效率,但是它们在基本对象的检索时会有一些问题,比如不能实现检索内容跟实体的转换,Hibernate Search正是在这样的情况下发展起来的,基于对象的检索引擎,能够很方便的将检索出来的内容转换为具体的实体对象。此外Hibernate Search能够根据需要进行同步或异步的索引更新。 http://baike.baidu.com/view/6288294.htm
View Detailsjasperreport
JasperReport是一个强大、灵活的报表生成工具,能够展示丰富的页面内容,并将之转换成PDF,HTML,或者XML格式。该库完全由Java写成,可以用于在各种Java应用程序,包括J2EE,Web应用程序中生成动态内容。 jasperreport是开源的,这给我们带来很大方便,但是文档却要钱,让人不爽。不过人总要生存,再说,做这么一个好东西,用户总不能一点代价也不付(虽然对于中国普通程序员来说太贵了点)。它还有一个相关的开源工程IReport,这是一个图形化的辅助工具,因为JasperReport仅提供了可使用的类库而未提供更好的开发工具,IReport的出现解决了这一难题。它们配合使用将会更大程度的提高效率。 该库完全由Java写成,可以用于在各种Java应用程序,包括J2EE,Web应用程序中生成动态内容。它的主要目的是辅助生成面向页面的(page oriented),准备付诸打印的文档。JasperReport借由定义于XML文档中的report design进行数据组织。这些数据可能来自不同的数据源,包括关系型数据库,collections,java对象数组。通过实现简单的接口,用户可以将report library插入到订制好的数据源中,在以后我们将提到有关内容。 其实这是一份JasperReport Ultimate Guide的简单翻译以及我的理解和例子。在最后,我将描述一个我正在做的工程,将其中用到的相关信息贡献出来。我这么做是因为当我在学这个类库的时候苦于很少有相关的中文文档,又或语言不详,希望其他人不再受苦。这个文档将分几次贴出来,与原文档的章节相对应。这份文档的Word形式将在全部完成之后放在我的公开邮箱中与各位共享。 http://baike.baidu.com/view/1662522.htm
View DetailsDbVisualizer
数据库管理工具 基本内容 DbVisualizer是一个完全基于JDBC的跨平台数据库管理工具,内置SQL语句编辑器(支持语法高亮),凡是具有JDBC数据库接口的数据库都可以管理,已经在Oracle, Sybase, DB2, MySQL, InstantDB, Cloudcape, HyperSonic ,Mimer SQL上通过测试。 DbVisualizer常见问题解答:http://database.ctocio.com.cn/tips/484/7625484.shtml DbVisualizer是一款涉及到所有主要数据库且基于交叉平台上的援助与维护数据库工具。它允许通过JDBC的驱动同时连接各种不同的数据库;立刻指向并浏览数据库结构,观看数据库对象的详细特征,图解桌面数据、任意的SQL声明或SQL脚本,利用逆向工程图示出primary/foreign的键值,并以先进的图表方式显示出来,友好的图形界面接口与各种特色的独特组合,足以值得您去收藏一份。 DbVisualizer 是一个功能强大Java工具,用来同时查看一个或者多个JDBC击活的数据库。它可以以图形的方式显示表单之间的关系。它可以显示关于数据项、关键字等信息。使用SQL命令,还可以执行所有的SQL语句。 个人版和免费版本相比,个人版有以下功能扩展: #编辑表格数据。 #支持表格/索引创建。 #SQL脚本执行。 #多个结果集合管理。 #数据图表化。 #BLOB/CLOB数据管理。 #浏览存储步骤等。 DbVisualizer的管理方式确实比phpMyAdmin会强一些,特别是可以轻松生成E-R图并导出,确实是不错的软件,现在只有英文版,DbVisualizer中文版还没有出,期待中文版。 DbVisualizer使用JAVA开发的,目前拿他来做Oracle、MySQL、PostgreSQL甚至包括 MS SQL Server 数据库管理都是一件非常轻松的事情。 新版本已经集成了JDBC 的jar包,所以在安装6.0版本时要选中JDBC 的jar包,不然在创建与数据库连接时无法连接的。 这是我在偶然间找到的一个软件,它是使用JAVA开发的,可以这么说,只要有 JDBC 的驱动包,可以连接市面上所有的数据库。目前经我测试,已经连接上 Oracle、SyBase、MySQL、PostgreSQL。 破解方法: Unpack, Install. Copy cracked files from /iNViSiBLE dir to installdir\lib Run app, go to Help > License Key and select supplied license file. http://baike.soso.com/v26476145.htm
View Detailsfreeswitch
FreeSWITCH 是一个电话的软交换解决方案,包括一个软电话和软交换机用以提供语音和聊天的产品驱动。FreeSWITCH 可以用作交换机引擎、PBX、多媒体网关以及多媒体服务器等。 FreeSWITCH 支持多种通讯技术标准,包括 SIP, H.323, IAX2 以及 GoogleTalk ,可以方便的与其他开源的PBX系统进行对接,例如 sipX, OpenPBX, Bayonne, YATE 或者 Asterisk. FreeSWITCH 支持许多高级的 SIP 特性,例如 presence/BLF/SLA 、TCP TLS 和 sRTP,它还可以用来作为类似于 SBC (Session Border Controller) 的透明代理。[1] FreeSWITCH的是一个跨平台的开源电话交换平台,具有很强的伸缩性。旨在为音频、视频、文字或任何其他形式的媒体,提供路由和互连通信协议。它创建于2006年,填补了许多商业解决方案的的空白。FreeSWITCH的也提供了一个稳定的电话平台,许多广泛使用的免费电话就是在使用它开发的。 FreeSWITCH 遵循RFC并支持很多高级的SIP特性,如 presence、BLF、SLA以及TCP、TLS和sRTP等。它也可以用作一个SBC进行透明的SIP代理(proxy)以支持其它媒体如T.38等。FreeSWITCH 支持宽带及窄带语音编码,电话会议桥可同时支持8、12、16、24、32及48kHZ的语音. 而在传统的电话网络中,要做到三方通话或多方通话需要通过专门的芯片来处理,其它像预付费,彩铃等业务在PSTN网络中都需要依靠智能网(IN)才能实现,而且配置起来相当不灵活。 FreeSWITCH 是一个开源的电话交换平台,从一个简单的软电话客户端到运营商级的软交换设备几乎无所不能。能原生地运行于Windows、Max OS X、Linux、BSD 及 solaris 等诸多32/64位平台。可以用作一个简单的交换引擎、一个PBX,一个媒体网关或媒体支持IVR的服务器等。它支持SIP、H323、Skype、Google Talk等协议,并能很容易地与各种开源的PBX系统如sipXecs、Call Weaver、Bayonne、YATE及Asterisk等通信。 视频编解码器(直通): Theora的 H.261 H.263 H.264 MP4 另见:编解码器 支持多种编解码器 CELT(32千赫 AHD 48千赫) G.722.1(宽带) G.722.1C(宽带32千赫) G.722协议(宽带) G.711 G.726(16K,24K,32K,48K)AAL2和RFC 3551 G.723.1(直通) G.729AB(需要许可证,除非使用直通) AMR(直通) iLBC的 Speex语音(窄带和宽带) LPC – 10 DVI4(ADPCM),8 kHz和16 kHz http://baike.baidu.com/view/6937725.htm
View Detailssvn is already locked解决方案
在出错文件夹下,鼠标右键TortoiseSVN->Clean up. SVN错误:Attempted to lock an already-locked dir 出现这个问题后使用“清理”功能,如果还不行,就直接到上一级目录,再执行“清理”,然后再“更新”。 有时候如果看到某个包里面的文件夹没有SVN的标志,直接用“Ctrl+Delete”手工删除,然后“清理”,最后“更新”或“提交”。 http://blog.csdn.net/dracotianlong/article/details/8026885
View Details[性能测试]VSTS经典测试解决方案文件浅析
*.testsettings文件; 在VS 2010中,测试解决方案会自动产生两个文件。一个是TraceAndTestImpact.testsettings,记录用于调试的测试设置。另一个Local.testsettings为本地缺省的测试设置。VS2008只有本地缺省设置。 *.testsettings,这是运行测试的环境参数和运行参数,包括以下内容:a) 用例运行前后执行的脚本b) 是否启用数据分析(代码覆盖率,测试影响分析,模拟网络,录制视频,智能跟踪等等)很多功能都是VS2010独有的,c) 运行机器是本机还是远程机器d) 测试超时时间等 VS2010 增强了测试监控功能,例如智能跟踪(IntelliTrace)和视频录制(Video Recoder),测试影响分析(TestImpact)等等 *.vsmdi文件,用于管理测试用例的列表(Test List).*.vsmdi 文件是管理Test List的,在VS 2010中虽然支持,但不推荐使用。主要原因是*.vsmdi非常不灵活,很难集中维护。取而代之的是更加自然的测试分类(Test Category):通过给每个测试用例设置标签,运行的时候通过标签选择需要运行的测试用例。 为了兼容问题,VS2010 还是支持*.vsmdi。下面是*.vsmdi的一些基本格式。 其内容基本上包括一个树状内容的Test List 列表,各个节点通过ParentListID相连,其中包括一个特殊根节点。另外,在每个TestList中,一个TestLink代表一个测试用 例,TestLink的ID是通过测试方法名,测试类名和包名等,通过MD5计算而得(而非任意值),我以前就写过一个程序,自动生成*.vsmdi文 件。 如何设置不同的标签,在运行用例时,可以通过过滤标签的属性来运行。其方法如下: 步骤一: 为每个测试用例设置测试分类属性(Test Category),在方法的属性中增加。
|
1 2 3 4 |
<strong style="padding:0px;margin:0px;">[<span style="padding:0px;margin:0px;color:#2b91af;">TestCategory</span>(<span style="padding:0px;margin:0px;color:#a31515;">"Nightly"</span>), <span style="padding:0px;margin:0px;color:#2b91af;">TestCategory</span>(<span style="padding:0px;margin:0px;color:#a31515;">"Weekly"</span>)</strong>, <span style="padding:0px;margin:0px;color:#2b91af;">TestMethod</span>()] <span style="padding:0px;margin:0px;color:blue;">public void </span>TestMethod1() { <span style="padding:0px;margin:0px;color:green;">// // TODO: Add test logic here // </span>} |
步骤二: 通过测试分类,运行测试用例 1)从UI中,选择测试用例运行 2)通过命令行运行 mstest /testcontainer:MyTestprojectName.dll /category:"Nightly&Weekly" 在条件选择时候,可以使用&或则|作为操作条件;但是在VS2010中,只能用一种操作符号 运行测试 写好测试用例就可以运行,Ctrl F5,就这么简单,能够得到测试用例运行的结果。很容易在IDE看到,测试结果,那么如何读懂后面的文件呢? 一次测试运行结果的目录: *.trx文件. 运行结果目录。其中有In, Out 和每个TestCase的详细结果。 http://opheliawei.blog.51cto.com/2653343/1026956
View Details