#
Jspxcms-5.2.0-release今天正式發(fā)布。
更新列表:
1、增加廣告管理的標(biāo)簽
2、描述去除空格。
3、tag增加欄目參數(shù)。
4、InfoList標(biāo)簽中加上模型參數(shù)。
5、select字段支持key、value。
6、支持可查詢字段。
7、文檔管理左邊欄及列表頁(yè)顯示所屬模型。
8、欄目管理左邊欄及列表頁(yè)顯示所屬模型。
9、修復(fù)會(huì)員投稿上傳獲取圖片目錄問(wèn)題。
10、修復(fù)IE8下視頻無(wú)法播放。
11、更新新浪采集規(guī)則,適用采集改版后的新浪網(wǎng)。
12、后臺(tái)默認(rèn)給予歡迎頁(yè)權(quán)限。
13、默認(rèn)的新浪采集報(bào)錯(cuò)(內(nèi)容沒(méi)有圖片)的內(nèi)容報(bào)錯(cuò)。
14、投稿編輯器改為ueditor。
15、投稿更新時(shí),欄目是否允許投稿判讀有誤。
16、采集是否提交沒(méi)有默認(rèn)值。
17、新聞模型默認(rèn)增加標(biāo)題圖字段。
18、增加默認(rèn)專題模型。
19、專題管理上傳控件改為swfupload。
20、徹底刪除文章后,評(píng)論沒(méi)有刪除。
21、會(huì)員投稿報(bào)錯(cuò)。
22、全局自定義表郵件數(shù)據(jù)有重復(fù)數(shù)據(jù)及無(wú)效數(shù)據(jù)。
23、文章翻頁(yè)第二頁(yè)標(biāo)題缺失。
可獨(dú)立管理的站群:
支持多組織、多站點(diǎn)、獨(dú)立管理的網(wǎng)站群,各個(gè)站點(diǎn)可以有獨(dú)立的管理員,對(duì)本站用戶、組織、模型、欄目等信息進(jìn)行獨(dú)立管理,互不干擾。
無(wú)侵入式二次開(kāi)發(fā):
支持無(wú)侵入式插件和二次開(kāi)發(fā),無(wú)需修改系統(tǒng)原有代碼,即可無(wú)縫整合Entity、Service、Controller、功能菜單、權(quán)限、標(biāo)簽、國(guó)際化等功能。查看教程。
高并發(fā):
jspxcms有近乎完美的性能表現(xiàn),在沒(méi)有做特殊優(yōu)化、純動(dòng)態(tài)頁(yè)下,支持高并發(fā)訪問(wèn)。
對(duì) http://demo.jspxcms.com/ 測(cè)試結(jié)果簡(jiǎn)要描述:5000次請(qǐng)求,500次并發(fā),全部成功,總耗時(shí)31.124秒,每秒處理160.65個(gè)請(qǐng)求,每個(gè)請(qǐng)求耗時(shí)6.225毫秒。
對(duì) http://demo.jspxcms.com/node/40.jspx 測(cè)試結(jié)果簡(jiǎn)要描述:5000次請(qǐng)求,500次并發(fā),全部成功,總耗時(shí)11.969秒,每秒處理417.73個(gè)請(qǐng)求,每個(gè)請(qǐng)求耗時(shí)2.394毫秒。
詳細(xì)測(cè)試報(bào)告http://bbs.jspxcms.com/thread-35-1-1.html
百萬(wàn)級(jí)數(shù)據(jù)支持:
很多cms在小數(shù)據(jù)量下可以運(yùn)行的不錯(cuò),但在日積月累的數(shù)據(jù)量增加,會(huì)讓這些cms運(yùn)行緩慢、不堪重負(fù)。
jspxcms在不需要任何特殊處理和優(yōu)化的情況下,輕松支持百萬(wàn)級(jí)數(shù)據(jù)量,且在純動(dòng)態(tài)頁(yè)訪問(wèn)的情況下,一樣快速如飛。
全站靜態(tài)化:
可以對(duì)所有的欄目頁(yè)、文檔頁(yè)做靜態(tài)化處理,在數(shù)據(jù)量大的情況下,可以設(shè)置前n頁(yè)靜態(tài)化,后面n頁(yè)為動(dòng)態(tài)頁(yè)。
下載及演示:
下載地址:http://www.jspxcms.com
演示站:http://demo.jspxcms.com 后臺(tái):http://demo.jspxcms.com/cmscp/index.do
主要技術(shù):SpringMVC3.2、Spring3.2、JPA2.0、JSP2.0、Freemarker2.3、Spring Data JPA,QueryDSL、Shiro、Lucene等。
技術(shù)亮點(diǎn):JPA、Spring Data JPA、QueryDSL組成的無(wú)比簡(jiǎn)潔高效的持久化技術(shù);Shiro安全框架;Lucene近實(shí)時(shí)檢索;Freemarker模板技術(shù);仿Gmail驗(yàn)證碼等。
功能列表:
1、文檔。(新聞、圖集、下載、視頻、作品、文庫(kù)、招聘等)
2、欄目。(無(wú)限級(jí)數(shù)欄目管理)
3、文件。(zip上傳自解壓、zip打包下載、模板、圖片、js、css)
4、生成。(全文檢索、頁(yè)面靜態(tài)化、定時(shí)任務(wù)、任務(wù)管理)
5、模塊。(文檔屬性管理、專題類別管理、專題管理、TAG管理、評(píng)論管理、敏感詞管理、評(píng)分組管理、附件管理)
6、擴(kuò)展。(友情鏈接類型管理、友情鏈接管理、留言板類型管理、留言板管理、廣告版位管理、廣告管理、投票管理)
7、插件。(簡(jiǎn)歷管理、數(shù)據(jù)庫(kù)備份)
8、統(tǒng)計(jì)。(流量分析、受訪訪問(wèn)、訪問(wèn)日志)
9、用戶。(用戶管理、角色管理、會(huì)員組管理、組織管理、全局用戶管理、全局組織管理)
10、系統(tǒng)。(網(wǎng)站設(shè)置、系統(tǒng)設(shè)置、站點(diǎn)管理、模型管理、文檔屬性、工作流組、工作流、發(fā)布點(diǎn)、操作日志)
前臺(tái)模板:
后臺(tái)界面:
摘要:在IT行業(yè),開(kāi)發(fā)和測(cè)試之間的關(guān)系一直是一個(gè)大家津津樂(lè)道的話題。那在周兆熊眼中,開(kāi)發(fā)和測(cè)試是什么樣的?他進(jìn)行了細(xì)致的說(shuō)明,并就兩者的關(guān)系給出了一些建議。
在IT行業(yè),開(kāi)發(fā)和測(cè)試之間的關(guān)系一直是一個(gè)大家津津樂(lè)道的話題。在整個(gè)軟件產(chǎn)品的生命周期中,開(kāi)發(fā)和測(cè)試人員所做的工作分別對(duì)應(yīng)不同的階段,如圖1所示。
圖1 開(kāi)發(fā)和測(cè)試人員的分工
工作內(nèi)容 從圖1可以看出,開(kāi)發(fā)和測(cè)試是一個(gè)上下游的關(guān)系。
具體而言,開(kāi)發(fā)人員主要做這幾件事情:
第一,對(duì)軟件需求說(shuō)明書(shū)進(jìn)行詳細(xì)評(píng)審,弄清楚要開(kāi)發(fā)一個(gè)什么樣的軟件。
第二,編寫(xiě)軟件詳細(xì)設(shè)計(jì)、單元測(cè)試和集成測(cè)試規(guī)程文檔。軟件詳細(xì)設(shè)計(jì)文檔是最重要的文檔,在里面,要寫(xiě)清楚自己程序的流程、函數(shù)設(shè)計(jì)、異常保護(hù)考慮等。在動(dòng)手寫(xiě)程序之前,一定要將軟件詳細(xì)設(shè)計(jì)文檔寫(xiě)好,等評(píng)審?fù)ㄟ^(guò)了再寫(xiě)代碼。
第三,編寫(xiě)代碼,用程序?qū)崿F(xiàn)軟件的功能。很多人認(rèn)為的軟件開(kāi)發(fā)就是寫(xiě)代碼,其實(shí)這是一種很狹隘的理解,寫(xiě)代碼在整個(gè)開(kāi)發(fā)流程中,只占了很小的部分。
第四,程序?qū)懞弥螅_(kāi)發(fā)人員要對(duì)它進(jìn)行單元測(cè)試和集成測(cè)試也叫(自測(cè)),確保程序的正確性。這里就出現(xiàn)了“測(cè)試”二字,但與軟件測(cè)試所做的“測(cè)試”是不同的,他們做的是“系統(tǒng)測(cè)試”。等自測(cè)通過(guò)之后,并且相關(guān)文檔也寫(xiě)好之后,就可以提交程序版本,供測(cè)試人員進(jìn)行測(cè)試了。
相對(duì)開(kāi)發(fā),測(cè)試人員主要做這幾件事情:
第一,參與軟件需求說(shuō)明書(shū)的評(píng)審,對(duì)軟件要實(shí)現(xiàn)的功能有一個(gè)大致的了解。
第二,搭建測(cè)試環(huán)境。這個(gè)是很重要的,也是比較難的事情。什么是“測(cè)試環(huán)境”呢?就是說(shuō),不管什么軟件,都有個(gè)運(yùn)行的條件,如操作系統(tǒng)類型、參數(shù)設(shè)置及配套軟硬件設(shè)施等,這些統(tǒng)稱為“環(huán)境”。為了保證程序功能的正確性,要在軟件發(fā)布之前,盡量模擬軟件實(shí)際的運(yùn)行環(huán)境,這就是搭建測(cè)試環(huán)境時(shí)要做的事情。很多軟件在正式商用之后出問(wèn)題,就是測(cè)試的時(shí)候沒(méi)有還原現(xiàn)場(chǎng)環(huán)境所致。
第三,對(duì)軟件進(jìn)行系統(tǒng)測(cè)試并輸出測(cè)試報(bào)告。所謂系統(tǒng)測(cè)試,就是指將配套的所有軟件都運(yùn)行起來(lái),看一下所有的功能是否正常。當(dāng)出現(xiàn)問(wèn)題的時(shí)候,要及時(shí)和開(kāi)發(fā)人員聯(lián)系,以修正軟件缺陷。
第四,指導(dǎo)現(xiàn)場(chǎng)人員安裝軟件程序,并在必要的時(shí)候親自出差到現(xiàn)場(chǎng)去安裝軟件。因此,測(cè)試人員也可能會(huì)經(jīng)常出差的。
“三足鼎立” 開(kāi)發(fā)人員的主要任務(wù)是用程序完成軟件需求,而測(cè)試人員的主要任務(wù)則是保證程序功能的正確性,他們做事的依據(jù)都是需求開(kāi)發(fā)工程師編寫(xiě)的需求說(shuō)明書(shū)。
在實(shí)際的軟件開(kāi)發(fā)項(xiàng)目中,需求開(kāi)發(fā)工程師、軟件開(kāi)發(fā)工程師和軟件測(cè)試工程師之間的交流是很頻繁的,如圖2所示。
圖2 三類角色的“三足鼎立”
就像“三國(guó)時(shí)期”的魏蜀吳“三足鼎立”一樣,需求開(kāi)發(fā)工程師、軟件開(kāi)發(fā)工程師和軟件測(cè)試工程師所站的立場(chǎng)不同,對(duì)軟件的認(rèn)識(shí)也不同。大家需要相互討論、協(xié)商,挑選出一套最佳的軟件實(shí)現(xiàn)方案。
一些建議 在完成軟件研發(fā)的過(guò)程中,開(kāi)發(fā)和測(cè)試之間的關(guān)系非常的“微妙”,時(shí)而合作如親人,時(shí)而爭(zhēng)論如敵人。我認(rèn)為,為了做出高質(zhì)量的軟件產(chǎn)品來(lái),開(kāi)發(fā)和測(cè)試需要做到:
第一,共同參與軟件需求文檔的評(píng)審,對(duì)程序要實(shí)現(xiàn)的功能有一個(gè)清晰的認(rèn)識(shí)。如果對(duì)需求有疑問(wèn),一定要當(dāng)面提出來(lái)。
第二,在對(duì)需求達(dá)成共識(shí)之后,軟件開(kāi)發(fā)人員嚴(yán)格按照軟件需求文檔上的描述來(lái)編寫(xiě)程序,如果在程序?qū)崿F(xiàn)上有困難,要提出來(lái)和大家討論。軟件測(cè)試人員嚴(yán)格按照需求的描述來(lái)驗(yàn)證程序的功能,如果發(fā)現(xiàn)程序?qū)崿F(xiàn)與需求不符,要及時(shí)與軟件開(kāi)發(fā)人員聯(lián)系,大家共同將程序問(wèn)題解決掉。
第三,如果開(kāi)發(fā)時(shí)間緊張、人手不足,那么在開(kāi)發(fā)人員編寫(xiě)程序的時(shí)候,測(cè)試人員可以幫忙把測(cè)試環(huán)境搭建好。等程序編寫(xiě)好之后,開(kāi)發(fā)人員便可以立即進(jìn)行單元測(cè)試和集成測(cè)試。
第四,不管是需求有問(wèn)題,還是程序有缺陷,大家都可以指出來(lái)。但注意要就事論事,不可將軟件問(wèn)題上升為對(duì)特定個(gè)人的人身攻擊。
第五,雖然是各司其職,也許還身處不同的部門(mén),但大家的共同目標(biāo)是一致的:做出讓客戶滿意的、高質(zhì)量的軟件產(chǎn)品。開(kāi)發(fā)和測(cè)試人員要為了這個(gè)目標(biāo),一起努力。
結(jié)束語(yǔ) 一個(gè)軟件產(chǎn)品的成功需要從各個(gè)環(huán)節(jié)上去把握,因此用人的左手和右手的關(guān)系來(lái)比喻開(kāi)發(fā)和測(cè)試之間的關(guān)系更為恰當(dāng)。好的軟件產(chǎn)品需要開(kāi)發(fā)和測(cè)兩手抓,兩手都要硬。
什么是系統(tǒng)架構(gòu)?
從字面上理解,系統(tǒng)架構(gòu)是系統(tǒng)的框架結(jié)構(gòu),是系統(tǒng)進(jìn)行抽象之后的一個(gè)草圖。它包含了系統(tǒng)中各個(gè)抽象組件的協(xié)作方式。
為什么需要架構(gòu)?
好的架構(gòu)能夠降低系統(tǒng)的創(chuàng)造和維護(hù)成本,特別是維護(hù)成本。一個(gè)系統(tǒng)的創(chuàng)造成本低,而維護(hù)的成本大,特別是互聯(lián)網(wǎng)應(yīng)用,一般情況下把一個(gè)系統(tǒng)搞上線只需要一個(gè)月,但是有的系統(tǒng)搞下線缺需要幾個(gè)月,而維護(hù)則需要數(shù)年。好的設(shè)計(jì)師不會(huì)在系統(tǒng)上線后對(duì)系統(tǒng)進(jìn)行大的修改,從而減少系統(tǒng)的維護(hù)成本。
如果區(qū)分創(chuàng)造和維護(hù)兩個(gè)階段的話,架構(gòu)師分為系統(tǒng)架構(gòu)師和維護(hù)架構(gòu)師,架構(gòu)新的系統(tǒng)的是系統(tǒng)架構(gòu)師,而維護(hù)老系統(tǒng)的則是維護(hù)架構(gòu)師,程序員大多數(shù)愿意做新系統(tǒng)不愿意維護(hù)老系統(tǒng),因?yàn)楦杏X(jué)沒(méi)什么技術(shù)含量,但是維護(hù)老的系統(tǒng)反而更難,因?yàn)槔舷到y(tǒng)的重構(gòu)和改進(jìn)更加復(fù)雜,維護(hù)架構(gòu)師不僅需要讀懂老系統(tǒng)架構(gòu)設(shè)計(jì),還要在不影響老系統(tǒng)功能的情況下,進(jìn)行功能新增和重構(gòu)。我的一位同事在對(duì)一個(gè)舊的系統(tǒng)進(jìn)行重構(gòu)之前,讀了幾個(gè)星期的代碼,然后才開(kāi)始設(shè)計(jì)改進(jìn)方案。
架構(gòu)設(shè)計(jì)的目標(biāo)
設(shè)計(jì)的目標(biāo)圍繞著降低成本這個(gè)需求進(jìn)行。設(shè)計(jì)的目標(biāo)非常多,不同的系統(tǒng)架構(gòu)目標(biāo)也不一致,但是我覺(jué)得比較重要的架構(gòu)目標(biāo)有以下幾個(gè),可擴(kuò)展性,靈活性和可插入性。
可擴(kuò)展性,新的功能容易加入到系統(tǒng)里,降低創(chuàng)造成本。
靈活性,一處修改不會(huì)波及其他的地方,降低維護(hù)成本。
可插入性,同樣的功能可方便的替換,降低創(chuàng)造和維護(hù)成本。
那么如何實(shí)現(xiàn)這三個(gè)目標(biāo)
提高可擴(kuò)展性:把不易變的抽象出來(lái)。抽象層要比實(shí)現(xiàn)層要更穩(wěn)定,抽象層的變化要少。把變化的集中起來(lái),比如把容易變化的功能放在單獨(dú)一個(gè)系統(tǒng)或者一個(gè)模塊里。
靈活性:模塊化,每個(gè)模塊相互獨(dú)立,減少模塊之間的藕合度,修改不會(huì)互相傳遞。
提高可插入性:模塊化,服務(wù)化。
如何開(kāi)始架構(gòu)
當(dāng)一塊新業(yè)務(wù)放在你面前時(shí),如何進(jìn)行系統(tǒng)架構(gòu)?我覺(jué)得需要進(jìn)行以下幾個(gè)步驟的思考:
業(yè)務(wù)分析:輸出業(yè)務(wù)架構(gòu)圖,這個(gè)系統(tǒng)里有多少個(gè)業(yè)務(wù)模塊,從前臺(tái)用戶到底層一共有多少層。
系統(tǒng)劃分:根據(jù)業(yè)務(wù)架構(gòu)圖輸出系統(tǒng)架構(gòu)圖,需要思考的是這塊業(yè)務(wù)劃分成多少個(gè)系統(tǒng),可能一個(gè)系統(tǒng)能支持多個(gè)業(yè)務(wù)。基于什么原則將一個(gè)系統(tǒng)拆分成多個(gè)系統(tǒng)?又基于什么原則將兩個(gè)系統(tǒng)合并成一個(gè)系統(tǒng)?
系統(tǒng)分層:系統(tǒng)是幾層架構(gòu),基于什么原則將一個(gè)系統(tǒng)進(jìn)行分層,分成多少層?
模塊化:系統(tǒng)里有多少個(gè)模塊,哪些需要模塊化?基于什么原則將一類代碼變成一個(gè)模塊。
首先,他們的測(cè)試方法不同:
單元測(cè)試屬于白盒測(cè)試;
集成測(cè)試屬于灰盒測(cè)試的范疇;
系統(tǒng)測(cè)試屬于黑盒測(cè)試。
其次,他們的考察范圍不同,也就是他們測(cè)試的重點(diǎn)不同:
單元測(cè)試主要測(cè)試單元內(nèi)部的數(shù)據(jù)結(jié)構(gòu)、邏輯控制、異常處理等等;
集成測(cè)試主要測(cè)試模塊之間的接口和接口數(shù)據(jù)傳遞的關(guān)系,以及模塊組合后的整體功能;
系統(tǒng)測(cè)試主要測(cè)試整個(gè)系統(tǒng)相對(duì)于需求的符合度。
再次,他們的基準(zhǔn)不同:
單元測(cè)試評(píng)估的主要是邏輯覆蓋率;
集成測(cè)試評(píng)估的主要是接口覆蓋率;
系統(tǒng)測(cè)試評(píng)估的是測(cè)試用例對(duì)需求規(guī)格的覆蓋率。
摘要: HTTP SESSION的管理通常是由容器來(lái)做,但如果是在PAAS環(huán)境下,服務(wù)器不能做變更,則需要由WEB應(yīng)用來(lái)做處理HTTP SESSION。同樣,如果是分布式的環(huán)境下,SESSION的管理也會(huì)帶來(lái)性能問(wèn)題。SPRING推出了處理SESSION的框架:SPRING-SESSION。
SPRING會(huì)重寫(xiě)HTTP SESSION的那一套,使用SESSION也同樣還是用
Code ...
閱讀全文
1、BI與數(shù)據(jù)倉(cāng)庫(kù)(DW)之間的關(guān)系是怎么樣的?
回答這個(gè)問(wèn)題有一個(gè)很恰當(dāng)?shù)谋扔鳎孔雍偷鼗?#8212;—數(shù)據(jù)倉(cāng)庫(kù)是BI的地基:數(shù)據(jù)倉(cāng)庫(kù)將數(shù)據(jù)抽取過(guò)來(lái),清洗完,整合到主題域和多維模型里,然后BI就可以基于主題域和多維模型做各種分析了。如果這個(gè)地基(數(shù)據(jù)倉(cāng)庫(kù))沒(méi)做好,整個(gè)房子(BI項(xiàng)目)就很容易倒塌。
2、BI系統(tǒng)主要是為了幫助企業(yè)解決什么樣的問(wèn)題?如何解決?
1)以前發(fā)生了什么——可以用固定報(bào)表、各種圖標(biāo)、儀表盤(pán)、計(jì)分卡等實(shí)現(xiàn);
2)為什么發(fā)生——可以用例外分析、即席查詢、OLAP分析和數(shù)據(jù)挖掘?qū)崿F(xiàn);
3)現(xiàn)在發(fā)生了什么——可以用EII技術(shù)、預(yù)警和自動(dòng)激發(fā)短信等工具來(lái)實(shí)現(xiàn);
4)將來(lái)會(huì)發(fā)生什么——可以用預(yù)測(cè)分析、數(shù)據(jù)挖掘等來(lái)實(shí)現(xiàn);
5)控制未來(lái)發(fā)展的方向,將活動(dòng)控制到正確的道路上來(lái)——可以用過(guò)程分析、過(guò)程監(jiān)控、統(tǒng)計(jì)過(guò)程控制(SPC)等實(shí)現(xiàn)。
從另一方面來(lái)看,可以這樣看:
支持戰(zhàn)略決策,通過(guò)數(shù)據(jù)反映宏觀和公司的運(yùn)營(yíng)狀況,幫助領(lǐng)導(dǎo)做出正確的戰(zhàn)略決策,起到參謀的作用。
優(yōu)化業(yè)務(wù),通過(guò)數(shù)據(jù)與業(yè)務(wù)的結(jié)合,發(fā)現(xiàn)可優(yōu)化的環(huán)節(jié)和總結(jié)出優(yōu)化方法,提高運(yùn)營(yíng)效率和公司輸出。
業(yè)務(wù)管控,業(yè)務(wù)模式成熟后,通過(guò)BI系統(tǒng)與其它系統(tǒng)對(duì)接,打通,形成循環(huán),通過(guò)數(shù)據(jù)化管理,保證業(yè)務(wù)運(yùn)營(yíng)行在正確的軌道上。
3、大數(shù)據(jù)、云計(jì)算和商業(yè)智能這三者的關(guān)系到底如何,以后的發(fā)展前景有什么看法?
云計(jì)算:著重于存儲(chǔ)(物理內(nèi)存,存儲(chǔ))
大數(shù)據(jù):著重于數(shù)據(jù),在云計(jì)算的基礎(chǔ)上將數(shù)據(jù)整合與存儲(chǔ)
商業(yè)智能:在大數(shù)據(jù)的基礎(chǔ)上,進(jìn)行數(shù)據(jù)建模,數(shù)據(jù)挖掘,然后在Dashboard上展示出規(guī)律
4、BI中的多維數(shù)據(jù)模型和OLAP的實(shí)用價(jià)值在哪?
1)讓分析人員可以快速地從不同的角度感知數(shù)據(jù)的情況。 在數(shù)據(jù)量大且維度指標(biāo)眾多的情況下,人的記憶力往往有限,只能記住某些方面,無(wú)法客觀地了解全局多個(gè)角度,OLAP可以提供幫助
2)在決策時(shí),可以方便讓參與決策的人員(不一定是專業(yè)分析人員)匯聚討論的焦點(diǎn)。 通過(guò)維度組合及條件過(guò)濾,很容易抽絲剝繭,驗(yàn)證各自的想法。 而對(duì)靜態(tài)的固定報(bào)表,由于無(wú)法深入下去,所以討論往往沒(méi)有達(dá)到關(guān)鍵點(diǎn)就作罷
原文出自FineBI商業(yè)智能解決方案官網(wǎng) www.finebi.com
使用SPRING的定時(shí)任務(wù)框架,如果是在分布式的環(huán)境下,由于有多臺(tái)節(jié)點(diǎn),會(huì)產(chǎn)生相同的任務(wù),會(huì)被多個(gè)節(jié)點(diǎn)執(zhí)行,這時(shí)需引入分布式的QUARTZ。
觸發(fā)器:存放時(shí)間排程
任務(wù):蔟業(yè)務(wù)代碼
排程器:負(fù)責(zé)調(diào)度,即在指定的時(shí)間執(zhí)行對(duì)應(yīng)的任務(wù)
如果是分布式QUARTZ,則各個(gè)節(jié)點(diǎn)會(huì)上報(bào)任務(wù),存到數(shù)據(jù)庫(kù)中,執(zhí)行時(shí)會(huì)從數(shù)據(jù)庫(kù)中取出觸發(fā)器來(lái)執(zhí)行,如果觸發(fā)器的名稱和執(zhí)行時(shí)間相同,則只有一個(gè)節(jié)點(diǎn)去執(zhí)行此任務(wù)。
如果此節(jié)點(diǎn)執(zhí)行失敗,則此任務(wù)則會(huì)被分派到另一節(jié)點(diǎn)執(zhí)行。
quartz.properties
#============================================================================
# Configure JobStore
# Using Spring datasource in quartzJobsConfig.xml
# Spring uses LocalDataSourceJobStore extension of JobStoreCMT
#============================================================================
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 5000
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.txIsolationLevelReadCommitted = true
# Change this to match your DB vendor
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#============================================================================
# Configure Main Scheduler Properties
# Needed to manage cluster instances
#============================================================================
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=MY_CLUSTERED_JOB_SCHEDULER
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
web-schedule-applicationcontext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 增加定時(shí)器配置 -->
<!-- 線程執(zhí)行器配置,用于任務(wù)注冊(cè) -->
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="500" />
</bean>
<!-- 設(shè)置調(diào)度 -->
<bean id="webScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:/properties/config/quartz.properties" />
<property name="dataSource" ref="dataSourceCMS" />
<property name="transactionManager" ref="txManager" />
<!-- This name is persisted as SCHED_NAME in db. for local testing could
change to unique name to avoid collision with dev server -->
<property name="schedulerName" value="quartzScheduler" />
<!-- Will update database cron triggers to what is in this jobs file on
each deploy. Replaces all previous trigger and job data that was in the database.
YMMV -->
<property name="overwriteExistingJobs" value="true" />
<property name="startupDelay" value="5"/>
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="jobFactory">
<bean class="com.tcl.project7.boss.common.scheduling.AutowiringSpringBeanJobFactory" />
</property>
<property name="triggers">
<list>
<ref bean="springQuertzClusterTaskSchedulerTesterTigger" />
</list>
</property>
<property name="jobDetails">
<list>
<ref bean="springQuertzClusterTaskSchedulerTesterJobDetail" />
</list>
</property>
<property name="taskExecutor" ref="executor" />
</bean>
<!-- 觸發(fā)器 -->
<bean id="springQuertzClusterTaskSchedulerTesterTigger" class="common.scheduling.PersistableCronTriggerFactoryBean">
<property name="jobDetail" ref="springQuertzClusterTaskSchedulerTesterJobDetail"/>
<property name="cronExpression" value="* * * * * ?" />
</bean>
<bean id="springQuertzClusterTaskSchedulerTesterJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="common.scheduling.SpringQuertzClusterTaskSchedulerTester" />
<!-- fail-over 重寫(xiě)執(zhí)行失敗的任務(wù),default=false -->
<property name="requestsRecovery" value="false"/>
</bean>
</beans>
JOB文件:SpringQuertzClusterTaskSchedulerTester.java
package common.scheduling;
import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.tcl.project7.boss.common.util.UrlUtil;
import com.tcl.project7.boss.common.util.time.TimeUtils;
/**
* <p>Title:SpringQuertzClusterTaskSchedulerTester</p>
* <p>Description:
* 應(yīng)為要持久化等特性操作,需要繼承 QuartzJobBean
* <br>由于要被持久化,所以不能存放xxxxManager類似對(duì)象,
* 只能從每次從QuartzJobBean注入的ApplicationContext 中去取出
*
* </p>
*
*
*/
public class SpringQuertzClusterTaskSchedulerTester extends QuartzJobBean {
private static Logger logger = LoggerFactory.getLogger(SpringQuertzClusterTaskSchedulerTester.class);
@Autowired
private UrlUtil urlUtil;
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
logger.info("------" + TimeUtils.formatTime(new Date()) + "------" + urlUtil.getNginxHost());
System.out.println("------" + TimeUtils.formatTime(new Date()) + "------" + urlUtil.getNginxHost());
}
}
如果JOB中有需要調(diào)用SPRING的BEAN,則需要此文件AutowiringSpringBeanJobFactory.java
package common.scheduling;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
/**
* Autowire Quartz Jobs with Spring context dependencies
* @see http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#15211030
*/
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
由于JOB需要存儲(chǔ)到數(shù)據(jù)庫(kù)中,會(huì)產(chǎn)生PROPERTY的問(wèn)題,需剔除JOB-DATA,需此文件PersistableCronTriggerFactoryBean.java
package common.scheduling;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailAwareTrigger;
/**
* Needed to set Quartz useProperties=true when using Spring classes,
* because Spring sets an object reference on JobDataMap that is not a String
*
* @see http://site.trimplement.com/using-spring-and-quartz-with-jobstore-properties/
* @see http://forum.springsource.org/showthread.php?130984-Quartz-error-IOException
*/
public class PersistableCronTriggerFactoryBean extends CronTriggerFactoryBean {
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
//Remove the JobDetail element
getJobDataMap().remove(JobDetailAwareTrigger.JOB_DETAIL_KEY);
}
}
建表語(yǔ)句,MYSQL:quartzTables.sql
#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
DROP TABLE IF EXISTS QRTZ_JOB_LISTENERS;
DROP TABLE IF EXISTS QRTZ_TRIGGER_LISTENERS;
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS
(
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
IS_STATEFUL VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_JOB_LISTENERS
(
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
JOB_LISTENER VARCHAR(200) NOT NULL,
PRIMARY KEY (JOB_NAME,JOB_GROUP,JOB_LISTENER),
FOREIGN KEY (JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_TRIGGERS
(
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
(
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CRON_TRIGGERS
(
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(200) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_TRIGGER_LISTENERS
(
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
TRIGGER_LISTENER VARCHAR(200) NOT NULL,
PRIMARY KEY (TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_LISTENER),
FOREIGN KEY (TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CALENDARS
(
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_STATEFUL VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (LOCK_NAME)
);
INSERT INTO QRTZ_LOCKS values('TRIGGER_ACCESS');
INSERT INTO QRTZ_LOCKS values('JOB_ACCESS');
INSERT INTO QRTZ_LOCKS values('CALENDAR_ACCESS');
INSERT INTO QRTZ_LOCKS values('STATE_ACCESS');
INSERT INTO QRTZ_LOCKS values('MISFIRE_ACCESS');
commit;
參考:
http://wenku.baidu.com/view/82e3bcbdfd0a79563c1e7223.htmlQuartz集成springMVC 的方案二(持久化任務(wù)、集群和分布式)
http://blog.csdn.net/congcong68/article/details/39256307
摘要: Bootstrap是快速開(kāi)發(fā)Web應(yīng)用程序的前端工具包。它是一個(gè)CSS和HTML的集合,它使用了最新的瀏覽器技術(shù),給你的Web開(kāi)發(fā)提供了時(shí)尚的版式,表單,buttons,表格,網(wǎng)格系統(tǒng)等等。本文向你推薦 50 個(gè) Bootstrap 的插件,可以考慮在你下一個(gè)項(xiàng)目中使用它們。1. Bootstrap Multiselect 2. Bootstrap Dialog 3. Boot...
閱讀全文
https://github.com/wandoulabs/codis
Codis 是一個(gè)分布式 Redis 解決方案, 對(duì)于上層的應(yīng)用來(lái)說(shuō), 連接到 Codis Proxy 和連接原生的 Redis Server 沒(méi)有明顯的區(qū)別 (不支持的命令列表), 上層應(yīng)用可以像使用單機(jī)的 Redis 一樣使用, Codis 底層會(huì)處理請(qǐng)求的轉(zhuǎn)發(fā), 不停機(jī)的數(shù)據(jù)遷移等工作, 所有后邊的一切事情, 對(duì)于前面的客戶端來(lái)說(shuō)是透明的, 可以簡(jiǎn)單的認(rèn)為后邊連接的是一個(gè)內(nèi)存無(wú)限大的 Redis 服務(wù).
Codis 由四部分組成:
Codis Proxy (codis-proxy)
Codis Manager (codis-config)
Codis Redis (codis-server)
ZooKeeper
codis-proxy 是客戶端連接的 Redis 代理服務(wù), codis-proxy 本身實(shí)現(xiàn)了 Redis 協(xié)議, 表現(xiàn)得和一個(gè)原生的 Redis 沒(méi)什么區(qū)別 (就像 Twemproxy), 對(duì)于一個(gè)業(yè)務(wù)來(lái)說(shuō), 可以部署多個(gè) codis-proxy, codis-proxy 本身是無(wú)狀態(tài)的.
codis-config 是 Codis 的管理工具, 支持包括, 添加/刪除 Redis 節(jié)點(diǎn), 添加/刪除 Proxy 節(jié)點(diǎn), 發(fā)起數(shù)據(jù)遷移等操作. codis-config 本身還自帶了一個(gè) http server, 會(huì)啟動(dòng)一個(gè) dashboard, 用戶可以直接在瀏覽器上觀察 Codis 集群的運(yùn)行狀態(tài).
codis-server 是 Codis 項(xiàng)目維護(hù)的一個(gè) Redis 分支, 基于 2.8.13 開(kāi)發(fā), 加入了 slot 的支持和原子的數(shù)據(jù)遷移指令. Codis 上層的 codis-proxy 和 codis-config 只能和這個(gè)版本的 Redis 交互才能正常運(yùn)行.
Codis 依賴 ZooKeeper 來(lái)存放數(shù)據(jù)路由表和 codis-proxy 節(jié)點(diǎn)的元信息, codis-config 發(fā)起的命令都會(huì)通過(guò) ZooKeeper 同步到各個(gè)存活的 codis-proxy.
Codis 支持按照 Namespace 區(qū)分不同的產(chǎn)品, 擁有不同的 product name 的產(chǎn)品, 各項(xiàng)配置都不會(huì)沖突.
目前 Codis 已經(jīng)是穩(wěn)定階段,目前豌豆莢已經(jīng)在使用該系統(tǒng)。
架構(gòu):

特性:
安裝:
界面截圖:
Dashboard
Migrate
Slots
經(jīng)過(guò)幾次搶購(gòu),相信有些 unwire 讀者已經(jīng)買到 Letv X50 Air 超級(jí)智能電視,在家享受它的豐富內(nèi)容,以及準(zhǔn)備欣賞 HKTV 直播劇集了吧。
而它提供的內(nèi)容中,最吸引的肯定是 4K 影片及劇集。相信大家都知道,4K 內(nèi)容檔案本身容量十分大,還要透過(guò)網(wǎng)絡(luò)進(jìn)行串流,一般情況也會(huì)「窒下窒下」,但為何在 X50 Air 上會(huì)如此順暢?以下小編就為大家解構(gòu)一下:
好了,謎底揭曉!
其實(shí)很多時(shí)候欣賞串流內(nèi)容(streaming)時(shí)要等,是因?yàn)?cache 時(shí)間十分長(zhǎng),導(dǎo)致影響載入時(shí)候。
而 Letv 就採(cǎi)用了 CDN(Content Delivery / Distribution Network;內(nèi)容傳遞網(wǎng)路)網(wǎng)路,它的總承載量比單一骨幹最大的頻寬還要大,而且有異地備援,萬(wàn)一某個(gè)伺服器出現(xiàn)故障,系統(tǒng)就會(huì)自動(dòng)調(diào)用其他鄰近地區(qū)的伺服器資源,所以可靠度極之接近 100%;
就算沒(méi)有故障時(shí),樂(lè)視香港的 CDN 網(wǎng)絡(luò)亦可有效回避繁忙擠塞的網(wǎng)絡(luò),並自動(dòng)尋找距離用家最接近的快取伺服器接收內(nèi)容,因此可以改善內(nèi)容存取速度,大大縮短下載時(shí)間,自然可以用串流網(wǎng)絡(luò),順暢欣賞極致 4K 影片內(nèi)容啦。