<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    任意Android設(shè)備上運(yùn)行測(cè)試

     圖:打開(kāi)數(shù)據(jù)源“對(duì)話框...
      
      圖:添加一個(gè)簡(jiǎn)單數(shù)據(jù)表...
      
      圖:添加設(shè)備名稱到簡(jiǎn)單數(shù)據(jù)表
      這樣做之后,切換到“數(shù)據(jù)綁定”選項(xiàng)卡,并綁定數(shù)據(jù)源中的模塊變量。
      
      圖:數(shù)據(jù)源綁定變量
      如果你想了解更多有關(guān)測(cè)試數(shù)據(jù)驅(qū)動(dòng)的方法,參考第3課:數(shù)據(jù)驅(qū)動(dòng)的測(cè)試。
      現(xiàn)在,測(cè)試套件準(zhǔn)備好在不同的設(shè)備上運(yùn)行了。 成功運(yùn)行測(cè)試后,測(cè)試報(bào)告看起來(lái)應(yīng)該像下面這樣。
      
      圖:兩個(gè)設(shè)備上成功執(zhí)行的測(cè)試
      我們會(huì)向你證明,在設(shè)備上運(yùn)行您的Andr??oid測(cè)試是多么容易。添加其他設(shè)備,調(diào)制并部署測(cè)試的App,如本章前面所述。
      注意:在不同的設(shè)備上運(yùn)行測(cè)試時(shí),請(qǐng)一定要加一個(gè)'Close Application'的action,因?yàn)槿绻耙粋€(gè)設(shè)備上的 App不被關(guān)閉,那么接著執(zhí)行時(shí),這個(gè)設(shè)備上的App仍然會(huì)被自動(dòng)化。
      圖:添加“Close Application”action,以確保錄制的腳本在正確的設(shè)備上執(zhí)行
      這樣做之后,對(duì)'Run Mobile App' 的'Device Display Name'列進(jìn)行參數(shù)化,改成模塊變量。
      
      圖:把設(shè)備名稱作為變量
      把設(shè)備名稱參數(shù)化后,打開(kāi)包含該模塊用例的“數(shù)據(jù)源”對(duì)話框,添加一個(gè)簡(jiǎn)單數(shù)據(jù)表,在表中添加你想運(yùn)行設(shè)備的名稱。
     
    并行執(zhí)行測(cè)試
      它也可以在多個(gè)設(shè)備上同時(shí)運(yùn)行一個(gè)測(cè)試。
      因?yàn)闆](méi)有必要使用數(shù)據(jù)源,所以在測(cè)試用例屬性對(duì)話框中禁用先前創(chuàng)建的數(shù)據(jù)源。
      
      圖:禁用數(shù)據(jù)源
      添加一個(gè)全局參數(shù),并把它綁定到變量'varMobileDevice'。
      
      圖:添加全局參數(shù)
      
      圖:把變量綁定到全局參數(shù)
      全局參數(shù)和數(shù)據(jù)綁定的進(jìn)一步詳情請(qǐng)參考“ 第3課:數(shù)據(jù)驅(qū)動(dòng)測(cè)試。
      在對(duì)象庫(kù)中,使用Ranorex Xpy 的path編輯器打開(kāi)移動(dòng)App的RanoreXPath,。
      
      圖:打開(kāi)高級(jí)RanoreXPath編輯器
      添加設(shè)備名稱到RanoreXPath中,并選擇變量'varMobileDevice'作為值。
      
      圖:把設(shè)備名稱變量添加到RanoreXPath
      執(zhí)行這些步驟之后,你就可以編譯測(cè)試套件,通過(guò)命令行,把移動(dòng)設(shè)備名稱作為命令行參數(shù)來(lái)執(zhí)行測(cè)試用例,參考“ 第4課:Ranorex測(cè)試套件-無(wú)RanorexStudio運(yùn)行測(cè)試 “:
      start MobileTest.exe /pa:globalMobileDevice="Galaxy Nexus"
      start MobileTest.exe /pa:globalMobileDevice="GT-P7500"

    posted @ 2014-07-07 21:33 順其自然EVO 閱讀(242) | 評(píng)論 (0)編輯 收藏

    lr檢查點(diǎn)

     前言
      很久很久沒(méi)有更新博客了。久到我都不記得上一次更新博客是什么時(shí)候,久到我們博客主機(jī)都過(guò)期了,一度我還想停掉這個(gè)博客。好在有simon的堅(jiān)持才決定博客繼續(xù)整下去。2013年對(duì)我來(lái)說(shuō)是一個(gè)比較折騰的一年。一年之類換了兩份工作。找工作的時(shí)候才發(fā)現(xiàn)理想與現(xiàn)實(shí)之間的差距是如此的巨大。期間經(jīng)歷了落差、失望、彷徨……
      最近一段時(shí)間給我們組成員培訓(xùn)LoadRunner,我自己也有所收獲,也就有了這篇文章
      一、為什么要使用檢查點(diǎn)
      為什么要使用檢查點(diǎn),那就要說(shuō)明一下LR如何判斷腳本是否執(zhí)行成功。
      LR判斷腳本是否執(zhí)行成功是根據(jù)服務(wù)器返回的狀態(tài)來(lái)確定的,如果服務(wù)器返回的HTTP狀態(tài)為 200 OK ,那么VuGen 就認(rèn)為腳本正確地運(yùn)行了,并且是運(yùn)行通過(guò)的。在絕大多數(shù)系統(tǒng)出錯(cuò)時(shí)會(huì)返回錯(cuò)誤頁(yè)面碼? 不會(huì)一般系統(tǒng)都會(huì)返回一個(gè)消息提示框,來(lái)提升用戶感受。例如,“網(wǎng)站繁忙,請(qǐng)稍后”。其實(shí)這個(gè)時(shí)候網(wǎng)站已經(jīng)無(wú)法正確響應(yīng)用戶請(qǐng)求了,但是VuGen 腳本無(wú)法識(shí)別,會(huì)錯(cuò)誤地認(rèn)為網(wǎng)站還能正確訪問(wèn),導(dǎo)致分析錯(cuò)誤。所以這時(shí)需要一種檢查點(diǎn)函數(shù)幫助驗(yàn)證請(qǐng)求發(fā)送出去后,服務(wù)器的返回是不是期望的內(nèi)容,如果不是,那么就說(shuō)明服務(wù)器返回?zé)o法提供正常的服務(wù)了。
      另外,需要特別說(shuō)明的是,檢查點(diǎn)一般跟事務(wù)結(jié)合起來(lái)使用。
      二、事務(wù)結(jié)束的四種狀態(tài)
      前面說(shuō)到檢查點(diǎn)一般跟事務(wù)結(jié)合使用。這樣需要說(shuō)明一下事務(wù)(transaction)。我認(rèn)為事務(wù)是LR中非常非常重要的一個(gè)概念。因?yàn)橥瓿梢粋€(gè)事務(wù)所需要的時(shí)間是響應(yīng)時(shí)間(Trans Response Time),一秒鐘可以完成多少事務(wù)是TPS(Trans/Sec)。響應(yīng)時(shí)間和TPS是性能測(cè)試中非常重要的兩個(gè)指標(biāo)??梢酝ㄟ^(guò)這兩個(gè)指標(biāo)來(lái)分析系統(tǒng)是否出現(xiàn)瓶頸。
      LR中事務(wù)結(jié)束的時(shí)候需要帶上一個(gè)狀態(tài)碼(Transaction Status)。LR中Transaction Status有四個(gè), 分別為L(zhǎng)R_PASS, LR_FAIL, LR_AUTO , LR_STOP。
      LR_AUTO:事物的狀態(tài)被自動(dòng)設(shè)置,如果事務(wù)執(zhí)行成功,狀態(tài)設(shè)置為PASS,如果執(zhí)行失敗,狀態(tài)設(shè)置為FAIL,如果由于異常中斷,狀態(tài)被設(shè)置成STOP.
      LR_PASS:事務(wù)如果執(zhí)行成功,代碼的返回狀態(tài)就是PASS。
      LR_FAIL:事務(wù)如果執(zhí)行失敗,代碼的返回狀態(tài)就是FAIL。
      一般情況下會(huì)選擇LR_AUTO,讓LR自動(dòng)判斷事務(wù)的狀態(tài)??墒侨缟厦嫠f(shuō)LR判斷腳本是否執(zhí)行成功是根據(jù)服務(wù)器返回的狀態(tài)來(lái)確定的,也就是只要服務(wù)器返回的HTTP狀態(tài)為 200 OK ,事務(wù)執(zhí)行后狀態(tài)總是被置為L(zhǎng)R_PASS。這樣不科學(xué)的地方在于,LR提示成功的事務(wù)你不知道實(shí)際上它到底是成功的還是失敗的。所以,這就需要檢查點(diǎn)了。使用只有事務(wù)執(zhí)行成功才會(huì)出現(xiàn)的文本或者圖片(PS:雖然圖片檢查點(diǎn)我從來(lái)沒(méi)用過(guò))來(lái)作為事務(wù)是否執(zhí)行成功的標(biāo)準(zhǔn)。
      三、如何添加檢查點(diǎn)
      使用文本檢查點(diǎn)(下面簡(jiǎn)稱檢查點(diǎn))需要使用web_reg_find函數(shù)。函數(shù)的使用詳見(jiàn)LR幫助手冊(cè),如果不會(huì)用可以下面的實(shí)戰(zhàn)部分。
      另外說(shuō)明一下如果web_reg_find查找中文失敗,完全可以查找英文,只要能實(shí)現(xiàn)檢查點(diǎn)功能就可以了,如果執(zhí)意要查找英文,請(qǐng)將Record-Options 中勾選support charset中的UTF-8后重新錄制。
      四、如何選擇檢查點(diǎn)
      選擇什么作為檢查點(diǎn),這是困擾了很久了一個(gè)問(wèn)題。就拿登陸來(lái)說(shuō),并不是所有的系統(tǒng)登陸完成后系統(tǒng)跳轉(zhuǎn)到登陸成功的頁(yè)面。這里這需要借助運(yùn)行時(shí)查看器(run-time viewer)來(lái)幫助我們查找合適的檢查點(diǎn)。運(yùn)行時(shí)查看器在選擇工具(tools)-常規(guī)選項(xiàng)(general Options)-顯示(Display) ,選擇 打開(kāi)運(yùn)行時(shí)查看器和自動(dòng)排列窗口。
      運(yùn)行時(shí)查看器的使用我還得感謝我們組成員文武同學(xué)。我還老吐槽他老開(kāi)著這沒(méi)用的玩意干嘛,我承認(rèn)我錯(cuò)了。
     五、實(shí)戰(zhàn)
      以網(wǎng)站www.huhoo.com(一不小心透露了經(jīng)緯度)登陸舉例,錄制登陸腳本后回放,回放的時(shí)候打開(kāi)運(yùn)行時(shí)查看器。可以看到登陸成功后發(fā)回這樣的信息。
      
    圖1 登陸成功后返回信息
      然后修改腳本,故意將用戶名的密碼弄錯(cuò),重新回放
      
    圖2 登陸錯(cuò)誤后返回信息
      結(jié)合兩張圖可以看出,用”code”:0作為檢查點(diǎn)比較合適。因?yàn)檫@樣的文本在登陸失敗時(shí)沒(méi)有出現(xiàn)。但是如果用“msg”來(lái)作為檢查點(diǎn)就不合適,因?yàn)椴还艿顷懗晒褪《汲霈F(xiàn)了這也的文本,不能作為檢查登陸成功的標(biāo)準(zhǔn)。
      檢查點(diǎn)示例代碼如下:
    web_reg_find("Text=\"code\":0","SaveCount=Code_Count", LAST );
    lr_start_transaction("login");
    web_submit_data("login.quick",
    "Action=http://www.huhoo.com/p/login.quick/",
    ……
    "Name=account", "Value=XXXXXX", ENDITEM,
    "Name=password", "Value=XXXXX", ENDITEM,
    LAST);
    if (atoi(lr_eval_string("{Code_Count}")) > 0){
    //lr_output_message("Log on successful.");
    lr_end_transaction("login", LR_PASS);
    }
    else{
    lr_error_message("Log on failed");
    lr_end_transaction("login", LR_FAIL);
    return -1;
    }
      完整腳本下載:傳送門
      說(shuō)明:
      腳本中用戶名,密碼已經(jīng)被我用XXX替換,如果想用此腳本做實(shí)驗(yàn),請(qǐng)到虎虎官網(wǎng)www.huhoo.com注冊(cè)用戶,并將用戶名寫入腳本中。

    posted @ 2014-07-07 21:31 順其自然EVO 閱讀(678) | 評(píng)論 (0)編輯 收藏

    Ant之build.xml詳解

    Ant的概念
      可能有些讀者并不連接什么是Ant以及入可使用它,但只要使用通過(guò)Linux系統(tǒng)得讀者,應(yīng)該知道m(xù)ake這個(gè)命令。當(dāng)編譯Linux內(nèi)核及一些軟件的源程序時(shí),經(jīng)常要用這個(gè)命令。Make命令其實(shí)就是一個(gè)項(xiàng)目管理工具,而Ant所實(shí)現(xiàn)功能與此類似。像make,gnumake和nmake這些編譯工具都有一定的缺陷,但是Ant卻克服了這些工具的缺陷。最初Ant開(kāi)發(fā)者在開(kāi)發(fā)跨平臺(tái)的應(yīng)用時(shí),用樣也是基于這些缺陷對(duì)Ant做了更好的設(shè)計(jì)。
      Ant 與 makefile
      Makefile有一些不足之處,比如很多人都會(huì)碰到的煩人的Tab問(wèn)題。最初的Ant開(kāi)發(fā)者多次強(qiáng)調(diào)”只是我在Tab前面加了一個(gè)空格,所以我的命令就不能執(zhí)行”。有一些工具在一定程度上解決了這個(gè)問(wèn)題,但還是有很多其他的問(wèn)題。Ant則與一般基于命令的工具有所不同,它是Java類的擴(kuò)展。Ant運(yùn)行需要的XML格式的文件不是Shell命令文件。它是由一個(gè)Project組成的,而一個(gè)Project又可分成可多target,target再細(xì)分又分成很多task,每一個(gè)task都是通過(guò)一個(gè)實(shí)現(xiàn)特定接口的java類來(lái)完成的。
      Ant的優(yōu)點(diǎn)
      Ant是Apache軟件基金會(huì)JAKARTA目錄中的一個(gè)子項(xiàng)目,它有以下的優(yōu)點(diǎn)??缙脚_(tái)性。Ant是存Java語(yǔ)言編寫的,所示具有很好的跨平臺(tái)性。操作簡(jiǎn)單。Ant是由一個(gè)內(nèi)置任務(wù)和可選任務(wù)組成的。Ant運(yùn)行時(shí)需要一個(gè)XML文件(構(gòu)建文件)。Ant通過(guò)調(diào)用target樹,就可以執(zhí)行各種task。每個(gè)task實(shí)現(xiàn)了特定接口對(duì)象。由于Ant構(gòu)建文件時(shí)XML格式的文件,所以和容易維護(hù)和書寫,而且結(jié)構(gòu)很清晰。Ant可以集成到開(kāi)發(fā)環(huán)境中。由于Ant的跨平臺(tái)性和操作簡(jiǎn)單的特點(diǎn),它很容易集成到一些開(kāi)發(fā)環(huán)境中去。
      Ant 開(kāi)發(fā)Ant的構(gòu)建文件當(dāng)開(kāi)始一個(gè)新的項(xiàng)目時(shí),首先應(yīng)該編寫Ant構(gòu)建文件。構(gòu)建文件定義了構(gòu)建過(guò)程,并被團(tuán)隊(duì)開(kāi)發(fā)中每個(gè)人使用。Ant構(gòu)建文件默認(rèn)命名為build.xml,也可以取其他的名字。只不過(guò)在運(yùn)行的時(shí)候把這個(gè)命名當(dāng)作參數(shù)傳給Ant。構(gòu)建文件可以放在任何的位置。一般做法是放在項(xiàng)目頂層目錄中,這樣可以保持項(xiàng)目的簡(jiǎn)潔和清晰。下面是一個(gè)典型的項(xiàng)目層次結(jié)構(gòu)。
      (1) src存放文件。
      (2) class存放編譯后的文件。
      (3) lib存放第三方JAR包。
      (4) dist存放打包,發(fā)布以后的代碼。
      Ant構(gòu)建文件是XML文件。每個(gè)構(gòu)建文件定義一個(gè)唯一的項(xiàng)目(Project元素)。每個(gè)項(xiàng)目下可以定義很多目標(biāo)(target元素),這些目標(biāo)之間可以有依賴關(guān)系。當(dāng)執(zhí)行這類目標(biāo)時(shí),需要執(zhí)行他們所依賴的目標(biāo)。每個(gè)目標(biāo)中可以定義多個(gè)任務(wù),目標(biāo)中還定義了所要執(zhí)行的任務(wù)序列。Ant在構(gòu)建目標(biāo)時(shí)必須調(diào)用所定義的任務(wù)。任務(wù)定義了Ant實(shí)際執(zhí)行的命令。Ant中的任務(wù)可以為3類。
      (1) 核心任務(wù)。核心任務(wù)是Ant自帶的任務(wù)。
      (2) 可選任務(wù)??蛇x任務(wù)實(shí)來(lái)自第三方的任務(wù),因此需要一個(gè)附加的JAR文件。
      (3) 用戶自定義的任務(wù)。用戶自定義的任務(wù)實(shí)用戶自己開(kāi)發(fā)的任務(wù)。
      1.<project>標(biāo)簽
      每個(gè)構(gòu)建文件對(duì)應(yīng)一個(gè)項(xiàng)目。<project>標(biāo)簽時(shí)構(gòu)建文件的根標(biāo)簽。它可以有多個(gè)內(nèi)在屬性,就如代碼中所示,其各個(gè)屬性的含義分別如下。
      (1) default表示默認(rèn)的運(yùn)行目標(biāo),這個(gè)屬性是必須的。
      (2) basedir表示項(xiàng)目的基準(zhǔn)目錄。
      (3) name表示項(xiàng)目名。
      (4) description表示項(xiàng)目的描述。
      每個(gè)構(gòu)建文件都對(duì)應(yīng)于一個(gè)項(xiàng)目,但是大型項(xiàng)目經(jīng)常包含大量的子項(xiàng)目,每一個(gè)子項(xiàng)目都可以有自己的構(gòu)建文件。
      2.<target>標(biāo)簽
      一個(gè)項(xiàng)目標(biāo)簽下可以有一個(gè)或多個(gè)target標(biāo)簽。一個(gè)target標(biāo)簽可以依賴其他的target標(biāo)簽。例如,有一個(gè)target用于編譯程序,另一個(gè)target用于聲稱可執(zhí)行文件。在生成可執(zhí)行文件之前必須先編譯該文件,因策可執(zhí)行文件的target依賴于編譯程序的target。Target的所有屬性如下。
      (1) name表示標(biāo)明,這個(gè)屬性是必須的。
      (2) depends表示依賴的目標(biāo)。
      (3) if表示僅當(dāng)屬性設(shè)置時(shí)才執(zhí)行。
      (4) unless表示當(dāng)屬性沒(méi)有設(shè)置時(shí)才執(zhí)行。
      (5) description表示項(xiàng)目的描述。
      Ant的depends屬性指定了target的執(zhí)行順序。Ant會(huì)依照depends屬性中target出現(xiàn)順序依次執(zhí)行每個(gè)target。在執(zhí)行之前,首先需要執(zhí)行它所依賴的target。程序中的名為run的target的depends屬性compile,而名為compile的target的depends屬性是prepare,所以這幾個(gè)target執(zhí)行的順序是prepare->compile->run。一個(gè)target只能被執(zhí)行一次,即使有多個(gè)target依賴于它。如果沒(méi)有if或unless屬性,target總會(huì)被執(zhí)行。3.<mkdir>標(biāo)簽
      該標(biāo)簽用于創(chuàng)建一個(gè)目錄,它有一個(gè)屬性dir用來(lái)指定所創(chuàng)建的目錄名,其代碼如下:<mkdir dir=”${class.root}”/>通過(guò)以上代碼就創(chuàng)建了一個(gè)目錄,這個(gè)目錄已經(jīng)被前面的property標(biāo)簽所指定。
      4.<jar>標(biāo)簽
      該標(biāo)簽用來(lái)生成一個(gè)JAR文件,其屬性如下。
      (1) destfile表示JAR文件名。
      (2) basedir表示被歸檔的文件名。
      (3) includes表示別歸檔的文件模式。
      (4) exchudes表示被排除的文件模式。
      5.<javac>標(biāo)簽
      該標(biāo)簽用于編譯一個(gè)或一組java文件,其屬性如下:
      (1).srcdir表示源程序的目錄。
      (2).destdir表示class文件的輸出目錄。
      (3).include表示被編譯的文件的模式。
      (4).excludes表示被排除的文件的模式。
      (5).classpath表示所使用的類路徑。
      (6).debug表示包含的調(diào)試信息。
      (7).optimize表示是否使用優(yōu)化。
      (8).verbose 表示提供詳細(xì)的輸出信息。
      (9).fileonerror表示當(dāng)碰到錯(cuò)誤就自動(dòng)停止。
      6.<java>標(biāo)簽
      該標(biāo)簽用來(lái)執(zhí)行編譯生成的.class文件,其屬性如下。
      (1).classname 表示將執(zhí)行的類名。
      (2).jar表示包含該類的JAR文件名。
      (3).classpath所表示用到的類路徑。
      (4).fork表示在一個(gè)新的虛擬機(jī)中運(yùn)行該類。
      (5).failonerror表示當(dāng)出現(xiàn)錯(cuò)誤時(shí)自動(dòng)停止。
      (6).output 表示輸出文件。
      (7).append表示追加或者覆蓋默認(rèn)文件。
      7.<delete>標(biāo)簽
      該標(biāo)簽用于刪除一個(gè)文件或一組文件,去屬性如下:
      (1).file表示要?jiǎng)h除的文件。
      (2).dir表示要?jiǎng)h除的目錄。
      (3).includeEmptyDirs 表示指定是否要?jiǎng)h除空目錄,默認(rèn)值是刪除。
      (4).failonerror 表示指定當(dāng)碰到錯(cuò)誤是否停止,默認(rèn)值是自動(dòng)停止。
      (5).verbose表示指定是否列出所刪除的文件,默認(rèn)值為不列出。
      8.<copy>標(biāo)簽
      該標(biāo)簽用于文件或文件集的拷貝,其屬性如下。
      (1).file 表示源文件。
      (2).tofile 表示目標(biāo)文件。
      (3).todir 表示目標(biāo)目錄。
      (4).overwrite 表示指定是否覆蓋目標(biāo)文件,默認(rèn)值是不覆蓋。
      (5).includeEmptyDirs 表示制定是否拷貝空目錄,默認(rèn)值為拷貝。
      (6).failonerror 表示指定如目標(biāo)沒(méi)有發(fā)現(xiàn)是否自動(dòng)停止,默認(rèn)值是停止。
      (7).verbose 表示制定是否顯示詳細(xì)信息,默認(rèn)值不顯示。
      Ant的數(shù)據(jù)類型
      在構(gòu)建文件中為了標(biāo)識(shí)文件或文件組,經(jīng)常需要使用數(shù)據(jù)類型。數(shù)據(jù)類型包含在
      org.apache.tool.ant.types包中。下面簡(jiǎn)單介紹構(gòu)建文件中一些常用的數(shù)據(jù)類型。
      1. argument 類型
      由Ant構(gòu)建文件調(diào)用的程序,可以通過(guò)<arg>元素向其傳遞命令行參數(shù),如apply,exec和java任務(wù)均可接受嵌套<arg>元素,可以為各自的過(guò)程調(diào)用指定參數(shù)。以下是<arg>的所有屬性。
      (1).values 是一個(gè)命令參數(shù)。如果參數(shù)種有空格,但又想將它作為單獨(dú)一個(gè)值,則使用此屬性。
      (2).file表示一個(gè)參數(shù)的文件名。在構(gòu)建文件中,此文件名相對(duì)于當(dāng)前的工作目錄。
      (3).line表示用空格分隔的多個(gè)參數(shù)列表。
      (4).path表示路徑。
      2.ervironment 類型
      由Ant構(gòu)建文件調(diào)用的外部命令或程序,<env>元素制定了哪些環(huán)境變量要傳遞給正在執(zhí)行的系統(tǒng)命令,<env>元素可以接受以下屬性。
      (1).file表示環(huán)境變量值得文件名。此文件名要被轉(zhuǎn)換位一個(gè)絕對(duì)路徑。
      (2).path表示環(huán)境變量的路徑。Ant會(huì)將它轉(zhuǎn)換為一個(gè)本地約定。
      (3).value 表示環(huán)境變量的一個(gè)直接變量。
      (4).key 表示環(huán)境變量名。
      注意  file path 或 value只能取一個(gè)。
      3.filelist類型,Filelist 是一個(gè)支持命名的文件列表的數(shù)據(jù)類型,包含在一個(gè)filelist類型中的文件不一定是存在的文件。以下是其所有的屬性。
      (1).dir是用于計(jì)算絕對(duì)文件名的目錄。
      (2).files 是用逗號(hào)分隔的文件名列表。
      (3).refid 是對(duì)某處定義的一個(gè)<filelist>的引用。
      注意  dir 和 files 都是必要的,除非指定了refid(這種情況下,dir和files都不允許使用)。
      4.fileset類型
      Fileset 數(shù)據(jù)類型定義了一組文件,并通常表示為<fileset>元素。不過(guò),許多ant任務(wù)構(gòu)建成了隱式的fileset,這說(shuō)明他們支持所有的fileset屬性和嵌套元素。以下為fileset 的屬性列表。
      (1).dir表示fileset 的基目錄。
      (2).casesensitive的值如果為false,那么匹配文件名時(shí),fileset不是區(qū)分大小寫的,其默認(rèn)值為true。
      (3).defaultexcludes 用來(lái)確定是否使用默認(rèn)的排除模式,默認(rèn)為true。
      (4).excludes 是用逗號(hào)分隔的需要派出的文件模式列表。
      (5).excludesfile 表示每行包含一個(gè)排除模式的文件的文件名。
      (6).includes 是用逗號(hào)分隔的,需要包含的文件模式列表。
      (7).includesfile 表示每行包括一個(gè)包含模式的文件名。
      5.patternset 類型
      Fileset 是對(duì)文件的分組,而patternset是對(duì)模式的分組,他們是緊密相關(guān)的概念。<patternset>支持4個(gè)屬性:includes excludex includexfile 和 excludesfile,與fileset相同。Patternset 還允許以下嵌套元素:include,exclude,includefile 和 excludesfile。
     6.filterset 類型
      Filterset定義了一組過(guò)濾器,這些過(guò)濾器將在文件移動(dòng)或復(fù)制時(shí)完成文件的文本替換。
      主要屬性如下:
      (1).begintoken 表示嵌套過(guò)濾器所搜索的記號(hào),這是標(biāo)識(shí)其開(kāi)始的字符串。
      (2).endtoken表示嵌套過(guò)濾器所搜索的記號(hào)這是標(biāo)識(shí)其結(jié)束的字符串。
      (3).id是過(guò)濾器的唯一標(biāo)志符。
      (4).refid是對(duì)構(gòu)建文件中某處定義一個(gè)過(guò)濾器的引用。
      7.Path類型
      Path元素用來(lái)表示一個(gè)類路徑,不過(guò)它還可以用于表示其他的路徑。在用作揖個(gè)屬性時(shí),路經(jīng)中的各項(xiàng)用分號(hào)或冒號(hào)隔開(kāi)。在構(gòu)建的時(shí)候,此分隔符將代替當(dāng)前平臺(tái)中所有的路徑分隔符,其擁有的屬性如下。
      (1).location 表示一個(gè)文件或目錄。Ant在內(nèi)部將此擴(kuò)展為一個(gè)絕對(duì)路徑。
      (2).refid 是對(duì)當(dāng)前構(gòu)建文件中某處定義的一個(gè)path的引用。
      (3).path表示一個(gè)文件或路徑名列表。
      8.mapper類型
      Mapper類型定義了一組輸入文件和一組輸出文件間的關(guān)系,其屬性如下。
      (1).classname 表示實(shí)現(xiàn)mapper類的類名。當(dāng)內(nèi)置mapper不滿足要求時(shí),用于創(chuàng)建定制mapper。
      (2).classpath表示查找一個(gè)定制mapper時(shí)所用的類型路徑。
      (3).classpathref是對(duì)某處定義的一個(gè)類路徑的引用。
      (4).from屬性的含義取決于所用的mapper。
      (5).to屬性的含義取決于所用的mapper。
      (6).type屬性的取值為identity,flatten glob merge  regexp  其中之一,它定義了要是用的內(nèi)置mapper的類型。
      Ant 的運(yùn)行
      安裝好Ant并且配置好路徑之后,在命令行中切換到構(gòu)建文件的目錄,輸入Ant命令就可以運(yùn)行Ant.若沒(méi)有指定任何參數(shù),Ant會(huì)在當(dāng)前目錄下查詢build.xml文件。如果找到了就用該文件作為構(gòu)建文件。如果使用了 –find 選項(xiàng),Ant 就會(huì)在上級(jí)目錄中找構(gòu)建文件,直至到達(dá)文件系統(tǒng)得跟目錄。如果構(gòu)建文件的名字不是build.xml ,則Ant運(yùn)行的時(shí)候就可以使用 –buildfile file,這里file 指定了要使用的構(gòu)建文件的名稱,示例如下:
      Ant如下說(shuō)明了表示當(dāng)前目錄的構(gòu)建文件為build.xml 運(yùn)行 ant 執(zhí)行默認(rèn)的目標(biāo)。
      Ant –buildfile  test.xml使用當(dāng)前目錄下的test.xml 文件運(yùn)行Ant ,執(zhí)行默認(rèn)的目標(biāo)

    posted @ 2014-07-07 21:29 順其自然EVO 閱讀(186) | 評(píng)論 (0)編輯 收藏

    Ant編譯時(shí)遇到的問(wèn)題記錄

     1. 需要使用svnant,從SVN中獲取源碼
      需要使用的擴(kuò)展包:svnant-1.3.1.zip里所有的jar
      下載地址:http://subclipse.tigris.org/files/documents/906/49042/svnant-1.3.1.zip
      build.xml中的寫法
    <!--定義SVN地址-->
    <property name="svnurl" value="http://xx/svn/projectName"/>
    <!-- -->
    <typedef resource="org/tigris/subversion/svnant/svnantlib.xml" />
    <!--定義訪問(wèn)SVN的賬號(hào)和密碼-->
    <svnSetting id="svn.setting" svnkit="true" username="username" password="password"  javahl="false" />
    <!--檢出代碼到${project.dir}變量定義的目錄下-->
    <target name="export">
    <delete dir="${project.dir}" />
    <mkdir dir="${project.dir}" />
    <svn refid="svn.setting">
    <export srcUrl="${svnurl}" destPath="${project.dir}" force="true"/>
    </svn>
    </target>
      2.foreach循環(huán)需要使用ant-contrib-1.0b3.jar
      下載地址請(qǐng)百度
      build.xml中的寫法
      <target name="loop" >
      <foreach list="src" target="all" param="src_loop" delimiter=","></foreach>
      </target>
      3. yguard代碼混淆
      具體介紹參見(jiàn):http://blog.csdn.net/vrix/article/details/7604636
      官網(wǎng)下載地址:http://www.yworks.com/en/downloads.html
      build.xml中的寫法
    <taskdef name="yguard" classname="com.yworks.yguard.YGuardTask"/>
    <yguard>
    <inoutpair in="${輸入.jar}" out="${輸出.jar}"/>
    <shrink logfile="${build.dir}/shrink.xml">
    <keep>
    <class classes="friendly" methods="private" fields="friendly"/>
    <field name="serialVersionUID"/>
    </keep>
    </shrink>
    </yguard>
      4.執(zhí)行腳本操作
      啟動(dòng)tomcat在build.xml中的寫法
    linux
    <target name="start" >
    <echo>start tomcat</echo>
    <exec executable = "${tomcat.dir}/bin/startup.sh" />
    </target>
    windows
    <target name="stop" >
    <echo>stop tomcat</echo>
    <exec executable="cmd" dir="${tomcat.dir}/bin" failonerror="false"  append="true">
    <env key="CATALINA_HOME" path="${tomcat.dir}"/>
    <arg value="/c startup.bat" />
    </exec>
    </target>

    posted @ 2014-07-07 21:28 順其自然EVO 閱讀(216) | 評(píng)論 (0)編輯 收藏

    XSS前端防火墻—天衣無(wú)縫的防護(hù)

      講解了鉤子程序的攻防實(shí)戰(zhàn),并實(shí)現(xiàn)了一套對(duì)框架頁(yè)的監(jiān)控方案,將防護(hù)作用到所有子頁(yè)面。
      到目前為止,我們防護(hù)的深度已經(jīng)差不多,但廣度還有所欠缺。
      例如,我們的屬性鉤子只考慮了 setAttribute,卻忽視還有類似的 setAttributeNode。盡管從來(lái)不用這方法,但并不意味人家不能使用。
      例如,創(chuàng)建元素通常都是 createElement,事實(shí)上 createElementNS 同樣也可以。甚至還可以利用現(xiàn)成的元素 cloneNode,也能達(dá)到目的。因此,這些都是邊緣方法都是值得考慮的。
      下面我們對(duì)之前討論過(guò)的監(jiān)控點(diǎn),進(jìn)行逐一審核。
      內(nèi)聯(lián)事件執(zhí)行 eval
      在第一篇文章結(jié)尾談到,在執(zhí)行回調(diào)的時(shí)候,最好能監(jiān)控 eval,setTimeout('...') 這些能夠解析代碼的函數(shù),以防止執(zhí)行儲(chǔ)存在其他地方的 XSS 代碼。
      先來(lái)列舉下這類函數(shù):
      eval
      setTimeout(String) / setInterval(String)
      Function
      execScript / setImmediate(String)
      事實(shí)上,利用上一篇的鉤子技術(shù),完全可以把它們都監(jiān)控起來(lái)。但現(xiàn)實(shí)并沒(méi)有我們想象的那樣簡(jiǎn)單。
      eval 重寫有問(wèn)題嗎
      eval 不就是個(gè)函數(shù),為什么不可以重寫?
      var raw_fn = window.eval;
      window.eval = function(exp) {
      alert('執(zhí)行eval: ' + exp);
      return raw_fn.apply(this, arguments);
      };
      console.log(eval('1+1'));
      完全沒(méi)問(wèn)題啊。那是因?yàn)榇a太簡(jiǎn)單了,下面這個(gè) Demo 就可以看出山寨版 eval 的缺陷:
      (function() {
      eval('var a=1');
      })();
      alert(typeof a);
      Run
      按理說(shuō)應(yīng)該 undefined 才對(duì),結(jié)果卻是 number。局部變量都跑到全局上來(lái)了。這是什么情況?事實(shí)上,eval 并不是真正意義的函數(shù),而是一個(gè)關(guān)鍵字!想了解詳情請(qǐng)戳這里。
      Function 重寫有意義嗎
      Function 是一個(gè)全局變量,重寫 window.Function 理論上完全可行吧。
      var raw_fn = window.Function;
      window.Function = function() {
      alert('調(diào)用Function');
      return raw_fn.apply(this, arguments);
      };
      var add = Function('a', 'b', 'return a+b');
      console.log( add(1, 2) );
      重寫確實(shí)可行。但現(xiàn)實(shí)卻是不堪一擊的:因?yàn)樗泻瘮?shù)都是 Function 類的實(shí)例,所以訪問(wèn)任何一個(gè)函數(shù)的 constructor 即可得到原始的 Function。
     例如 alert.constructor,就可以繞過(guò)我們的鉤子。甚至可以用匿名函數(shù):
      (function(){}).constructor
      所以,F(xiàn)unction 是永遠(yuǎn)鉤不住的。
      額外的執(zhí)行方法
      就算不用這類函數(shù),仍有相當(dāng)多的辦法執(zhí)行字符串,例如:
      創(chuàng)建腳本,innerHTML = 代碼
      創(chuàng)建腳本,路徑 = data:代碼
      創(chuàng)建框架,路徑 = javascript:代碼
      ......
      看來(lái),想完全把類似 eval 的行為監(jiān)控起來(lái),是不現(xiàn)實(shí)的。不過(guò)作為預(yù)警,我們只監(jiān)控 eval,setTimeout/Interval 也就足夠了。
      可疑模塊攔截
      第二篇談了站外模塊的攔截。之所以稱之『模塊』而不是『腳本』,并非只有腳本元素才具備執(zhí)行能力。框架頁(yè)、插件都是可以運(yùn)行代碼的。
      可執(zhí)行元素
      我們列舉下,能執(zhí)行遠(yuǎn)程模塊的元素:
      腳本
      <script src="..." />
      框架
      <iframe src="...">
      <frame src="...">
      插件(Flash)
      <embed src="...">
      <object data="...">
      <object><param name="moive|src" value="..."></object>
      插件(其他)
      <applet codebase="...">
      這些元素的路徑屬性,都應(yīng)該作為排查的對(duì)象。
      不過(guò),有這么個(gè)元素的存在,可能導(dǎo)致我們的路徑檢測(cè)失效,它就是:
      <base href="...">
      它能重定義頁(yè)面的相對(duì)路徑,顯然是不容忽視的。
      事實(shí)上,除了使用元素來(lái)執(zhí)行站外模塊,還可以使用網(wǎng)絡(luò)通信,獲得站外的腳本代碼,然后再調(diào)用 eval 執(zhí)行:
      AJAX
      目前主流瀏覽器都支持跨域請(qǐng)求,只要服務(wù)端允許就可以。因此,我們需監(jiān)控 XMLHttpRequest::open 方法。如果請(qǐng)求的是站外地址,就得做策略匹配。不通過(guò)則放棄向上調(diào)用,或者拋出一個(gè)異常,或者給 XHR 產(chǎn)生一個(gè) 400 狀態(tài)。
      WebSocket
      WebSocket 和 XHR 類似,也能通過(guò)鉤子的方法進(jìn)行監(jiān)控。
      不過(guò),值得注意的是,WebSocket 并非是個(gè)函數(shù),而是一個(gè)類。因此,在返回實(shí)例的時(shí)候,別忘了將 constructor 改成自己的鉤子,否則就會(huì)泄露原始接口:
      var raw_class = window.WebSocket;
      window.WebSocket = function WebSocket(url, arg) {
      alert('WebSocket 請(qǐng)求:' + url);
      var ins = new raw_class(url, arg);
      // 切記
      ins.constructor = WebSocket;
      return ins;
      };
      var ws = new WebSocket('ws://127.0.0.1:1000');
      另外,因?yàn)樗且粋€(gè)類,所以不要忽略了靜態(tài)方法或?qū)傩裕?/div>
      WebSocket.CONNECTING
      WebSocket.OPEN
      ...
      因此,還需將它們拷貝到鉤子上。
      框架頁(yè)消息
      HTML5 賦予了框架頁(yè)跨域通信的能力。如果沒(méi)有為框架元素建立白名單的話,攻擊者可以嵌入自己的框架頁(yè)面,然后將 XSS 代碼 postMessage 給主頁(yè)面,通過(guò) eval 執(zhí)行。
      不過(guò)為了安全考慮,HTML5 在消息事件里保存了來(lái)源地址,以識(shí)別消息是哪個(gè)頁(yè)面發(fā)出的。
      因?yàn)槭莻€(gè)事件,我們可以使用第一篇文章里提到的方法,對(duì)其進(jìn)行捕獲。每當(dāng)有消息收到時(shí),可以根據(jù)策略,決定是否阻止該事件的傳遞。
    // 我們的防御系統(tǒng)
    (function() {
    window.addEventListener('message', function(e) {
    if (confirm('發(fā)現(xiàn)來(lái)自[' + e.origin + ']的消息:\n\n' + e.data + '\n\n是否攔截?')) {
    e.stopImmediatePropagation();
    }
    }, true);
    })();
    window.addEventListener('message', function(e) {
    alert('收到:' + e.data)
    })
    postMessage('hello', '*');
    Run


      昨天嘗試了一系列的可疑模塊攔截試驗(yàn),盡管最終的方案還存在著一些兼容性問(wèn)題,但大體思路已經(jīng)明確了:
      靜態(tài)模塊:使用 MutationObserver 掃描。
      動(dòng)態(tài)模塊:通過(guò) API 鉤子來(lái)攔截路徑屬性。
      提到鉤子程序,大家會(huì)聯(lián)想到傳統(tǒng)應(yīng)用程序里的 API Hook,以及各種外掛木馬。當(dāng)然,未必是系統(tǒng)函數(shù),任何 CPU 指令都能被改寫成跳轉(zhuǎn)指令,以實(shí)現(xiàn)先運(yùn)行自己的程序。
      無(wú)論是在哪個(gè)層面,鉤子程序的核心理念都是一樣的:無(wú)需修改已有的程序,即可先執(zhí)行我們的程序。
      這是一種鏈?zhǔn)秸{(diào)用的模式。調(diào)用者無(wú)需關(guān)心上一級(jí)的細(xì)節(jié),直管用就是了,即使有額外的操作對(duì)其也是不可見(jiàn)的。從最底層的指令攔截,到語(yǔ)言層面的虛函數(shù)繼承,以及更高層次的面向切面,都帶有這類思想。
      對(duì)于 JavaScript 這樣靈活的語(yǔ)言,任何模式都可以實(shí)現(xiàn)。之前做過(guò)一個(gè)網(wǎng)頁(yè)版的變速齒輪,用的就是這類原理。
      JavaScript 鉤子小試
      要實(shí)現(xiàn)一個(gè)最基本的鉤子程序非常簡(jiǎn)單,昨天已演示過(guò)了。現(xiàn)在我們?cè)賮?lái)給 setAttribute 接口實(shí)現(xiàn)一個(gè)鉤子:
    // 保存上級(jí)接口
    var raw_fn = Element.prototype.setAttribute;
    // 勾住當(dāng)前接口
    Element.prototype.setAttribute = function(name, value) {
    // 額外細(xì)節(jié)實(shí)現(xiàn)
    if (this.tagName == 'SCRIPT' && /^src$/i.test(name)) {
    if (/xss/.test(value)) {
    if (confirm('試圖加載可疑模塊:\n\n' + url + '\n\n是否攔截?')) {
    return;
    }
    }
    }
    raw_fn.apply(this, arguments);
    };
    // 創(chuàng)建腳本
    var el = document.createElement('script');
    el.setAttribute('SRC', 'http://www.etherdream.com/xss/alert.js');
    document.body.appendChild(el);
    Run
      類似昨天的訪問(wèn)器攔截,現(xiàn)在我們對(duì) setAttribute 也進(jìn)行類似的監(jiān)控。因?yàn)樗莻€(gè)函數(shù),所有主流瀏覽器都兼容。
      鉤子泄露
      看起來(lái)似乎毫無(wú)難度,而且也沒(méi)什么不對(duì)的地方,這不就可以了嗎?
      如果最終就用這代碼,那也太挫了。我們把原始接口都暴露在全局變量里了,攻擊者只要拿了這個(gè)變量,即可繞過(guò)我們的檢測(cè)代碼:
      var el = document.createElement('script');
      // 直接調(diào)用原始接口
      raw_fn.call(el, 'SRC', 'http://www.etherdream.com/xss/alert.js');
      document.body.appendChild(el);
      Run

    posted @ 2014-07-07 21:27 順其自然EVO 閱讀(182) | 評(píng)論 (0)編輯 收藏

    如何對(duì)所發(fā)現(xiàn)的缺陷進(jìn)行嚴(yán)密的等級(jí)劃分?

     提問(wèn):如何對(duì)所發(fā)現(xiàn)的缺陷進(jìn)行嚴(yán)密的等級(jí)劃分?
      回答:測(cè)試過(guò)程中發(fā)現(xiàn)的缺陷一般分為如下幾類
      功能問(wèn)題(FunctionError):對(duì)產(chǎn)品、項(xiàng)目質(zhì)量有影響,但尚難以確定是否是錯(cuò)誤,暫時(shí)無(wú)法解決
      功能缺陷(FunctionDefect):不滿足用戶需求等bug的總稱
      頁(yè)面缺陷(UIDefect):頁(yè)面美觀性、協(xié)調(diào)性、錯(cuò)別字等
      建議類(Suggestion):對(duì)產(chǎn)品、項(xiàng)目的建議性意見(jiàn),不強(qiáng)制要求修改
      硬件性能:進(jìn)行性能測(cè)試時(shí)使用,暫定:網(wǎng)絡(luò)延時(shí)、內(nèi)存問(wèn)題、CPU占用、硬盤問(wèn)題
      安全性問(wèn)題:進(jìn)行系統(tǒng)安全測(cè)試時(shí)使用,暫不訂具體標(biāo)準(zhǔn)
      業(yè)務(wù)流程問(wèn)題:進(jìn)行業(yè)務(wù)流程測(cè)試時(shí)進(jìn)行
      數(shù)據(jù)庫(kù)性能:暫不執(zhí)行
      模塊間接口問(wèn)題:涉及有模塊間數(shù)據(jù)傳遞時(shí)使用
      其他(Other):其它
      根據(jù)各類缺陷的嚴(yán)重程度將缺陷分為5個(gè)等級(jí),具體如下:
      1)低(Low)
      建議類錯(cuò)誤,對(duì)軟件的改進(jìn)意見(jiàn)或者建議。如:
      a)功能建議
      b)操作建議
      c)校驗(yàn)建議
      d)說(shuō)明建議
      e)UI建議
      2)中(Medium)
      使操作者不合理或者不方便或操作遇到麻煩,但它不影響執(zhí)行工作功能或重要功能,次要功能,對(duì)產(chǎn)品使用影響不大。如:
      界面錯(cuò)誤
      a)使操作者不方便或者遇到麻煩,但不影響執(zhí)行工作功能的實(shí)現(xiàn)
      b)界面、控件的擺布、圖標(biāo)、輸入輸出不規(guī)范
      提示類錯(cuò)誤
      a)刪除操作未給出提示
      b)長(zhǎng)時(shí)間操作未給出提示
      c)提示窗口文字未采用行業(yè)術(shù)語(yǔ)
      d)出錯(cuò)沒(méi)有提示
      其他錯(cuò)誤
      a)不符合編碼標(biāo)準(zhǔn)
      b)輔助說(shuō)明描述不清楚、不規(guī)范
      c)快捷鍵無(wú)效,快捷鍵錯(cuò)誤操作
      d)打印內(nèi)容、格式錯(cuò)誤
      3)高(High)
      影響系統(tǒng)正常運(yùn)行的缺陷,主要功能出現(xiàn)錯(cuò)誤,影響到產(chǎn)品的使用。如:
      數(shù)據(jù)庫(kù)缺陷:數(shù)據(jù)庫(kù)設(shè)計(jì)未達(dá)到第三范式的要求或需求規(guī)格說(shuō)明的格式水平
      操作錯(cuò)誤:因錯(cuò)誤操作迫使程序中斷
      功能錯(cuò)誤:
      a)程序功能無(wú)法實(shí)現(xiàn)
      b)程序功能實(shí)現(xiàn)錯(cuò)誤
      其他錯(cuò)誤:
      a)腳本錯(cuò)誤
      b)軟件產(chǎn)品的編譯,打包,安裝,卸載錯(cuò)誤
      4)非常高(Very High)
      規(guī)定的功能沒(méi)有實(shí)現(xiàn)或不完整或產(chǎn)生錯(cuò)誤結(jié)果;設(shè)計(jì)不合理造成性能低下,影響系統(tǒng)的運(yùn)營(yíng);使系統(tǒng)不穩(wěn)定、或破壞數(shù)據(jù);而且是常規(guī)操作中經(jīng)常發(fā)生或非常規(guī)操作中不可避免的主要問(wèn)題,且沒(méi)有辦法更正(重新安裝或重新啟動(dòng)軟件不屬更正辦法),須盡快修正,如:
      數(shù)據(jù)缺陷
      a)數(shù)據(jù)計(jì)算錯(cuò)誤
      b)數(shù)據(jù)約束錯(cuò)誤
      c)數(shù)據(jù)輸入、輸出錯(cuò)誤
      數(shù)據(jù)庫(kù)缺陷
      a)數(shù)據(jù)庫(kù)發(fā)生死鎖
      b)數(shù)據(jù)庫(kù)的表、業(yè)務(wù)規(guī)則、缺省值未加完整性等約束條件
      c)數(shù)據(jù)庫(kù)連接錯(cuò)誤
      d)數(shù)據(jù)通訊錯(cuò)誤
      接口缺陷
      a)程序接口錯(cuò)誤
      b)硬件接口、通訊錯(cuò)誤
      功能錯(cuò)誤:
      a)程序功能無(wú)法實(shí)現(xiàn)
      b)程序功能實(shí)現(xiàn)錯(cuò)誤
      5)緊急(Critical)
      不能執(zhí)行正常工作或重要功能,使系統(tǒng)崩潰或資源嚴(yán)重不足,數(shù)據(jù)丟失(金幣,包子)非常死機(jī)等導(dǎo)致系統(tǒng)不能繼續(xù)運(yùn)行須馬上修正,如:
      a)由于程序所引起的死機(jī),非法退出
      b)程序死循環(huán)
      c)性能與需求不一致(壓力測(cè)試)
      d)存在安全性與保密性問(wèn)題
      e)文件打開(kāi)與保存錯(cuò)誤
      總結(jié):
      1級(jí)-建議問(wèn)題的軟件缺陷(Enhancemental):由問(wèn)題提出人對(duì)測(cè)試對(duì)象的改進(jìn)意見(jiàn)或測(cè)試人員提出的建議、質(zhì)疑。
      2級(jí)—較小錯(cuò)誤的軟件缺陷(Minor),使操作者不方便或遇到麻煩,但它不影響功能過(guò)的操作和執(zhí)行,如錯(cuò)別字、界面不規(guī)范(字體大小不統(tǒng)一,文字排列不整齊,可輸入?yún)^(qū)域和只讀區(qū)域沒(méi)有明顯的區(qū)分標(biāo)志),輔助說(shuō)明描述不清楚。
      3級(jí)—一般錯(cuò)誤的軟件缺陷(major):次要功能沒(méi)有完全實(shí)現(xiàn)但不影響使用。如提示信息不太準(zhǔn)確,或用戶界面差,操作時(shí)間長(zhǎng),模塊功能部分失效等,打印內(nèi)容、格式錯(cuò)誤,刪除操作未給出提示,數(shù)據(jù)庫(kù)表中有過(guò)多的空字段等。
      4級(jí)—嚴(yán)重錯(cuò)誤的軟件缺陷(critical):系統(tǒng)的主要功能部分喪失、數(shù)據(jù)不能保存,系統(tǒng)的次要功能完全喪失。問(wèn)題局限在本模塊,導(dǎo)致模塊功能失效或異常退出。如致命的錯(cuò)誤聲明,程序接口錯(cuò)誤,數(shù)據(jù)庫(kù)的表、業(yè)務(wù)規(guī)則、缺省值未加完整性等約束條件
      5級(jí)—致命的軟件缺陷(Fatal):造成系統(tǒng)或應(yīng)用程序崩潰、死機(jī)、系統(tǒng)掛起,或造成數(shù)據(jù)丟失,主要功能完全喪失,導(dǎo)致本模塊以及相關(guān)模塊異常等問(wèn)題。如代碼錯(cuò)誤,死循環(huán),數(shù)據(jù)庫(kù)發(fā)生死鎖、與數(shù)據(jù)庫(kù)連接錯(cuò)誤或數(shù)據(jù)通訊錯(cuò)誤,未考慮異常操作,功能錯(cuò)誤等。
    原帖地址:http://bbs.51testing.com/thread-1000328-1-1.html

    posted @ 2014-07-07 21:25 順其自然EVO 閱讀(280) | 評(píng)論 (0)編輯 收藏

    JAVA Reflection(反射機(jī)制)

     Java 反射機(jī)制
      反射機(jī)制簡(jiǎn)介
      反射機(jī)制應(yīng)用示例
      簡(jiǎn)單的Ioc實(shí)現(xiàn)
      代理模式
      Java動(dòng)態(tài)代理
      簡(jiǎn)單的Aop實(shí)現(xiàn)
      “程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語(yǔ)言稱為動(dòng)態(tài)語(yǔ)言”。從這個(gè)觀點(diǎn)看,Perl,PythonRuby是動(dòng)態(tài)語(yǔ)言,C++,Java,C#不是動(dòng)態(tài)語(yǔ)言。
      盡管在這樣得定義與分類下Java不是動(dòng)態(tài)語(yǔ)言,它卻有著一個(gè)非常突出的動(dòng)態(tài)相關(guān)的機(jī)制:反射機(jī)制 (Reflection)。
      什么是反射?
      反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問(wèn)、檢測(cè)和修改它本身狀態(tài)或者行為的一種能力。
      JAVA反射機(jī)制都是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語(yǔ)言的反射機(jī)制。
      JAVA反射機(jī)制(Reflection)
      動(dòng)態(tài)獲取類的信息,以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能。
      主要提供了以下功能:
      在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類;
      在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;
      在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法;
      在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法;
      生成動(dòng)態(tài)代理。
      JAVA反射機(jī)制包
      在 JDK 中,主要由以下類來(lái)實(shí)現(xiàn) Java  反射機(jī)制,這些類都位于 java.lang.reflect包中。
      Class 類:代表一個(gè)類。
      Field 類:代表類的成員變量(成員變量也稱為類的屬性)。
      Method 類:代表類的方法。
      Constructor 類:代表類的構(gòu)造方法。
      Array 類:提供了動(dòng)態(tài)創(chuàng)建數(shù)組,以及訪問(wèn)數(shù)組元素的靜態(tài)方法。
      java.lang.Class
      static Class forName(String className)
      返回描述類名為className的Class對(duì)象
      Object newInstance()
      返回一個(gè)類的一個(gè)新實(shí)例
      Field[] getFields()
      返回包含F(xiàn)ield對(duì)象的數(shù)組,這些對(duì)象記錄了這個(gè)類或者其超類的公共域
      Field[] getDeclaredField()
      返回包含F(xiàn)ield對(duì)象的數(shù)組,這些對(duì)象記錄了這個(gè)類的全部域
      Method[] getMethods()                             返回這個(gè)類或者其超類所有的公有方法
      Method[] getDeclareMethods()                 返回這個(gè)類或者接口的所有方法,不包括超類繼承的方法
      Constructor[] getConstructors()                返回所有包含了Class對(duì)象所描述類的公有構(gòu)造器
      Constructor[] getDeclaredConstructors()  返回包含了Class對(duì)象所描述的類的所有構(gòu)造器
     Java.lang.reflect.Constructor
      Class[] getParameterTypes()
      返回一個(gè)用于描述參數(shù)類型的Class對(duì)象數(shù)組
      getReturnType()
      返回一個(gè)用于描述返回類型的Class對(duì)象
      int getModifiers()
      返回一個(gè)用于描述方法拋出的異常類型的Class對(duì)象數(shù)組
      Class getDeclaringClass()
      返回一個(gè)用于描述類中定義的構(gòu)造器、方法或域的Class對(duì)象
      通過(guò)反射實(shí)例化參數(shù)
      平常實(shí)例化對(duì)象通常使用new關(guān)鍵字。但是使用new關(guān)鍵字實(shí)例化的對(duì)象具有強(qiáng)耦合性。New對(duì)象無(wú)法勝任未知對(duì)象的實(shí)例化,這時(shí)候只能通過(guò)反射動(dòng)態(tài)生成。例如Spring的DI。
      實(shí)例化無(wú)參構(gòu)造函數(shù)的對(duì)象
      Class.newInstance()
      Class.getConstructor(new Class[]{}).newInstance(new Object[]{})
      實(shí)例化帶參構(gòu)造函數(shù)的對(duì)象
      Clazz.getConstructor(Class<?> ...ParameterType).newInstance(Object ...initargs)
      反射機(jī)制舉例
    import java.lang.reflect.*;
    public class DumpMethods {
    public static void main(String args[]) throws Exception{
    //加載并初始化命令行參數(shù)指定的類
    Class classType = Class.forName(args[0]);
    //獲得類的所有方法
    Method methods[] = classType.getDeclaredMethods();
    for(int i = 0; i < methods.length; i++)
    System.out.println(methods[i].toString());
    }
    }
    輸入:java DumpMethods java.util.Stack
    public synchronized java.lang.Object java.util.Stack.pop()
    public java.lang.Object java.util.Stack.push(java.lang.Object)
    public boolean java.util.Stack.empty()
    public synchronized java.lang.Object java.util.Stack.peek()
    public synchronized int java.util.Stack.search(java.lang.Object)
      運(yùn)用反射機(jī)制調(diào)用方法
      getMethod和invoke方法的時(shí)序圖


     獲取反射對(duì)象
    import java.lang.reflect.*;
    public class ReflectTester {
    public Object  copy(Object object) throws Exception{
    //獲得對(duì)象的類型
    Class classType=object.getClass();
    System.out.println("Class:"+classType.getName());
    //通過(guò)默認(rèn)構(gòu)造方法創(chuàng)建一個(gè)新的對(duì)象
    Object  objectCopy=classType.getConstructor(new Class[]{}).
    newInstance(new Object[]{});
    //獲得對(duì)象的所有屬性
    Field fields[]=classType.getDeclaredFields();
    for(int i=0; i<fields.length;i++){
    Field field=fields[i];
    String fieldName=field.getName();
    String firstLetter=fieldName.substring(0,1).toUpperCase();
    //獲得和屬性對(duì)應(yīng)的 getXXX()方法的名字
    String getMethodName="get"+firstLetter+fieldName.substring(1);
    //獲得和屬性對(duì)應(yīng)的 setXXX()方法的名字
    String setMethodName="set"+firstLetter+fieldName.substring(1);
    //獲得和屬性對(duì)應(yīng)的 getXXX()方法
    Method getMethod=classType.getMethod(getMethodName,new Class[]{});
    //獲得和屬性對(duì)應(yīng)的 setXXX()方法
    Method setMethod=classType.getMethod(setMethodName,new Class[]{field.getType()});
    //調(diào)用原對(duì)象的 getXXX()方法
    Object value=getMethod.invoke(object,new Object[]{});
    System.out.println(fieldName+":"+value);
    //調(diào)用復(fù)制對(duì)象的 setXXX()方法
    setMethod.invoke(objectCopy,new Object[]{value});
    }
    return objectCopy;
    }
    public static void main(String[] args) throws Exception{
    Customer customer=new Customer("Tom",21);
    customer.setId(new Long(1));
    Customer customerCopy=(Customer)new ReflectTester().copy(customer);
    System.out.println("Copy information:"+customerCopy.getName()+
    “ "+  customerCopy.getAge());
    }
    }
      運(yùn)用反射機(jī)制調(diào)用方法
    class Customer{
    //Customer 類是一個(gè) JavaBean
    private Long id;
    private String name;
    private int age;
    public Customer(){}
    public Customer(String name,int age){
    this.name=name;
    this.age=age;
    }
    public Long getId(){return id;}
    public void setId(Long id){this.id=id;}
    public String getName(){return name;}
    public void setName(String name){this.name=name;}
    public int getAge(){return age;}
    public void setAge(int age){this.age=age;}
    }
    import java.lang.reflect.*;
    public class InvokeTester {
    public int add(int param1,int param2){  return param1+param2;   }
    public String echo(String msg){   return "echo:"+msg; }
    public static void main(String[] args) throws Exception{
    Class classType=InvokeTester.class;
    Object invokeTester=classType.newInstance();
    //調(diào)用 InvokeTester 對(duì)象的 add()方法
    Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});
    Object result=addMethod.invoke(invokeTester,
    new Object[]{new Integer(100),new Integer(200)});
    System.out.println((Integer)result);
    //調(diào)用 InvokeTester 對(duì)象的 echo()方法
    Method echoMethod=classType.getMethod("echo",new Class[]{String.class});
    result=echoMethod.invoke(invokeTester,new Object[]{"Hello"});
    System.out.println((String)result);
    }
    }

    posted @ 2014-07-07 20:53 順其自然EVO 閱讀(128) | 評(píng)論 (0)編輯 收藏

    Java高速、多線程虛擬內(nèi)存的實(shí)現(xiàn)

     本文作者Alex已經(jīng)從事Java開(kāi)發(fā)15年了,最近幫助開(kāi)發(fā)了COBOL和Magik語(yǔ)言的JVM 。當(dāng)前,他正致力于Micro Focus的Java性能測(cè)試工具。在本文中,他闡述了在標(biāo)準(zhǔn)硬件中實(shí)現(xiàn)高速、多線程虛擬內(nèi)存的可能性及方案。原文內(nèi)容如下。
      你想在標(biāo)準(zhǔn)硬件上運(yùn)行TB級(jí)甚至PB級(jí)內(nèi)存的JVM嗎?你想與內(nèi)存交互一樣讀寫文件,且無(wú)需關(guān)心文件的打開(kāi)、關(guān)閉、讀、寫嗎?
      JVM的64位地址空間使這些成為可能。
      首先,不要在觀念上將內(nèi)存和磁盤進(jìn)行區(qū)分,而是統(tǒng)一處理為內(nèi)存映射文件。在32位地址空間時(shí),內(nèi)存映射文件只是為了高速訪問(wèn)磁盤;因?yàn)槭芟抻谔摂M機(jī)的有限地址空間,并不支持大規(guī)模的虛擬內(nèi)存或大文件。如今JVM已經(jīng)發(fā)展為64位,而且可以在64位操作系統(tǒng)上運(yùn)行。在一個(gè)進(jìn)程的地址空間中,內(nèi)存映射文件大小就可以達(dá)到TB甚至PB。
      進(jìn)程無(wú)需關(guān)心內(nèi)存是在RAM或是磁盤上。操作系統(tǒng)會(huì)負(fù)責(zé)處理,而且處理得非常高效。
      我們可以使用Java的MappedByteBuffer類訪問(wèn)內(nèi)存映射文件。該類的實(shí)例對(duì)象與普通的ByteBuffer一樣,但包含的內(nèi)存是虛擬的——可能是在磁盤上,也可能是在RAM中。但無(wú)論哪種方式,都是由操作系統(tǒng)負(fù)責(zé)處理。因?yàn)榈腂yteBuffer的大小上限是Intger.MAX_VALUE,我們需要若干個(gè)ByteBuffer來(lái)映射大量?jī)?nèi)存。在這個(gè)示例中,我映射了40GB。
      這是因?yàn)槲业腗ac只有16GB內(nèi)存,下面代碼證明了這一點(diǎn)!
    public MapperCore(String prefix, long size) throws IOException {
    coreFile = new File(prefix + getUniqueId() + ".mem");
    // This is a for testing - to avoid the disk filling up
    coreFile.deleteOnExit();
    // Now create the actual file
    coreFileAccessor = new RandomAccessFile(coreFile, "rw");
    FileChannel channelMapper = coreFileAccessor.getChannel();
    long nChunks = size / TWOGIG;
    if (nChunks > Integer.MAX_VALUE)
    throw new ArithmeticException("Requested File Size Too Large");
    length = size;
    long countDown = size;
    long from = 0;
    while (countDown > 0) {
    long len = Math.min(TWOGIG, countDown);
    ByteBuffer chunk = channelMapper.map(MapMode.READ_WRITE, from, len);
    chunks.add(chunk);
    from += len;
    countDown -= len;
    }
    }
      上面的代碼在虛擬內(nèi)存創(chuàng)建了40GB MappedByteBuffer對(duì)象列表。讀取和寫入時(shí)只需要注意處理兩個(gè)內(nèi)存模塊的跨越訪問(wèn)。完整代碼的可以在這里找到。
    線程
      一個(gè)極其強(qiáng)大且簡(jiǎn)單易用的方法就是線程。但是普通的Java IO簡(jiǎn)直就是線程的噩夢(mèng)。兩個(gè)線程無(wú)法在不引起沖突的情況下同時(shí)訪問(wèn)相同的數(shù)據(jù)流或RandomAccessFile 。雖然可以使用非阻塞IO,但是這樣做會(huì)增加代碼的復(fù)雜性并對(duì)原有的代碼造成侵入。
      與其他的內(nèi)存線程一樣,內(nèi)存映射文件也是由操作系統(tǒng)來(lái)處理??梢愿鶕?jù)讀寫需要,在同一時(shí)刻盡可能多的使用線程。我的測(cè)試代碼有128個(gè)線程,而且工作得很好(雖然機(jī)器發(fā)熱比較大)。唯一重要的技巧是復(fù)用MappedByteBuffer對(duì)象,避免自身位置狀態(tài)引發(fā)問(wèn)題。
      現(xiàn)在可以執(zhí)行下面的測(cè)試:
    @Test
    public void readWriteCycleThreaded() throws IOException {
    final MapperCore mapper = new MapperCore("/tmp/MemoryMap", BIG_SIZE);
    final AtomicInteger fails = new AtomicInteger();
    final AtomicInteger done = new AtomicInteger();
    Runnable r = new Runnable() {
    public void run() {
    try {
    // Set to 0 for sequential test
    long off = (long) ((BIG_SIZE - 1024) * Math.random());
    System.out.println("Running new thread");
    byte[] bOut = new byte[1024];
    double counts = 10000000;
    for (long i = 0; i < counts; ++i) {
    ByteBuffer buf = ByteBuffer.wrap(bOut);
    long pos = (long) (((BIG_SIZE - 1024) * (i / counts)) + off)
    % (BIG_SIZE - 1024);
    // Align with 8 byte boundary
    pos = pos / 8;
    pos = pos * 8;
    for (int j = 0; j < 128; ++j) {
    buf.putLong(pos + j * 8);
    }
    mapper.put(pos, bOut);
    byte[] bIn = mapper.get(pos, 1024);
    buf = ByteBuffer.wrap(bIn);
    for (int j = 0; j < 128; ++j) {
    long val = buf.getLong();
    if (val != pos + j * 8) {
    throw new RuntimeException("Error at " + (pos + j * 8) + " was " + val);
    }
    }
    }
    System.out.println("Thread Complete");
    } catch (Throwable e) {
    e.printStackTrace();
    fails.incrementAndGet();
    } finally {
    done.incrementAndGet();
    }
    }
    };
    int nThreads = 128;
    for (int i = 0; i < nThreads; ++i) {
    new Thread(r).start();
    }
    while (done.intValue() != nThreads) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // ignore
    }
    }
    if (fails.intValue() != 0) {
    throw new RuntimeException("It failed " + fails.intValue());
    }
    }
      我曾嘗試進(jìn)行其他形式的IO,但是只要像上面那樣運(yùn)行128個(gè)線程,性能都不如上面的方法。我在四核、超線程I7 Retina MacBook Pro上嘗試過(guò)。代碼運(yùn)行時(shí)會(huì)啟動(dòng)128個(gè)線程,超出CPU的最大負(fù)載(800%),直到操作系統(tǒng)檢測(cè)到該進(jìn)程的內(nèi)存不足。在這個(gè)時(shí)候,系統(tǒng)開(kāi)始對(duì)內(nèi)存映射文件的讀寫進(jìn)行分頁(yè)。為實(shí)現(xiàn)這一目標(biāo),內(nèi)核會(huì)占用一定的CPU,Java進(jìn)程的性能會(huì)下降到650~750%。Java無(wú)需關(guān)心讀取、寫入、同步或類似的東西——操作系統(tǒng)會(huì)負(fù)責(zé)處理。
      結(jié)果會(huì)有所不同
      如果讀取和寫入點(diǎn)不是連續(xù)而是隨機(jī)的,性能下降有所區(qū)別(帶有交換時(shí)會(huì)達(dá)到750%,否則會(huì)達(dá)到250%)。我相信這種方式可能更適合處理少量的大數(shù)據(jù)對(duì)象,而不適用于大量的小數(shù)據(jù)對(duì)象。對(duì)于后者,可能的處理辦法是預(yù)先將大量小數(shù)據(jù)對(duì)象加載到緩存中,再將其映射到虛擬內(nèi)存。
      應(yīng)用程序
      到目前為止,我使用的技術(shù)都是虛擬內(nèi)存系統(tǒng)。在示例中,一旦與虛擬內(nèi)存交互完成,就會(huì)刪除底層文件。但是,這種方法可以很容易地進(jìn)行數(shù)據(jù)持久化。
      例如,視頻編輯是一個(gè)非常具有挑戰(zhàn)性的工程問(wèn)題。一般來(lái)說(shuō),有兩個(gè)有效的方法:無(wú)損耗存儲(chǔ)整個(gè)視頻,并編輯存儲(chǔ)的信息;或根據(jù)需要重新生成視頻。因?yàn)镽AM的制約,后一種方法越來(lái)越普遍。然而,視頻是線性的——這是一種理想的數(shù)據(jù)類型,可用來(lái)存儲(chǔ)非常大的映射虛擬內(nèi)存。由于在視頻算法上取得的進(jìn)步,可以將它作為原始字節(jié)數(shù)組訪問(wèn)。操作系統(tǒng)會(huì)根據(jù)需要將磁盤到虛擬內(nèi)存的緩沖區(qū)進(jìn)行分頁(yè)處理。
      另一個(gè)同樣有效的應(yīng)用場(chǎng)景是替代文檔服務(wù)中過(guò)度設(shè)計(jì)的RAM緩存解決方案。想想看,我們有一個(gè)幾TB的中等規(guī)模的文檔庫(kù)。它可能包含圖片、短片和PDF文件。有一種常見(jiàn)的快速訪問(wèn)磁盤的方法,使用文件的RAM緩存弱引用或軟引用。但是,這會(huì)對(duì)JVM垃圾收集器產(chǎn)生重大影響,并且增加操作難度。如果將整個(gè)文檔映射到虛擬內(nèi)存,可以更加簡(jiǎn)單地完成同樣的工作。操作系統(tǒng)會(huì)根據(jù)需要將數(shù)據(jù)讀入內(nèi)存。更重要的是,操作系統(tǒng)將盡量保持RAM中最近被訪問(wèn)的內(nèi)存頁(yè)。這意味著內(nèi)存映射文件就像RAM緩存一樣,不會(huì)對(duì)Java或JVM垃圾收集器產(chǎn)生任何影響。
      最后,內(nèi)存映射文件在科學(xué)計(jì)算和建模等應(yīng)用中非常有效。在用來(lái)處理代表真實(shí)世界系統(tǒng)的計(jì)算模型時(shí),經(jīng)常需要大量的數(shù)據(jù)才能正常工作。在我的音頻處理系統(tǒng)Sonic Field中,通過(guò)混合和處理單一聲波,可以模擬真實(shí)世界中的音頻效果。例如,創(chuàng)建原始音頻副本是為模擬從硬表面反射的聲波,并將反射回來(lái)的聲波與原聲波混合。這種方法需要大量的存儲(chǔ)空間,這時(shí)就可以把音頻信號(hào)放在虛擬內(nèi)存中(也是這項(xiàng)工作的最初動(dòng)機(jī))。

    posted @ 2014-07-07 20:47 順其自然EVO 閱讀(195) | 評(píng)論 (0)編輯 收藏

    NoSQL數(shù)據(jù)庫(kù):數(shù)據(jù)的一致性

    讀取一致性
      · 強(qiáng)一致性
      在任何時(shí)間訪問(wèn)集群中任一結(jié)點(diǎn),得到的數(shù)據(jù)結(jié)果一致;
      · 用戶一致性
      對(duì)同一用戶,訪問(wèn)集群期間得到的數(shù)據(jù)一致;
      解決用戶一致性:使用粘性會(huì)話,將會(huì)話綁定到特定結(jié)點(diǎn)來(lái)處理;
      這樣會(huì)降低負(fù)載均衡器的性能;
      · 最終一致性
      集群中各結(jié)點(diǎn)間由于數(shù)據(jù)同步不及時(shí)造成暫時(shí)的數(shù)據(jù)不一致,但數(shù)據(jù)同步完成后,最終具有一致性;
      更新一致性
      · 悲觀方式
      使用寫鎖
      大幅降低系統(tǒng)響應(yīng)能力
      可能導(dǎo)致死鎖
      · 樂(lè)觀方式
      先讓沖突發(fā)生,再檢測(cè)順序
      自動(dòng)合并的處理方式極具“領(lǐng)域特定”問(wèn)題
      放寬“一致性約束”
      · CAP定理
      一致性(Consistency)、可用性(Availability)和分區(qū)耐受性(Partition tolerance),3個(gè)屬性只可能同時(shí)滿足2個(gè);
      分區(qū)耐受性的解釋:集群因通信故障而劃分為多個(gè)時(shí)仍然可用
      · CA系統(tǒng)
      單服務(wù)器
      集群中出現(xiàn)”分區(qū)“,就不可用
      · PA/PC
      集群出現(xiàn)”分區(qū)“時(shí),需要在”一致性“ 和“可用性”間權(quán)衡
      一般會(huì)犧牲部分一致性(eg:使用最終一致性),保證可用性
     放寬“持久性”約束
      更嚴(yán)格的持久性,意味著更多的性能損失;
      · 犧牲“持久性”換取更好的性能
      · 復(fù)制“持久性”故障
      主節(jié)點(diǎn)故障,未同步到從節(jié)點(diǎn)的數(shù)據(jù)丟失
      主節(jié)點(diǎn)恢復(fù),故障期間更新的數(shù)據(jù)沖突
      解決方案:針對(duì)單個(gè)請(qǐng)求指定其所需的持久性
      附思維導(dǎo)圖

    posted @ 2014-07-07 20:45 順其自然EVO 閱讀(161) | 評(píng)論 (0)編輯 收藏

    開(kāi)發(fā)者應(yīng)了解的一些SQL優(yōu)化準(zhǔn)則

      下面介紹一些開(kāi)發(fā)者在數(shù)據(jù)庫(kù)操作中要注意的SQL編碼準(zhǔn)則。雖然本文不能覆蓋所有的準(zhǔn)則,但還是希望能給開(kāi)發(fā)者帶來(lái)些許幫助。下面就來(lái)看看在編碼實(shí)踐中哪些應(yīng)該做,哪些不應(yīng)該做。
      1.  在長(zhǎng)時(shí)間運(yùn)行的查詢和短查詢中使用事務(wù)
      如果預(yù)期有一個(gè)長(zhǎng)時(shí)間運(yùn)行的查詢,并且有大量的數(shù)據(jù)輸出時(shí),開(kāi)發(fā)者就應(yīng)該在BEGIN TRAN 和END TRAN之間使用事務(wù)。
      這樣事務(wù)會(huì)在緩沖區(qū)緩存為獨(dú)立事務(wù),并會(huì)被分配特定內(nèi)存,以此來(lái)提高處理速度。
      2.  不要使用SELECT *
      如果使用SELECT * 來(lái)選擇表中的所有記錄,那么一些不必要的記錄也被讀取、緩存,增加了磁盤的I/O和內(nèi)存消耗。
      3.  避免在WHERE子句中使用顯式或隱式函數(shù),比如Convert ()
      4.  避免在觸發(fā)器中執(zhí)行長(zhǎng)時(shí)間的操作
      5.  適當(dāng)使用臨時(shí)表和表變量
      當(dāng)結(jié)果集較小的時(shí)候,請(qǐng)盡量使用表變量;當(dāng)結(jié)果集相當(dāng)大時(shí),使用臨時(shí)表。
      6.  使用連接(JOIN)代替子查詢(Sub-Queries)
      子查詢通常作為內(nèi)聯(lián)代碼來(lái)使用,而連接(JOIN)則作為表來(lái)使用,這樣速度會(huì)更快。所以,應(yīng)盡量避免在連接中使用子查詢。
      7.  連接條件中表的順序
      在連接條件中,應(yīng)盡量首先使用較小的表,然后逐步使用較大的表。
      8.  循環(huán)優(yōu)化
      如果操作在循環(huán)內(nèi)部沒(méi)有任何影響,那么應(yīng)盡量將操作放到循環(huán)外面,這樣可以減少不必要的重復(fù)工作。因?yàn)?,SQL Server優(yōu)化器不會(huì)自動(dòng)識(shí)別這種低效率的代碼,更不會(huì)自動(dòng)優(yōu)化(其他一些語(yǔ)言的編譯器可以)。
      9.  參數(shù)探測(cè)
      不要在正執(zhí)行的SP(存儲(chǔ)過(guò)程)中使用SP參數(shù),這樣會(huì)導(dǎo)致參數(shù)探測(cè)(Parameter Sniffing)。應(yīng)該在聲明和設(shè)置后再使用SP參數(shù)。由于這個(gè)原因,SP的行為在每次運(yùn)行期間都不相同。
      10.  當(dāng)使用條件語(yǔ)句時(shí),可以使用Index(索引)Hint(提示)
      比如在SQL Server 2008中,可以使用Index hint,也可以使用fixed plan hint強(qiáng)制在查詢中使用hint,以提高運(yùn)行速度。
      11.  在聲明中明確指定存儲(chǔ)過(guò)程中數(shù)據(jù)類型的大小
      開(kāi)發(fā)者隨機(jī)聲明數(shù)據(jù)類型的大小是不可取的,如:Varchar (500)。這在執(zhí)行時(shí)會(huì)在緩沖區(qū)中增加不必要的預(yù)留空間。
      12.  在查詢中有效利用MAXDOP(最大并行度)設(shè)置
      詢問(wèn)數(shù)據(jù)庫(kù)管理員關(guān)于四核CPU可用性的設(shè)置,包括內(nèi)存的設(shè)置,然后適當(dāng)使用hint,可以有效改善查詢速度。
      13.  SQL Server 2008中的GROUPING SETS
      如果數(shù)據(jù)庫(kù)服務(wù)器為SQL Server 2008,那么可以在所有的Unions中使用Grouping Set來(lái)代替Group By。這樣在Union中重新進(jìn)行g(shù)roup by排序時(shí),優(yōu)化器不會(huì)每次都制定一個(gè)計(jì)劃。
      14.  當(dāng)發(fā)生死鎖時(shí),總是使用With (nolock) 和With (rowlock)

    posted @ 2014-07-07 20:44 順其自然EVO 閱讀(178) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共394頁(yè): First 上一頁(yè) 88 89 90 91 92 93 94 95 96 下一頁(yè) Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    • 隨筆 - 3936
    • 文章 - 404
    • 評(píng)論 - 179
    • 引用 - 0

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 一级毛片全部免费播放| 91亚洲导航深夜福利| h片在线观看免费| 国产自国产自愉自愉免费24区| 亚洲国产成人VA在线观看| 美女免费视频一区二区| jjizz全部免费看片| MM131亚洲国产美女久久| 有色视频在线观看免费高清在线直播 | 精品亚洲456在线播放| 欧美大尺寸SUV免费| 亚洲色偷偷色噜噜狠狠99网| 妞干网在线免费视频| 亚洲av日韩精品久久久久久a| 国产大片免费观看中文字幕| 国产精品亚洲一区二区无码| 亚洲AV蜜桃永久无码精品| 中文字幕亚洲精品无码| 永久黄网站色视频免费观看| 无人视频在线观看免费播放影院 | 亚洲成人在线免费观看| 国产成在线观看免费视频| 伊人久久五月丁香综合中文亚洲 | 在线观看成人免费视频不卡| 色老板亚洲视频免在线观| 午夜视频在线在免费| 美女黄色免费网站| 国产亚洲精品免费视频播放| 黄色网址在线免费| 亚洲精彩视频在线观看| 日本妇人成熟免费中文字幕| 亚洲高清一区二区三区电影| 亚洲国产黄在线观看| 99精品免费视频| 亚洲天堂在线视频| 国产成人无码区免费网站| 亚洲色偷偷av男人的天堂| 国内免费高清在线观看| 黄色毛片免费观看| 亚洲国产精品一区二区成人片国内| 亚洲成人免费网址|