qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Web開發測試中的18個關鍵性錯誤

           前幾年,我有機會能參與一些有趣的項目,并且獨立完成開發、升級、重構以及新功能的開發等工作
            本文總結了一些PHP程序員在Web開發中經常 忽略的關鍵錯誤,尤其是在處理中大型的項目上問題更為突出。典型的錯誤表現在不能很好區分各種開發環境和沒有使用緩存和備份等。
            下面以PHP為例,但是其核心思想對每一個Web程序員都是適用的。
            應用程序級別的錯誤
            1、在開發階段關閉了錯誤報告
            我唯一想問的是:為什么?為什么在開發的時候要關閉錯誤報告?
            PHP有很多級別的錯誤報告,在開發階段我們必須將它們全部開啟。
            如果你覺得錯誤不會發生,那么你把程序太理想化了,在現實世界中,錯誤是必然的。error_reporting和display_error是兩個完全不同的方法,error_reporting()設置了錯誤的級別,而display_errors則是設置錯誤信息是否要被輸出。
            在開發階段,錯誤報告的級別應該設置成最高的,比如以下設置: error_reporting(E_ALL);以及ini_set(‘display_errors’, true);
            2、淹沒錯誤
            和上一點相反,很多程序員喜歡將錯誤淹沒了,你明知道錯誤會發生,但是你選擇將錯誤隱藏掉,然后可以早早回家睡大覺,殊不知將來會發生更嚴重的錯誤。
            3、代碼中任何地方都沒有使用日志
            軟件開發的一開始你就要牢記使用日志,不能到項目結束了才去彌補日志功能。很多程序員都會用這樣或那樣的手段進行日志記錄,但是很少有人能真正用日志來記錄異常信息,試問一個沒有人查看的日志系統有什么用?
            4、沒有使用緩存
            在的應用系統中,我們可以在多個系統層次上使用緩存,比如在服務端、應用端和數據庫端等。和日志一樣,緩存也應該在一開始就應用到系統中去,你可以在開發階段禁用緩存,等到了產品發布后再將緩存開啟。
            5、丟棄了最佳實踐和設計模式
            你看到過多少人使用自己的密碼加密算法?很遺憾的告訴你,有很多,因為他們認為將更了解它。
            最好的實踐方式和設計模式已經由前輩創建了,這往往比你自己再造一個輪子要來的簡單奏效,我們開發者只需要熟練掌握這些設計模式并且合理地應用在項目中即可,比如一些加密算法。
            6、沒有使用自動化測試
            在每一個Web項目中都會使用到測試,就像日志一樣,如果沒有人管理和使用,那么測試也是一無是處的。
            運行測試工程是一項枯燥乏味的工作,幸好有一系列工具幫助我們實現自動化測試。在PHP開發中,有一款很好的測試工具叫Jenkins,使用起來非常方便。
            7、沒有做代碼審查
            在團隊中工作是一項非常大的挑戰,因為每一個成員都有自己不同的工作習慣和方式,如果沒有良好的規范,那么項目開發就會走很多彎路。
            團隊中的每一個成員都應該互相審查代碼,就像單元測試,它可以幫助項目變得更加干凈和一致性。
            8、編程只考慮理想情況
            你是否遇到過自己或者別人的代碼在交到客戶手中后經常出問題,甚至是亂套了?我當然沒有。
            出現這種情況往往是因為開發者懶惰了,只考慮了理想情況,這會導致數據庫崩潰了、PHP發生致命錯誤、甚至是服務器被黑。程序員在寫代碼時不僅要考慮最理想的情況,更要考慮最壞的情況,思考全面,才能讓代碼覆蓋所有的情況。
            9、沒有正確運用面向對象編程的思想
            大部分PHP初學者都不會再其代碼中運用面向對象的思想,因為這個概念在剛開始的時候很難理解。
            當然面向對象的概念并不是簡單地將一些類組織在一起。
            對象、屬性、方法、繼承和封裝等都是OOP中最基本的概念,開發者正確使用了面向對象設計模式后,就有能力寫出更干凈、更有擴展性的代碼了。
          10、“飛行模式”(On-the-fly)編程
            大部分開發者都會遇到這樣的情況:“快,客戶需要一項新功能,要能運行ASAP”,于是你就在源代碼上新增一些功能,然后直接上傳到正在運行的服務器上,這種編程方式我們稱其為“飛行模式”(On-the-fly)編程。
            我們在開發軟件時,尤其是中大型的項目,都必須按照工作流程來進行分析、編程和發布,這將大大減少未來軟件的bug。這種“飛行模式”并不可取。
            數據庫級別的錯誤
            11、沒有將數據庫讀寫分離
            為了能長時間運行復雜的系統,每一個程序員都應該考慮到系統的可擴展性,系統99%的時間都不需要考慮擴展,因為并沒有如此大的流量。
            為什么要數據庫讀寫分離?
            在每一個系統中,數據庫將會是第一個出現的瓶頸,在大流量的沖擊下,數據庫很可能將會是第一個陣亡的。所以大部分情況下我們會用多個數據庫來分散流量,開發者經常會使用Master – Slave模式或者Master – Master 模式。Master – Slave是最受歡迎的一種數據庫分壓模式,它會將指定的select語句路由到每一個Slave服務器,這樣Master服務器的壓力會減輕不少。
            12、代碼只能連接到一個數據庫
            這和上一個錯誤非常像,但是開發者有時候因為某些原因需要連接到多個數據庫,比如你會將用戶日志、活動信息流、實時數據分析等高負載的數據放到不同的數據庫中來緩解對主數據庫的壓力。
            13、沒有檢測數據庫漏洞
            如果你不對數據庫進行漏洞檢測,就相當于給大部分黑客敞開了服務器的大門。
            在眾多漏洞中,數據庫漏洞是最脆弱的,最常見的就是SQL注入。因此定期做數據庫漏洞檢測還是很有必要的。
            14、數據表不建索引
            索引在數據表中有著非常重要的作用,合適的索引可以提高每張表的性能,這里有一篇文章就講述了如何創建索引以及何時創建索引。
            15、沒有使用事務機制
            數據完整性對Web系統非常重要,如果數據一致性發生錯誤,那么整個系統都會崩潰并且難以修復。合理地運用數據庫的事務機制將有效地解決這個問題。比如你要保存用戶數據,在table1中有e-mail, username和password,table2中有first name, last name,和gender age。我們可以利用事務對兩張表更新時保證數據同時被更新或者同時不被更新。
            16、沒有加密敏感數據
            對于數據庫中的敏感信息,如果你不對它們進行加密,或者用簡單的算法進行加密,那么在2014年你肯定會遇到一些麻煩的問題,黑客們一旦入侵你的數據庫,用戶的密碼或者其他重要信息就會一覽無余。
            PHP5.5中提供了一個哈希加密方法,使用如下:
            $hash = password_hash( $password, PASSWORD_BCRYPT );
            17、沒有備份
            看到下面這張圖片沒,如果遇到這樣的情況,你又沒有備份,那么一切都over了。
            18、沒有監控
            沒有監控,你將不知道接下來會發生什么事情,對于監控,要注意以下幾個問題:
            有多少人可以直接訪問這個應用服務?
            服務器是否在高負載下運行?
            我們需要用另一臺數據庫服務器來擴展系統嗎?
            應用系統的失敗點在哪里?
            系統目前正處于離線狀態嗎?

          posted @ 2014-09-26 10:08 順其自然EVO 閱讀(186) | 評論 (0)編輯 收藏

          性能測試中如何選取被測對象的業務邏輯

          很多搞性能測試的人員,只會跟著網上、前輩教導的方法進行測試:挑選業務邏輯中并發量、訪問量最高的業務邏輯、結合讀寫等業務進行測試,然后取整條業務邏輯(模擬用戶全流程動作)的邏輯進行測試;結果就是:準備大堆的測試數據,復雜的準備工作;其實那些數據只是用來滿足業務流中的條件,而不是真的能產生壓力的部分;
            筆者采用的方法:
            1、B/S結構中,用戶操作功能流程其實是前端js依次調用不同的CGI接口,后臺實現上面其實并沒有強依賴關系(只要滿足對應條件進行發包都能執行)。
            所以,首先挑選業務邏輯中用戶訪問最高的流程,然后從流程中挑選調用次數、壓力最大的CGI接口;這樣聚焦于對應的測試對象,可以避免很多無用的測試數據;
            2、根據業務邏輯,分析被測對象券流程中,所調用的接口,對于安全旁路、分支判斷等,根據情況進行取舍(有些業務只測試某個CGI,有些是測試全平臺,測試中根據情況進行聚焦)。
            3、根據分析情況直接修改被測對象代碼:通常接口調用形式都會使用iret方式來判斷,例如:
          /*原有代碼----begin*/
          iret=xxx.call(args1,args2,args3);
          if(iret != 0){
          print("xxxxx");
          break;
          }
          /*原有代碼----end*/
          iret=0 ---------- 添加iret=0,讓程序繼續走。
            這樣不會影響外部接口調用次數,不會影響網絡發包次數,但可能會影響單個網絡包大小進而影響網絡流量;同時稍微增加cpu負擔(賦值造成內存讀寫)。但其實我們要測的是業務主流程,而不是外部接口(外部接口如果有需要可單獨進行壓測),所以筆者認為也是可以采取此種方案,而不需要準備一大堆無用的數據,只需有針對性的進行業務邏輯選取即可;

          posted @ 2014-09-26 10:07 順其自然EVO 閱讀(221) | 評論 (0)編輯 收藏

          測試用例設計的價值與誤區

          測試用例是一系列特定的軟件行為,用于驗證軟件的某特定功能、檢查軟件能否正確處理某種出錯行為、或者檢查其他一些軟件質量衡量的屬性 (如性能、安全、可靠性等)。 一個測試用例是一個正式的文件或記錄,描述了測試活動是怎樣具體執行的。測試用例設計的目的就是發現缺陷,但是測試用例的用處遠遠超出發現缺陷。
            測試用例文檔的一些好處如下:
            1、歷史借鑒:測試用例的存在要遠遠超過產品發布。持續工程(Sustained engineering)以及產品未來版本的負責人往往需要借用測試用例來了解測試過什么,以及是如何測試的。測試用例文檔和一個有組織的儲存系統對長期支持或修訂產品的一部分是至關重要的策略。----注----為了便于后來者對于測試用例的使用和借鑒,測試用例設計要盡量描述準確、步驟清晰。
            2、測試進展跟蹤:通過測試用例文檔,可以跟蹤一些額外的屬性,如測試用例的執行數目,測試用例的通過或失敗數目,以及每個功能領域的測試用例總數。 ----注----在測試用例管理系統中要準確且實際地描述用例的執行結果,包括其他必填的屬性,便于分期人員從各個屬性和維度進行測試過程分析。
            3、可重復性:好的測試用例文檔可以由任何人在任何時候執行。這同樣適用于自動和手動的測試用例。重復準確地執行同樣的測試對重現步驟或檢測回歸是至關重要的。 ----注----測試用例的描述要準確、全面,要能保證除自己以外的測試人員能正確理解和執行該用例。
            測試用例文檔也有缺點:
            1、建立文檔的時間:如果建立測試用例文檔的時間比運行測試用例所需的時間還長,建立測試用例文檔也許就沒有意義了。經常有這樣的情況,即測試用例只需要在一個單一的環境下執行寥寥幾次。 ----注----但是從測試用例價值的角度來考慮,建立測試用例文檔卻是個不可裁剪的過程。但是,這個缺點會隨著用例設計的熟練程度的提高以及用例設計平均時間成本的減小而逐漸減弱。
            2、功能變化引起測試用例過期:建立測試用例所需的時間很可能因功能經常變化而增加,以至于失去控制。如果測試用例的功能領域變化頻繁,建立測試用例文檔就不一定是明智的。這種場景之一是嘗試寫測試用例以驗證用戶界面組件。 ----注----功能需求或者設計和實現的變化常常導致測試用例需要調整和修改,甚至有時候修改用例的時間會超過新建用例的時間。因此,在用例設計過程中,保持與設計、開發人員的密切溝通,及時了解功能變化的情況十分必要。否則后期再修改用例的時間成本很大。當然,在軟件開發后期,軟件需求和設計盡量保持穩定是最合適的。
            3、很難設想讀者的知識:寫測試用例的人往往極為熟悉被測試的功能。這些人常犯的錯誤是在測試用例中使用術語或縮寫,而將來運行測試用例的人很可能看不懂這些測試用例。出現這種情況出現時,測試用例已不再能準確地重復,測試用例也失去了這關鍵屬性之一。 ----注----為了用例便于后來者正常使用該用例,用例設計應盡量避免使用只有自己熟悉的專業詞匯和縮寫詞,或者存在用例描述太簡潔但自己能理解的情況。
            測試用例設計的誤區
            創建好的測試用例是一個困難的過程。即使一個錯誤就可以毀掉測試用例的意圖。一些易出問題的領域如下:
            1、步驟缺乏:  匆忙建立的測試用例或假設測試用例的一些步驟會被執行而未將它們包括在測試用例里是非常常見的錯誤, 它造成不能準確地重復。----注----必要的用例步驟不能省,避免在執行用例的時候出現描述不清導致模棱兩可的情況發生,從而影響案例執行進度。
            2、太多細節: 雖然提供具體和足夠的信息很重要,不必要的字詞或冗長的解釋,會使測試用例難以遵循。僅需包含足夠的信息以便精確地運行測試用例。  ----注----太多的細節描述會增加案例設計的成本,適可而止即可。
            3、行話太多: 不要以為運行測試用例的人(包括產品技術支持和持續工程)都知道所有你寫的縮略語,代號和縮寫。闡明任何對整個產品生命周期有價值和必要的信息。  ----注----同上缺點3的注釋。
            4、不明確的通過/失敗標準: 如果運行測試后,不清楚測試是否通過或失敗,那測試用例是毫無用處的。----注----測試用例的預期結果一定要準確和清晰。對于測試后存在不符合預期結果的情況,即可判斷為失敗,全部符合預期結果則為成功。

          posted @ 2014-09-26 10:06 順其自然EVO 閱讀(164) | 評論 (0)編輯 收藏

          JDBC連接MySQL數據庫及演示樣例

           JDBC是Sun公司制定的一個能夠用Java語言連接數據庫的技術。
            一、JDBC基礎知識
            JDBC(Java Data Base Connectivity,java數據庫連接)是一種用于執行SQL語句的Java API,能夠為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC為數據庫開發者提供了一個標準的API,據此能夠構建更高級的工具和接口,使數據庫開發者能夠用純 Java API 編寫數據庫應用程序,而且可跨平臺執行,而且不受數據庫供應商的限制。
            1、跨平臺執行:這是繼承了Java語言的“一次編譯,到處執行”的特點;
            2、不受數據庫供應商的限制:巧妙在于JDBC設有兩種接口,一個是面向應用程序層,其作用是使得開發者通過SQL調用數據庫和處理結果,而不須要考慮數據庫的提供商;還有一個是驅動程序層,處理與詳細驅動程序的交互,JDBC驅動程序能夠利用JDBC API創建Java程序和數據源之間的橋梁。應用程序僅僅須要編寫一次,便能夠移到各種驅動程序上執行。Sun提供了一個驅動管理器,數據庫供應商——如MySQLOracle,提供的驅動程序滿足驅動管理器的要求就能夠被識別,就能夠正常工作。所以JDBC不受數據庫供應商的限制。
            JDBC API能夠作為連接Java應用程序與各種關系數據庫的紐帶,在帶來方便的同一時候也有負面影響,下面是JDBC的優、缺點。長處例如以下:
            操作便捷:JDBC使得開發者不須要再使用復雜的驅動器調用命令和函數;
            可移植性強:JDBC支持不同的關系數據庫,所以能夠使同一個應用程序支持多個數據庫的訪問,僅僅要載入對應的驅動程序就可以;
            通用性好:JDBC-ODBC橋接驅動器將JDBC函數換成ODBC;
            面向對象:能夠將經常使用的JDBC數據庫連接封裝成一個類,在使用的時候直接調用就可以。
            缺點例如以下:
            訪問數據記錄的速度受到一定程度的影響;
            更改數據源困難:JDBC可支持多種數據庫,各種數據庫之間的操作必有不同,這就給更改數據源帶來了非常大的麻煩
            二、JDBC連接數據庫的流程及其原理
            1、在開發環境中載入指定數據庫的驅動程序。比如,接下來的實驗中,使用的數據庫是MySQL,所以須要去下載MySQL支持JDBC的驅動程序(最新的是:mysql-connector-java-5.1.18-bin.jar);而開發環境是MyEclipse,將下載得到的驅動程序載入進開發環境中(詳細演示樣例的時候會解說怎樣載入)。
            2、在Java程序中載入驅動程序。在Java程序中,能夠通過 “Class.forName(“指定數據庫的驅動程序”)” 方式來載入加入到開發環境中的驅動程序,比如載入MySQL的數據驅動程序的代碼為:  Class.forName(“com.mysql.jdbc.Driver”)
            3、創建數據連接對象:通過DriverManager類創建數據庫連接對象Connection。DriverManager類作用于Java程序和JDBC驅動程序之間,用于檢查所載入的驅動程序能否夠建立連接,然后通過它的getConnection方法,依據數據庫的URL、username和password,創建一個JDBC Connection 對象。如:Connection connection =  DriverManager.geiConnection(“連接數據庫的URL", "username", "password”)。當中,URL=協議名+IP地址(域名)+port+數據庫名稱;username和password是指登錄數據庫時所使用的username和password。詳細演示樣例創建MySQL的數據庫連接代碼例如以下:
            Connection connectMySQL  =  DriverManager.geiConnection(“jdbc:mysql://localhost:3306/myuser","root" ,"root" );
            4、創建Statement對象:Statement 類的主要是用于運行靜態 SQL 語句并返回它所生成結果的對象。通過Connection 對象的 createStatement()方法能夠創建一個Statement對象。比如:Statement statament = connection.createStatement(); 詳細演示樣例創建Statement對象代碼例如以下:
            Statement statamentMySQL =connectMySQL.createStatement();
            5、調用Statement對象的相關方法運行相相應的 SQL 語句:通過execuUpdate()方法用來數據的更新,包含插入和刪除等操作,比如向staff表中插入一條數據的代碼:
            statement.excuteUpdate( "INSERT INTO staff(name, age, sex,address, depart, worklen,wage)" + " VALUES ('Tom1', 321, 'M', 'china','Personnel','3','3000' ) ") ;
            通過調用Statement對象的executeQuery()方法進行數據的查詢,而查詢結果會得到 ResulSet對象,ResulSet表示運行查詢數據庫后返回的數據的集合,ResulSet對象具有能夠指向當前數據行的指針。通過該對象的next()方法,使得指針指向下一行,然后將數據以列號或者字段名取出。假設當next()方法返回null,則表示下一行中沒有數據存在。使用演示樣例代碼例如以下:
            ResultSet resultSel = statement.executeQuery( "select * from staff" );
            6、關閉數據庫連接:使用完數據庫或者不須要訪問數據庫時,通過Connection的close() 方法及時關閉數據連接。
            三、JDBC應用演示樣例實驗
            實驗內容:使用phpMyAdmin在MySQL中創建數據庫(myuser),并加入實驗所需的數據(新建staff表,加入一些記錄);編寫Java程序,利用JDBC連接在MySQL中創建好的數據庫(myuser),對staff表格進行插入、更新、刪除和查詢等操作。
            實驗環境及開發工具:Win7操作系統;jdk1.6.0_26;XAMPP1.7.7(MySQL 5.1,  phpMyAdmin);MyEclipse 8.5
            實驗環境的搭建:可參考我的博客
            Java環境搭配:http://blog.csdn.net/cxwen78/article/details/6400798;
            windows系統XAMPP安裝配置使用:http://blog.csdn.net/cxwen78/article/details/6847927
            實驗過程及步驟:
            1、下載MySQL支持JDBC的驅動程序:假設已經有了,可跳過這一步。前往MySQL官網(http://www.mysql.com/products/connector/ )下載驅動程序,,MySQL針對不同的平臺提供了不同的連接器,我們須要的是DBC Driver for MySQL (Connector/J),例如以下圖所看到的,點擊 Download 跟著站點的引導進行下載。打開下載得到的壓縮包(mysql-connector-java-5.1.18.zip),將當中的Java包(mysql-connector-java-5.1.18-bin.jar),拷貝到MySQL文件夾下(僅是為了方便才放到這里),以備載入驅動程序時使用。
            2、創建數據庫:使用phpMyAdmin,登錄MySQL,創建數據庫myuser,并在當中插入一個名為staff的表格。并加入一些數據,操作步驟如圖,登錄進去MySQL數據庫后:
            1)創建數據庫,名稱為myuser,編碼為utf8_general_ci(支持中文);
            2)新建表格,名稱為staff,表格有8個字段;
            3)8個字段的設置,包含名稱、類型、值的長度、初始值、編碼等等(點擊查看大圖);
            4)加入成功后,查看的staff表格情況:
            5)往表格中插入一些實驗所需數據,須要插入兩條,一個是員工lucy的,還有lili的:
            3、在MyEclips中創建項目并在項目中加入MySQL驅動程序:創建的項目類型能夠是Java項目或者是Java Web項目都能夠。這里創建的是Web項目,項目名稱能夠隨便取,我命名為“JavaWebChp07”。創建成功后將步驟1里下載得到的MySQL驅動程序包(mysql-connector-java-5.1.18-bin.jar)加入到project的Build path中,加入過程如圖所看到的:
           4、編寫JDBC連接MySQL數據庫的實例詳細代碼,JDBC_Test.java:
            詳細代碼:
            <pre name="code" class="java">package chp07;
            import java.sql.Connection;
            import java.sql.DriverManager;
            import java.sql.ResultSet;
            import java.sql.SQLException;
            import java.sql.Statement;
            public class JDBC_Test {
            // 創建靜態全局變量
            static Connection conn;
            static Statement st;
            public static void main(String[] args) {
            insert(); //插入加入記錄
            update(); //更新記錄數據
            delete(); //刪除記錄
            query(); //查詢記錄并顯示
            }
            /* 插入數據記錄,并輸出插入的數據記錄數*/
            public static void insert() {
            conn = getConnection(); // 首先要獲取連接,即連接到數據庫
            try {
            String sql = "INSERT INTO staff(name, age, sex,address, depart, worklen,wage)"
            + " VALUES ('Tom1', 32, 'M', 'china','Personnel','3','3000')"; // 插入數據的sql語句
            st = (Statement) conn.createStatement(); // 創建用于運行靜態sql語句的Statement對象
            int count = st.executeUpdate(sql); // 運行插入操作的sql語句,并返回插入數據的個數
            System.out.println("向staff表中插入 " + count + " 條數據"); //輸出插入操作的處理結果
            conn.close(); //關閉數據庫連接
            } catch (SQLException e) {
            System.out.println("插入數據失敗" + e.getMessage());
            }
            }
            /* 更新符合要求的記錄,并返回更新的記錄數目*/
            public static void update() {
            conn = getConnection(); //相同先要獲取連接,即連接到數據庫
            try {
            String sql = "update staff set wage='2200' where name = 'lucy'";// 更新數據的sql語句
            st = (Statement) conn.createStatement(); //創建用于運行靜態sql語句的Statement對象,st屬局部變量
            int count = st.executeUpdate(sql);// 運行更新操作的sql語句,返回更新數據的個數
            System.out.println("staff表中更新 " + count + " 條數據"); //輸出更新操作的處理結果
            conn.close(); //關閉數據庫連接
            } catch (SQLException e) {
            System.out.println("更新數據失敗");
            }
            }
            /* 查詢數據庫,輸出符合要求的記錄的情況*/
            public static void query() {
            conn = getConnection(); //相同先要獲取連接,即連接到數據庫
            try {
            String sql = "select * from staff"; // 查詢數據的sql語句
            st = (Statement) conn.createStatement(); //創建用于運行靜態sql語句的Statement對象,st屬局部變量
            ResultSet rs = st.executeQuery(sql); //運行sql查詢語句,返回查詢數據的結果集
            System.out.println("最后的查詢結果為:");
            while (rs.next()) { // 推斷是否還有下一個數據
            // 依據字段名獲取對應的值
            String name = rs.getString("name");
            int age = rs.getInt("age");
            String sex = rs.getString("sex");
            String address = rs.getString("address");
            String depart = rs.getString("depart");
            String worklen = rs.getString("worklen");
            String wage = rs.getString("wage");
            //輸出查到的記錄的各個字段的值
            System.out.println(name + " " + age + " " + sex + " " + address
            + " " + depart + " " + worklen + " " + wage);
            }
            conn.close(); //關閉數據庫連接
            } catch (SQLException e) {
            System.out.println("查詢數據失敗");
            }
            }
            /* 刪除符合要求的記錄,輸出情況*/
            public static void delete() {
            conn = getConnection(); //相同先要獲取連接,即連接到數據庫
            try {
            String sql = "delete from staff  where name = 'lili'";// 刪除數據的sql語句
            st = (Statement) conn.createStatement(); //創建用于運行靜態sql語句的Statement對象,st屬局部變量
            int count = st.executeUpdate(sql);// 運行sql刪除語句,返回刪除數據的數量
            System.out.println("staff表中刪除 " + count + " 條數據\n"); //輸出刪除操作的處理結果
            conn.close(); //關閉數據庫連接
            } catch (SQLException e) {
            System.out.println("刪除數據失敗");
            }
            }
            /* 獲取數據庫連接的函數*/
            public static Connection getConnection() {
            Connection con = null; //創建用于連接數據庫的Connection對象
            try {
            Class.forName("com.mysql.jdbc.Driver");// 載入Mysql數據驅動
            con = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/myuser", "root", "root");// 創建數據連接
            } catch (Exception e) {
            System.out.println("數據庫連接失敗" + e.getMessage());
            }
            return con; //返回所建立的數據庫連接
            }
            }
            項目部署到server,然后執行結果:

          posted @ 2014-09-24 15:39 順其自然EVO 閱讀(827) | 評論 (0)編輯 收藏

          Unix/Linux中Cron的用法

          cron是unix或者linux下用來定時任務的命令,大致的用法如下:
            1、服務的啟動和關閉
            /sbin/service crond start   //啟動服務
            /sbin/service crond stop    //關閉服務
            /sbin/service crond restart //重啟服務
            /sbin/service crond reload  //重新載入配置
            也可以讓該服務在開機時自啟動:在/etc/rc.d/rc.local這個腳本的末尾加上如下腳本:
            /sbin/service crond start
            2、編輯cron服務
            crontab -u //設定某個用戶的cron服務,一般root用戶在執行這個命令的時候需要此參數crontab -l //列出某個用戶cron服務的詳細內容
            crontab -r //刪除沒個用戶的cron服務
            crontab -e //編輯某個用戶的cron服務
            用crontab -u user -e 進入vi編輯模式,編輯的內容一定要符合下面的格式:
            * * * * * command
            這個格式的前一部分是對時間的設定,后面一部分是要執行的命令,當然,這個命令也可以是一個腳本。五個 * 的作用如下:
            分鐘 (0-59)
            小時 (0-23)
            日期 (1-31)
            月份 (1-12)
            星期 (0-6)//0代表星期天
            每 次編輯完某個用戶的cron設置后,cron自動在/var/spool/cron下生成一個與此用戶同名的文件,此用戶的cron信息都記錄在這個文件 中,這個文件是不可以直接編輯的,只可以用crontab -e 來編輯。cron啟動后每過一份鐘讀一次這個文件,檢查是否要執行里面的命令。因此此文件修改后不需要重新啟動cron服務。
            3、定時方法說明
            除了數字之外,還有幾個特殊的符號("*"、"/"和"-"、",")可以用來編輯啟動時間,*代表所有的取值范圍內的數字,"/"代表每的意思,"*/5"表示每5個單位,"-"代表從某個數字到某個數字,","分開幾個離散的數字。以下舉幾個例子說明問題:
            每天早上6點:0 6 * * * command
            每兩個小時:0 */2 * * * command
            晚上11點到早上8點之間每兩個小時,早上八點:0 23-7/2,8 * * * command
            每個月的4號和每個禮拜的禮拜一到禮拜三的早上11點:0 11 4 * 1-3 command
            1月1日早上4點:0 4 1 1 * command
            4、配置文件/etc/crontab的編輯
            cron 服務每分鐘不僅讀一次/var/spool/cron內的文件,還要讀一次/etc/crontab,因此我們配置這個文件也能運用cron服務做一些事 情。用crontab配置是針對某個用戶的,而編輯/etc/crontab是針對系統的任務。此文件的文件格式是:
          SHELL=/bin/bash
          PATH=/sbin:/bin:/usr/sbin:/usr/bin
          MAILTO=root //如果出現錯誤,或者有數據輸出,數據作為郵件發給這個帳號
          HOME=/ //使用者運行的路徑,這里是根目錄
          # run-parts
          01 * * * * root run-parts /etc/cron.hourly //每小時執行/etc/cron.hourly內的腳本
          02 4 * * * root run-parts /etc/cron.daily //每天執行/etc/cron.daily內的腳本
          22 4 * * 0 root run-parts /etc/cron.weekly //每星期執行/etc/cron.weekly內的腳本
          42 4 1 * * root run-parts /etc/cron.monthly //每月去執行/etc/cron.monthly內的腳本
            大家注意"run-parts"這個參數了,如果去掉這個參數的話,后面就可以寫要運行的某個腳本名,而不是文件夾名了。
            5、權限設置
            默認情況下,所有用戶都能訪問cron工具,要對cron進行訪問控制,則可以生成/etc/cron.allow與/etc/cron.deny文件。
            ①、這兩個文件都不存在時,每個用戶都可以訪問cron工具。
            ②、默認情況下,應該有cron.deny(空文件),cron.allow需要自己創建。
            ③、存在/etc/cron.allow文件時,則只有cron.allow文件中允許的用戶才能訪問cron工具,如果也有/etc/cron.deny文件,則忽略cron.deny文件中的內容。

          posted @ 2014-09-24 15:38 順其自然EVO 閱讀(236) | 評論 (0)編輯 收藏

          深入理解Java:類加載機制及反射

           一、Java類加載機制
            1.概述
            Class文件由類裝載器裝載后,在JVM中將形成一份描述Class結構的元信息對象,通過該元信息對象可以獲知Class的結構信息:如構造函數,屬性和方法等,Java允許用戶借由這個Class相關的元信息對象間接調用Class對象的功能。
            虛擬機把描述類的數據從class文件加載到內存,并對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。
            2.工作機制
            類裝載器就是尋找類的字節碼文件,并構造出類在JVM內部表示的對象組件。在Java中,類裝載器把一個類裝入JVM中,要經過以下步驟:
            (1) 裝載:查找和導入Class文件;
            (2) 鏈接:把類的二進制數據合并到JRE中;
            (a)校驗:檢查載入Class文件數據的正確性;
            (b)準備:給類的靜態變量分配存儲空間;
            (c)解析:將符號引用轉成直接引用;
            (3) 初始化:對類的靜態變量,靜態代碼塊執行初始化操作
            Java程序可以動態擴展是由運行期動態加載和動態鏈接實現的;比如:如果編寫一個使用接口的應用程序,可以等到運行時再指定其實際的實現(多態),解析過程有時候還可以在初始化之后執行;比如:動態綁定(多態);
            【類初始化】
            (1) 遇到new、getstatic、putstatic或invokestatic這4條字節碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。生成這4條指令的最常見的Java代碼場景是:使用new關鍵字實例化對象的時候,讀取或設置一個類的靜態字段(被final修飾、已在編譯期把結果放入常量池的靜態字段除外)的時候,以及調用一個類的靜態方法的時候。
            (2) 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
            (3) 當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
            (4)當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類。
            只有上述四種情況會觸發初始化,也稱為對一個類進行主動引用,除此以外,所有其他方式都不會觸發初始化,稱為被動引用
            代碼清單1
            上述代碼運行后,只會輸出【---SuperClass init】, 而不會輸出【SubClass init】,對于靜態字段,只有直接定義這個字段的類才會被初始化,因此,通過子類來調用父類的靜態字段,只會觸發父類的初始化,但是這是要看不同的虛擬機的不同實現。
            代碼清單2
            此處不會引起SuperClass的初始化,但是卻觸發了【[Ltest.SuperClass】的初始化,通過arr.toString()可以看出,對于用戶代碼來說,這不是一個合法的類名稱,它是由虛擬機自動生成的,直接繼承于Object的子類,創建動作由字節碼指令newarray觸發,此時數組越界檢查也會伴隨數組對象的所有調用過程,越界檢查并不是封裝在數組元素訪問的類中,而是封裝在數組訪問的xaload,xastore字節碼指令中.
          代碼清單3
            對常量ConstClass.value 的引用實際都被轉化為NotInitialization類對自身常量池的引用,這兩個類被編譯成class后不存在任何聯系。
            【裝載】
            在裝載階段,虛擬機需要完成以下3件事情
            (1) 通過一個類的全限定名來獲取定義此類的二進制字節流
            (2) 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構
            (3) 在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區這些數據的訪問入口。
            虛擬機規范中并沒有準確說明二進制字節流應該從哪里獲取以及怎樣獲取,這里可以通過定義自己的類加載器去控制字節流的獲取方式。
            【驗證】
            虛擬機如果不檢查輸入的字節流,對其完全信任的話,很可能會因為載入了有害的字節流而導致系統奔潰。
            【準備】
            準備階段是正式為類變量分配并設置類變量初始值的階段,這些內存都將在方法區中進行分配,需要說明的是:
            這時候進行內存分配的僅包括類變量(被static修飾的變量),而不包括實例變量,實例變量將會在對象實例化時隨著對象一起分配在Java堆中;這里所說的初始值“通常情況”是數據類型的零值,假如:
            public static int value = 123;
            value在準備階段過后的初始值為0而不是123,而把value賦值的putstatic指令將在初始化階段才會被執行
            二、類加載器與雙親委派模型
            類加載器
            (1) Bootstrap ClassLoader : 將存放于<JAVA_HOME>\lib目錄中的,或者被-Xbootclasspath參數所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如 rt.jar 名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內存中。啟動類加載器無法被Java程序直接引用
            (2) Extension ClassLoader : 將<JAVA_HOME>\lib\ext目錄下的,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫加載。開發者可以直接使用擴展類加載器。
            (3) Application ClassLoader : 負責加載用戶類路徑(ClassPath)上所指定的類庫,開發者可直接使用。
            雙親委派模型
            工作過程:如果一個類加載器接收到了類加載的請求,它首先把這個請求委托給他的父類加載器去完成,每個層次的類加載器都是如此,因此所有的加載請求都應該傳送到頂層的啟動類加載器中,只有當父加載器反饋自己無法完成這個加載請求(它在搜索范圍中沒有找到所需的類)時,子加載器才會嘗試自己去加載。
            好處:java類隨著它的類加載器一起具備了一種帶有優先級的層次關系。例如類java.lang.Object,它存放在rt.jar中,無論哪個類加載器要加載這個類,最終都會委派給啟動類加載器進行加載,因此Object類在程序的各種類加載器環境中都是同一個類。相反,如果用戶自己寫了一個名為java.lang.Object的類,并放在程序的Classpath中,那系統中將會出現多個不同的Object類,java類型體系中最基礎的行為也無法保證,應用程序也會變得一片混亂。
            java.lang.ClassLoader中幾個最重要的方法:
            //加載指定名稱(包括包名)的二進制類型,供用戶調用的接口
            public Class<?> loadClass(String name);
            //加載指定名稱(包括包名)的二進制類型,同時指定是否解析(但是,這里的resolve參數不一定真正能達到解析的效果),供繼承用
            protected synchronized Class<?> loadClass(String name, boolean resolve);
            protected Class<?> findClass(String name)
            //定義類型,一般在findClass方法中讀取到對應字節碼后調用,可以看出不可繼承(說明:JVM已經實現了對應的具體功能,解析對應的字節碼,產生對應的內部數據結構放置到方法區,所以無需覆寫,直接調用就可以了)
            protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError{}
            如下是實現雙親委派模型的主要代碼:
            三、反射
            Reflection機制允許程序在正在執行的過程中,利用Reflection APIs取得任何已知名稱的類的內部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructors、 methods、 modifiers等,并可以在執行的過程中,動態生成instances、變更fields內容或喚起methods。
            1、獲取構造方法
            Class類提供了四個public方法,用于獲取某個類的構造方法。
            Constructor getConstructor(Class[] params)
            根據構造函數的參數,返回一個具體的具有public屬性的構造函數
            Constructor getConstructors()
            返回所有具有public屬性的構造函數數組
            Constructor getDeclaredConstructor(Class[] params)
            根據構造函數的參數,返回一個具體的構造函數(不分public和非public屬性)
            Constructor getDeclaredConstructors()
            返回該類中所有的構造函數數組(不分public和非public屬性)
            2、獲取類的成員方法
            與獲取構造方法的方式相同,存在四種獲取成員方法的方式。
            Method getMethod(String name, Class[] params)
            根據方法名和參數,返回一個具體的具有public屬性的方法
            Method[] getMethods()
            返回所有具有public屬性的方法數組
            Method getDeclaredMethod(String name, Class[] params)
            根據方法名和參數,返回一個具體的方法(不分public和非public屬性)
            Method[] getDeclaredMethods()
            返回該類中的所有的方法數組(不分public和非public屬性)
            3、獲取類的成員變量(成員屬性)
            存在四種獲取成員屬性的方法
            Field getField(String name)
            根據變量名,返回一個具體的具有public屬性的成員變量
            Field[] getFields()
            返回具有public屬性的成員變量的數組
            Field getDeclaredField(String name)
            根據變量名,返回一個成員變量(不分public和非public屬性)
            Field[] getDelcaredFields()
            返回所有成員變量組成的數組(不分public和非public屬性)

          posted @ 2014-09-24 15:36 順其自然EVO 閱讀(175) | 評論 (0)編輯 收藏

          EnterpriseFrameWork框架基礎功能之字典數據配置管理

          框架中的“通用字典數據配置管理”主要解決的問題是,所有的行業軟件給客戶實施第一步一般都是基礎數據的維護,一個系統的字典是少不了的,涉及業務范圍越廣字典就越多,如果每一個字典數據都做一個界面來進行維護數據的話,那開發工作量還是比較大的,所以得考慮設計一個通用的模塊來管理這些字典數據;
            1)通用字典管理功能清單
            2)通用字典管理界面展示,包括Winform版和Web版
           3)通用字典管理核心業務流程圖與數據庫表關系圖
            4)通用字典管理關鍵點技術實現
            1.字典保存數據實現
          //保存數據
          public Object SaveResultDataTable(int titleId, string IdName, object IdValue, Dictionary<string, object> fieldAndValue)
          {
          if (IdValue.Equals(System.DBNull.Value) == true)//插入數據
          {
          string fields = "";
          string values = "";
          string strsql = "insert into {0} ({1}) values({2})";
          foreach (KeyValuePair<string, object> val in fieldAndValue)
          {
          fields += (fields == "" ? "" : ",") + val.Key;
          values += (values == "" ? "" : ",") + ConvertDBValue(val.Value);
          }
          BaseGeneralTitle title = NewObject<BaseGeneralTitle>().getmodel(titleId) as BaseGeneralTitle;
          IdValue = oleDb.InsertRecord(string.Format(strsql, title.TableName, fields, values));
          }
          else//更新數據
          {
          string field_values = "";
          string strsql = "update  {0} set {1} where {2}";
          foreach (KeyValuePair<string, object> val in fieldAndValue)
          {
          field_values += (field_values == "" ? "" : ",") + val.Key + "=" + ConvertDBValue(val.Value);
          }
          BaseGeneralTitle title = NewObject<BaseGeneralTitle>().getmodel(titleId) as BaseGeneralTitle;
          oleDb.DoCommand(string.Format(strsql, title.TableName, field_values, IdName + "=" + ConvertDBValue(IdValue)));
          }
          return IdValue;
          }
            2.Web版JqueryEasyUI的Gird控件動態列
          <div id="resulttool" class="toolbar">
          <a href="#" class="easyui-linkbutton" plain="true" iconCls="icon-search" onclick="btnresult_search();">查詢</a>
          <a href="#" class="easyui-linkbutton" plain="true" iconCls="icon-add" onclick="btnresult_addData();">增加</a>
          <a href="#" class="easyui-linkbutton" plain="true" iconCls="icon-edit" onclick="btnresult_editData();">編輯</a>
          <a href="#" class="easyui-linkbutton" plain="true" iconCls="icon-cancel" onclick="btnresult_delData();">刪除</a>
          </div>
          <table id="resultGird"  class="easyui-datagrid" fit="true" border="false" toolbar="#resulttool" iconCls="icon-edit" pagination="true" idField="<%=Session["resulstDataKeyName"]%>">
          <thead>
          <tr>
          <th field="ck" checkbox="true"></th>
          <%=Session["resulstDatacolmodel"]%>
          </tr>
          </thead>
          </table>

          posted @ 2014-09-24 15:34 順其自然EVO 閱讀(207) | 評論 (0)編輯 收藏

          AppScan Source V8.8 中棄用的功能

          從 AppScan Source V8.8 開始,不再支持以下操作系統
            Microsoft Windows XP
            Microsoft Windows Server 2003,所有版本和修訂版
            此外:
            Visual Studio 2005 項目文件不再受支持,而且 AppScan Source for Development(Visual Studio 插件) 不再能適用于 Visual Studio 2005。
            Eclipse V3.3、V3.4 和 V3.5 項目文件和工作空間不再受支持,而且 AppScan Source for Development(Eclipse 插件) 不再能適用于 Eclipse V3.3、V3.4 和 V3.5。
            Rational Application Developer for WebSphere? Software (RAD) V7.x 項目文件和工作空間不再受支持,而且 IBM Security AppScan Source for Development plug-in for IBM Rational Application Developer for WebSphere Software (RAD) 不再能適用于 RAD V7.x。
            Java 和 JSP 編譯不再支持 Tomcat V3 (Jasper 1)。如果要升級 AppScan Source 并使用該版本的 Tomcat,您需要將 Tomcat 升級到 AppScan Source V8.8 支持的版本(請參閱 AppScan Source 系統需求以了解受支持的 Tomcat 版本)。
            IBM Rational ClearQuest? V7.0 和 IBM Rational Team Concert? V2.0.0.2 不再是受支持的缺陷跟蹤系統。
            注意:如果之前裝的8.7的AppScan Enterprise Server,現在把AppScan Source升級到8.8,運行會提示版本不兼容!

          posted @ 2014-09-24 15:33 順其自然EVO 閱讀(512) | 評論 (0)編輯 收藏

          解決Junit單元測試 找不到類

           做junit 單元測試時,發現怎么執行都是以前編譯過得代碼。
            最后找到原因了, src/test/java 編譯完的.class路徑是 Default output folder
            Default output folder:  zphVip/src/main/webapp/WEB-INF/classes
            解決
            1 勾選 Allow output floders for source folders  ------允許源文件夾編譯過后的.class輸入文件夾自己指定
            2 Edit 指定 output floder為 target/classes-----不適用默認,自己指定output floder

          posted @ 2014-09-24 15:33 順其自然EVO 閱讀(645) | 評論 (0)編輯 收藏

          在MS單元測試中引發期望異常

           首先準備一個引發異常的方法。
            1 public static void ThrowException()
            2 {
            3     throw new ArgumentException();
            4 }
            然后在單元測試項目中,寫下測試方法。
            [TestMethod]
            [ExpectedException(typeof(ArgumentException))]// 構造函數中為期望引發的異常。
            public void ThrowExceptionTest()
            {
            Program.ThrowException();// 調用被測試的方法。
            }
            如果測試通過,則說明被測試的方法與預期正確,否則被測試的方法邏輯存在錯誤。

          posted @ 2014-09-24 15:32 順其自然EVO 閱讀(147) | 評論 (0)編輯 收藏

          僅列出標題
          共394頁: First 上一頁 41 42 43 44 45 46 47 48 49 下一頁 Last 
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 阿克苏市| 兴安盟| 上犹县| 潜江市| 集贤县| 衡水市| 彭州市| 嘉鱼县| 金秀| 海宁市| 台湾省| 苍南县| 平顶山市| 璧山县| 依安县| 宁晋县| 周宁县| 塔河县| 汪清县| 杨浦区| 侯马市| 岢岚县| 洛扎县| 麟游县| 彭泽县| 新竹市| 壤塘县| 蒙城县| 福贡县| 得荣县| 垣曲县| 安岳县| 瓦房店市| 德格县| 清河县| 盘山县| 武陟县| 盈江县| 抚顺县| 三明市| 平和县|