国产精品一区二区三区久久,中文字幕亚洲欧美,久久精品一区二区三区四区http://www.aygfsteel.com/xiaosao/不懂我的人 , 離不了我 , 該了解了解我 !而懂我的人 , 更離不了我 , 因?yàn)樗麄儛畚?。zh-cnMon, 05 May 2025 05:39:44 GMTMon, 05 May 2025 05:39:44 GMT60<轉(zhuǎn)>標(biāo)題欄新消息提示效果http://www.aygfsteel.com/xiaosao/archive/2011/06/15/352379.htmlcAng^ErcAng^ErWed, 15 Jun 2011 10:24:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/06/15/352379.htmlhttp://www.aygfsteel.com/xiaosao/comments/352379.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/06/15/352379.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/352379.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/352379.html標(biāo)題欄新消息提示如圖:

公司的項(xiàng)目中用到了這個(gè)新消息提示的效果,主要用于提示用戶有新消息。具體實(shí)現(xiàn)代碼如下:

01 var newMessageRemind={
02 _step: 0,
03 _title: document.title,
04 _timer: null,
05 //顯示新消息提示
06 show:function(){
07 var temps = newMessageRemind._title.replace("【   】", "").replace("【新消息】", "");
08 newMessageRemind._timer = setTimeout(function() {
09 newMessageRemind.show();
10 //這里寫Cookie操作
11 newMessageRemind._step++;
12 if (newMessageRemind._step == 3) { newMessageRemind._step = 1 };
13 if (newMessageRemind._step == 1) { document.title = "【   】" + temps };
14 if (newMessageRemind._step == 2) { document.title = "【新消息】" + temps };
15 }, 800);
16 return [newMessageRemind._timer, newMessageRemind._title];
17 },
18 //取消新消息提示
19 clear: function(){
20 clearTimeout(newMessageRemind._timer );
21 document.title = newMessageRemind._title;
22 //這里寫Cookie操作
23 }
24   
25 };

調(diào)用顯示新消息提示:newMessageRemind.show();

調(diào)用取消新消息提示:newMessageRemind.clear();

查看demo:http://www.css88.com/demo/newMessageRemind/

另:?jiǎn)渭兊倪@個(gè)代碼會(huì)出現(xiàn)這么一個(gè)問題:
就是當(dāng)你打開一個(gè)站點(diǎn)很多張頁面的時(shí)候,如過有新消息,那么所有頁面都會(huì)不停的閃,當(dāng)你查看消息后其他頁面仍會(huì)提示。

我們公司是通過使用Cookie的方式解決的,當(dāng)查看新消息后所有標(biāo)題閃動(dòng)的頁面將全部取消提示。

聲明: 本文采用 BY-NC-SA 協(xié)議進(jìn)行授權(quán) | WEB前端開發(fā)
轉(zhuǎn)載請(qǐng)注明轉(zhuǎn)自《標(biāo)題欄新消息提示效果



cAng^Er 2011-06-15 18:24 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>return閉包函數(shù)http://www.aygfsteel.com/xiaosao/archive/2011/06/15/352374.htmlcAng^ErcAng^ErWed, 15 Jun 2011 09:56:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/06/15/352374.htmlhttp://www.aygfsteel.com/xiaosao/comments/352374.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/06/15/352374.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/352374.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/352374.html高手繞道!這跟閉包本身沒什么大的關(guān)系,也不知道怎么取標(biāo)題,隨便湊了個(gè)數(shù),望見諒!

今天一個(gè)剛學(xué)js的朋友給了我一段代碼問為什么方法不執(zhí)行,代碼如下:

1 function  makefunc(x)  {
2         return function (){
3             return  x;
4         }
5     }
6 alert(makefunc(0));

其實(shí)不是不執(zhí)行,只是朋友的意思這里alert出來的應(yīng)該是“0”,而不是function (){return x;}。
不是腳本寫錯(cuò)了,只是沒搞懂return,從當(dāng)前函數(shù)退出,并從那個(gè)函數(shù)返回一個(gè)值。如果返回的是一個(gè)函數(shù),那么返回的也是函數(shù)本身。
可以這樣修改上面的代碼,就是alert(makefunc(0)()):

1 function  makefunc(x)  {
2         return (function (){
3             return  x;
4         })();
5     }
6 alert(makefunc(0)());

如果要返回函數(shù)執(zhí)行的結(jié)果那么首先要讓這個(gè)函數(shù)執(zhí)行,例如:

1 function  makefunc(x)  {
2         return (function (){
3             return  x;
4         })();
5     }
6 alert(makefunc(0));

這里有一個(gè)匿名函數(shù),

1 (function (){
2            return  x;
3        })();

在第一個(gè)括號(hào)內(nèi)是匿名函數(shù),第二個(gè)括號(hào)用于調(diào)用該匿名函數(shù),您可以在第二個(gè)括號(hào)中傳入所需的參數(shù)。例如:

1 (function( x , y){
2     alert( x + y);
3 })(2 ,3 );

聲明: 本文采用 BY-NC-SA 協(xié)議進(jìn)行授權(quán) | WEB前端開發(fā)
轉(zhuǎn)載請(qǐng)注明轉(zhuǎn)自《return閉包函數(shù)



cAng^Er 2011-06-15 17:56 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>頁面翻轉(zhuǎn),讓你的頁面旋轉(zhuǎn)一下http://www.aygfsteel.com/xiaosao/archive/2011/06/10/352061.htmlcAng^ErcAng^ErFri, 10 Jun 2011 10:08:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/06/10/352061.htmlhttp://www.aygfsteel.com/xiaosao/comments/352061.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/06/10/352061.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/352061.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/352061.htmln.styleSheet.cssText = r;這個(gè)寫法是亮點(diǎn),動(dòng)態(tài)載入過css,但從來都沒這么載入過,在公司的項(xiàng)目中試了下,不一樣的感覺.很搞怪.

原帖:http://www.webchina110.cn/?p=328
今天網(wǎng)上閑逛,看到克軍寫了一句話,惡搞一下。憑著這句話的吸引力,我點(diǎn)進(jìn)去了。

哇,居然頁面倒過來了,頁頭和頁腳翻了一個(gè)根頭,其實(shí)我以前還在想,背景圖片是不是可以這樣呢,今天至少在頁面上看到了。

真好奇,立即啟動(dòng)火狐看了一下,哈哈,找到原因了,馬上在試了一下IE,搞定,也OK,哈哈,如果不知道的同學(xué)們,我想你們也想知道這是怎么回事吧。

其實(shí)就是這個(gè)東東在做怪。。。

-moz-transform: rotate(180deg);

-webkit-transform: rotate(180deg);

filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);

三行代碼,分別用來支持moz,webkit和IE的內(nèi)核的瀏覽器。

我們看看克軍是怎么做的呢,他使用了JS,讓代碼立即執(zhí)行的方式。。給頁面增加一個(gè)<sytle>和相應(yīng)的樣式,并且為body增加相應(yīng)的class.下面我將他的js代碼貼出來。嘿嘿!

;(function(){
var d = document, n = d.createElement('style'), r='.flip { -moz-transform: rotate(180deg);-webkit-transform: rotate(180deg);filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); }';
n.type = 'text/css';
if(n.styleSheet)
{
 n.styleSheet.cssText = r;
}
else
{
 n.appendChild(d.createTextNode(r))
}
d.getElementsByTagName('head')[0].appendChild(n);
d.body.className += ' flip';
}

為了使用document方便,他把document傳給了變量d,建立了一個(gè)style標(biāo)簽為變量n,把樣式的內(nèi)容傳給
了變量r,克軍的命名都很簡(jiǎn)潔。
在為這個(gè)n其實(shí)就是style標(biāo)簽了type這個(gè)屬性。
下面是進(jìn)行判斷頁面中style有不有屬性,如果沒有,直接將r,也就是樣式的內(nèi)容放入n中。
如果有,就得使用建立文本并且追加的方式。
我不知道我的解釋對(duì)不對(duì)哈,反正大概意思就是這樣的,歡迎指正。
一切準(zhǔn)備就緒以后,就將n添加到head中去,在將class增加到body上,這樣頁面一加載。。。。你的頁面就會(huì)被旋轉(zhuǎn)180度,當(dāng)然你可以旋轉(zhuǎn)90度,10度,數(shù)字是可以調(diào)整的喲。

2010.09.30  今天在使用過程中,最后發(fā)現(xiàn),原來ie只支持4個(gè)值,分別旋轉(zhuǎn)值可以是1,2,3或4。這些數(shù)字分別代表90,180,270,或360度旋轉(zhuǎn)。



cAng^Er 2011-06-10 18:08 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>Web前端工程師技能列表http://www.aygfsteel.com/xiaosao/archive/2011/06/10/352060.htmlcAng^ErcAng^ErFri, 10 Jun 2011 10:04:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/06/10/352060.htmlhttp://www.aygfsteel.com/xiaosao/comments/352060.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/06/10/352060.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/352060.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/352060.html要打造一流的Web產(chǎn)品開發(fā)團(tuán)隊(duì),在團(tuán)隊(duì)成員基礎(chǔ)能力上一定要下功夫。對(duì)于Web前端產(chǎn)品開發(fā)來說,僅僅掌握Web1.0時(shí)代簡(jiǎn)單的”網(wǎng)頁套接”是完全不夠的。我結(jié)合自己的團(tuán)隊(duì)配備,特此羅列了Web前端產(chǎn)品工程師所涉及的技能列表如下:

通過許多實(shí)際項(xiàng)目,個(gè)人認(rèn)為一個(gè)完備的前端產(chǎn)品開發(fā)團(tuán)隊(duì),必須擁有如下的人才配備,也希望大家補(bǔ)充:

  • 團(tuán)隊(duì)全體成員達(dá)到所有技能中的a級(jí)標(biāo)準(zhǔn)
  • 團(tuán)隊(duì)全體成員必須掌握兩項(xiàng)技能中的b級(jí)標(biāo)準(zhǔn),并保證所有的b級(jí)標(biāo)準(zhǔn)在該團(tuán)隊(duì)中有50%以上成員能達(dá)到
  • 團(tuán)隊(duì)全體成員必須掌握一項(xiàng)技能中的c級(jí)標(biāo)準(zhǔn),并保證所有的c級(jí)標(biāo)準(zhǔn)在該團(tuán)隊(duì)中有25%以上成員能達(dá)到

具體技能描述:

  • 【必備】UserInterface
    1. PhotoShop/Fireworks Design
      a – 配合美工將草圖形成具體的符合WebPage的設(shè)計(jì)
      b – 有快速制作分層高品質(zhì)PSD、PNG的能力
      c – 能迅速將PSD、PNG的內(nèi)容構(gòu)思成div+css或者table等HTML代碼
    2. Flash Design
      a – 基本動(dòng)畫效果
      b – 復(fù)雜的交互體系設(shè)計(jì),了解第三方swf輔助設(shè)計(jì)軟件
      c – 復(fù)雜的交互體系設(shè)計(jì)以及較強(qiáng)的對(duì)各類外埠資源(PNG、JPG、MP3、WAV等)的整合能力。精通部分第三方輔助設(shè)計(jì)軟件(AE、SwishMax、Swift3D等)
  • 【必備】Browser-side (Web Application)
    1. XHTML/CSS
      a – 基本的layout實(shí)現(xiàn)
      b – 嚴(yán)格跨平臺(tái)的layout實(shí)現(xiàn)以
      c – 優(yōu)雅的HTML code,盡可能符合標(biāo)準(zhǔn)并有SEO的考慮因素。在任何平臺(tái)、瀏覽器下基本保持一致。不要求了解各種CSS的hacks,但要求知道遇到問題應(yīng)該如何查閱資料以在第一時(shí)間內(nèi)解決。能夠?yàn)镴avaScript開發(fā)人員提供最好操作的DOM結(jié)構(gòu),讓JS開發(fā)人員在開發(fā)的時(shí)候認(rèn)為”一切都已經(jīng)準(zhǔn)備就緒了”,而不是”捉襟見肘”。
    2. JavaScript/Ajax/DOM
      a – 基本的DOM操作,了解AJAX,可以實(shí)現(xiàn)數(shù)據(jù)通信
      b – 基本的DOM操作,能寫高效率的OOP代碼,以降低維護(hù)成本
      c – 基于需求,進(jìn)行不同的開發(fā),選擇合適的框架,做到代碼效率最高,用戶體驗(yàn)最好,代碼下載量最小,并且可以在單獨(dú)甚至更多產(chǎn)品線中最大限度重用代碼
    3. Flash Developement
      a – 基于Timeline的ActionScript操作,能實(shí)現(xiàn)簡(jiǎn)單交互
      b – 掌握a外,能實(shí)現(xiàn)數(shù)據(jù)層通信(與服務(wù)器以及本地SharedObject)
      c – 精通AS1-3,能根據(jù)需求進(jìn)行各類RIA開發(fā)。無論是要求支持FlashPlayer8的,還是FlashPlayer9的,都能做到開發(fā)效率最高、靈活性最大(比如對(duì)HTML層的接口設(shè)計(jì),等等)。
  • 【必備】Client-side (Desktop Application)
    1. Apollo
      a – 產(chǎn)品級(jí)的封裝,基本技術(shù)了解(如何打包、如何加入HTML和JavaScript等)
      b – 掌握a的同時(shí),能利用Apollo的API獨(dú)立設(shè)計(jì)、開發(fā)OS的文件I/O功能。
      c – 掌握基本技能的同時(shí),對(duì)”3D概念體系”有所認(rèn)知。這里”3D”即:Design(設(shè)計(jì))、Development(開發(fā))、Deploy(產(chǎn)品部署)。能用Apollo
    2. Windows Presentation Foundation、WPF/E(Silverlight)
      (待定,歡迎補(bǔ)充)
  • 【增補(bǔ)】Server-side (修改:經(jīng)考慮,這個(gè)技能不參與評(píng)級(jí))
    本來列舉了”1、Server端簡(jiǎn)單的技術(shù)、腳本”和”2、MediaServer(Red5)接口”作為”Web前端工程師技能列表“的一種(服務(wù)器、數(shù)據(jù)邏輯層技能的)評(píng)判標(biāo)準(zhǔn)。但似乎很多朋友對(duì)于前端工程師是否應(yīng)該掌握Server端技能的必要性表示懷疑。確實(shí),要掌握好上述的展現(xiàn)層技能不是意見容易的事情,而且前端工程師的確非常辛苦。但是,站在另一方面來說,辛苦的原因是什么,我不知道在你日夜奮戰(zhàn)div+CSS的時(shí)候思考過沒有。就我的經(jīng)驗(yàn),前端的辛苦在于以下幾個(gè)方面:

     

    1. 重復(fù)勞動(dòng)多,大量的div+css都是重復(fù)的,即便可以復(fù)制粘貼,但幾千行的div海洋中去尋找一個(gè)入口恐怕都非常痛苦
    2. 需求變更多,往往你折騰幾個(gè)小時(shí)終于把跨平臺(tái)問題解決好了,而且在IE6、7和Firefox下面都能顯示同樣的效果了,甚至連JavaScript交互都已經(jīng)快搞定了。突然上面說需求要變。這無疑是莫大的痛苦。

    也許表面上看,這跟Server端技能無關(guān),但我覺得有好的Server端的意識(shí),一定會(huì)有所幫助(當(dāng)然不可能解決所有的問題)。畢竟信息結(jié)構(gòu)和數(shù)據(jù)庫是密切相關(guān)的,而Server是連接數(shù)據(jù)庫的唯一渠道(至少大多數(shù)B/S應(yīng)用是如此)。掌握Server端的基本技能,對(duì)于同邏輯層開發(fā)人員設(shè)計(jì)接口是非常重要的。而且HTML表現(xiàn)層在開發(fā)時(shí)與數(shù)據(jù)的分離,也與Server端的各種模板技術(shù)有關(guān)。例如PHP中的Smarty模板(我曾經(jīng)用的)、jsp的model2概念等等。HTML結(jié)構(gòu)如何設(shè)計(jì),如何讓HTML重用,甚至在HTML層進(jìn)行OOP的開發(fā)(我現(xiàn)在在新產(chǎn)品線中設(shè)計(jì)的前端開發(fā)流程),都需要Server端的支持。最起碼,你要告訴php程序員你需要什么。如果你完全對(duì)PHP一無所知的話,那也無從談起了。
    此外,對(duì)于創(chuàng)業(yè)團(tuán)隊(duì),往往人手非常有限。為了讓運(yùn)營成本降到最低,所有的技術(shù)人員都有義務(wù)對(duì)Server端技術(shù)有所了解。如果為了修改一個(gè)網(wǎng)頁的標(biāo)題還要跑去喊PHP程序員連接Remote Server的話,那實(shí)在是增加了整個(gè)公司的運(yùn)營成本。
    總結(jié):我認(rèn)為,可以不了解技術(shù)細(xì)節(jié),但應(yīng)該知道原理,最好能掌握一兩套設(shè)計(jì)思想(畢竟數(shù)據(jù)邏輯都在這里走,光看HTML和JavaScript,對(duì)人的見識(shí)還是有局限的,這種局限限制了我自己很久的時(shí)間),那將是一比寶貴的財(cái)富。

  • 【增補(bǔ)】Mobile-side(不參與評(píng)級(jí))
    1. Flashlite
      (待定,歡迎補(bǔ)充)
    2. Java?
      (待定,歡迎補(bǔ)充)

看到很多朋友留言說前端工程師沒前途,我在想,同時(shí)掌握移動(dòng)設(shè)備的技能是否也是拓展前途的一個(gè)必要性?這里再多說幾句,關(guān)于技術(shù)人員的前途,目前在國內(nèi)確實(shí)得用”慘淡”來形容。浮躁的氛圍讓技術(shù)人才往往過早放棄了自己的技術(shù)生涯,而爾虞我詐的整體道德水平也讓單純的技術(shù)人員痛不欲生(我身邊太多了,恩,不說具體細(xì)節(jié)了,呵呵)。

作為一個(gè)技術(shù)人員,開發(fā)人員,在保持純粹地敬業(yè)心態(tài)(這是前提,這么沒有,啥也別談)外,更要學(xué)會(huì)如何保護(hù)自己,如何壯大自身,社會(huì)不會(huì)同情你,只有你自己才能保護(hù)你自己。



cAng^Er 2011-06-10 18:04 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>webkit webApp 開發(fā)技術(shù)要點(diǎn)總結(jié)http://www.aygfsteel.com/xiaosao/archive/2011/06/09/351982.htmlcAng^ErcAng^ErThu, 09 Jun 2011 06:24:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/06/09/351982.htmlhttp://www.aygfsteel.com/xiaosao/comments/351982.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/06/09/351982.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/351982.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/351982.html閱讀全文

cAng^Er 2011-06-09 14:24 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>Jquery插件Thickbox的使用總結(jié)及自定義設(shè)置 http://www.aygfsteel.com/xiaosao/archive/2011/04/26/349052.htmlcAng^ErcAng^ErTue, 26 Apr 2011 08:59:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/04/26/349052.htmlhttp://www.aygfsteel.com/xiaosao/comments/349052.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/04/26/349052.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/349052.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/349052.html

ThickBox運(yùn)行需要的文件

官方下載:

Download thickbox.js or thickbox-compressed.js, ThickBox.css, and the loading graphic (loadingAnimation.gif) to your local machine (or cut and paste the code from the tabs). Along with these three files, a copy of the jQuery JavaScript library is needed. For this site, and ThickBox, I am using the compressed version of jQuery.

首先在 HTML 文件的 head中導(dǎo)入jquery.js 和thickbox.js文件,導(dǎo)入 thickbox.css 文件;并且jquery.js 文件放在前面:

<script src="../Scripts/jquery-latest.pack.js" mce_src="Scripts/jquery-latest.pack.js" type="text/javascript"></script>
<script src="../Scripts/thickbox.js" mce_src="Scripts/thickbox.js" type="text/javascript"></script>
<link href="../Styles/thickbox.css" mce_href="Styles/thickbox.css" rel="stylesheet" type="text/css" />  

最后你只要給元素添加 class=”thickbox” 屬性就可以開始用 thickbox

實(shí)現(xiàn)了一張圖片的彈出展示功能:

<a href="”bg.jpg”" mce_href="”bg.jpg”" class=”thickbox” ><img src="”bg.jpg”" mce_src="”bg.jpg”" alt=”圖片”/></a>
//只需要指定圖片的class為thickbox
彈出框使用方法:
<a href="Default.aspx?keepThis=true&TB_iframe=true&height=400&width=500" title="主頁" class="thickbox" </a>
<input onclick="<web.path:path/>/bannedUserList!unBannedUserList?height=400&width=800&inlineId=myOnPageContent" title="彈出層" class="thickbox" type="button" value="Ban Another" />
//內(nèi)嵌內(nèi)容
<input alt="#TB_inline?height=300&width=400&inlineId=myOnPageContent" title="標(biāo)題" class="thickbox" type="button" value="Show" />
<a href="#TB_inline?height=155&width=300&inlineId=hiddenModalContent&modal=true" class="thickbox">顯示隱藏內(nèi)容a>
//遮罩層
URL后面加?KeepThis=true&TB_iframe=true&height=400&width=600
參數(shù)字符串中加 modal=true
?KeepThis=true&TB_iframe=true&height=400&width=600&modal=true
這樣當(dāng)關(guān)閉ThickBox時(shí)會(huì)調(diào)用ThickBox iframe (self.parent.tb_remove())內(nèi)部的一個(gè)tb_remove()函數(shù)
所有其他參數(shù)字符都必須在TB_iframe 參數(shù)之前。URL中所有"TB" 之后的將被移除。
<a href="index.html?keepThis=true&TB_iframe=true&height=250&width=400" title="標(biāo)題" class="thickbox">打開一個(gè)頁面</a>
<a href="index.html?keepThis=true&TB_iframe=true&height=300&width=500" title="標(biāo)題" class="thickbox">打開一個(gè)頁面</a>
<a href="index.html?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=200&width=300&modal=true" title="標(biāo)題" class="thickbox">打開一個(gè)頁面</a>  

 

自定義設(shè)置:

1、彈出窗口(div)右上角的關(guān)閉按鈕為顯示為"close or esc key",而不是中文的; 如果想把它變成[X]或"關(guān)閉"應(yīng)該怎么來辦呢?

將thickbox.js文件打開,查找關(guān)鍵字"or esc key",將其刪除,并將前面的close更改為[X]或"關(guān)閉",然后把文件另存為UTF-8格式,如果不保存為UTF-8的話,將會(huì)出現(xiàn)亂碼。
2、thickbox 彈出層的遮住層透明度修改

打開thickbox.css查找.TB_overlayBG 進(jìn)行更改

.TB_overlayBG {
background-color:#000;
filter:alpha(opacity=75);
-moz-opacity: 0.75;
opacity: 0.75;
}

3、關(guān)閉層:如果我們需要自己添加一個(gè)關(guān)閉按鈕或者圖片可以使用:

onclick="self.parent.tb_remove();"  

4、關(guān)閉層刷新父頁面,修改關(guān)閉方法 :

function tb_remove() {
$("#TB_imageOff").unbind("click");
$("#TB_closeWindowButton").unbind("click");
$("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
$("#TB_load").remove();
if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
$("body","html").css({height: "auto", width: "auto"});
$("html").css("overflow","");
}
document.onkeydown = "";
document.onkeyup = "";
//刷新父頁面,未指定
window.location.reload();
return false;
}

5、thickbox插件默認(rèn)情況是點(diǎn)擊灰色的遮罩層就會(huì)關(guān)閉取消

把兩個(gè)$("#TB_overlay").click(tb_remove);去掉就可以取消掉

6、updatepanel回發(fā)后thickbox失效的解決方法

只需把以下代碼粘貼至頁面中就OK了。
<script type="text/javascript" language="javascript">
function pageLoad()
{
var isAsyncPostback = Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack();
if (isAsyncPostback)
{
tb_init('a.thickbox, area.thickbox, input.thickbox');
}
}
</script>


cAng^Er 2011-04-26 16:59 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>ThickBox 3.1參數(shù)詳解http://www.aygfsteel.com/xiaosao/archive/2011/04/26/349046.htmlcAng^ErcAng^ErTue, 26 Apr 2011 08:15:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2011/04/26/349046.htmlhttp://www.aygfsteel.com/xiaosao/comments/349046.htmlhttp://www.aygfsteel.com/xiaosao/archive/2011/04/26/349046.html#Feedback2http://www.aygfsteel.com/xiaosao/comments/commentRss/349046.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/349046.html 前幾天寫了一篇關(guān)于ThickBox 3.1的文章:[ThickBox 3.1完美修正版下載],今天在使用這個(gè)東西的時(shí)候發(fā)現(xiàn)里面有許多參數(shù)沒有詳細(xì)解釋,今天抽空整理出來,現(xiàn)和大家分享一下:

先說幾個(gè)參數(shù):
class="thickbox" 調(diào)用特效;
height 打開頁面的高度;
width 打開頁面的寬度;
title="Iframe(Auto Hide)" title的內(nèi)容;
keepThis=true TB_iframe=true 這兩個(gè)參數(shù)沒搞明白什么意思,但通過框架來調(diào)用頁面時(shí)不可缺少;
#TB_inline 調(diào)用當(dāng)前頁面的層;
inlineId 當(dāng)前頁面層的ID;
modal=true 表示禁用title,去掉即可顯示title及可自動(dòng)關(guān)閉;

1、調(diào)用框架,固定寬度和高度,超出顯示滾動(dòng)條 Iframe(auto hide):

<a >OECSPACE</a>


2、打開頁面,固定寬度和高度,無滾動(dòng)條,禁用title, fixed width, fixed height

<a href="boxs.html?keepThis=true&TB_iframe=true&height=100&width=220&modal=true" title="ThickBox 3.1:modal=true表示禁用title,去掉即可顯示title及可自動(dòng)關(guān)閉" class="thickbox">Open iFrame Modal</a>


3、Ajax載入,自動(dòng)寬度和高度,禁用title,頁面無法查看源代碼

<a href="box.html?height=350&width=350&modal=true" title="ThickBox 3.1:Ajax載入,頁面無法查看源代碼" class="thickbox">Example</a>


4、鏈接顯示隱藏的層,層存在于頁面中。

<a href="#TB_inline?height=200&width=300&inlineId=hiddenModalContent&modal=true" title="ThickBox 3.1:鏈接顯示隱藏層" class="thickbox">Show hidden modal content</a>

<div id="hiddenModalContent" style="display:none">
<p>ThickBox hidden modal content. Click to hide.</p>
<p style="text-align:center"><input type="submit" value=" O K " onclick="tb_remove()" /></p>
</div>


5、按鈕顯示隱藏的層,層存在于頁面中。

<input alt="#TB_inline?height=150&width=400&inlineId=myOnPageContent " title="ThickBox 3.1:按鈕顯示隱藏層" class="thickbox" type="button" value="Show" />

<div id="myOnPageContent" style="display:none">
<p>ThickBox hidden modal content.Auto Hide.</p>
</div>


6、單張圖片調(diào)用

<a href="images/plant1.jpg" title="plant" class="thickbox"><img src="images/plant1_t.jpg" alt="ThickBox 3.1" /></a>


7、多張圖片調(diào)用

<a href="images/plant1.jpg" title="plant1" class="thickbox" rel="gallery-plants"><img src="images/plant1_t.jpg" alt="ThickBox 3.1 1" /></a>
<a href="images/plant2.jpg" title="plant2" class="thickbox" rel="gallery-plants"><img src="images/plant2_t.jpg" alt="ThickBox 3.1 2" /></a>
<a href="images/plant3.jpg" title="plant3" class="thickbox" rel="gallery-plants"><img src="images/plant3_t.jpg" alt="ThickBox 3.1 3" /></a>


另外,如果不想點(diǎn)擊圖片關(guān)閉的話,找到thickbox.js,到128行,把下面的代碼:

$("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div>");     

改成:

$("#TB_window").append("<img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div>");     

即可,說白了就是把鏈接去掉。

cAng^Er 2011-04-26 16:15 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>如何求素?cái)?shù)http://www.aygfsteel.com/xiaosao/archive/2008/05/28/203457.htmlcAng^ErcAng^ErWed, 28 May 2008 04:34:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/05/28/203457.htmlhttp://www.aygfsteel.com/xiaosao/comments/203457.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/05/28/203457.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/203457.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/203457.html1。自然數(shù)是0,1,2……
2。素?cái)?shù)是2,3,5……(不包括1的只能背1和它本身整除的自然數(shù))

import java.util.Scanner;

public class Prime {

    //最基本的做法

    private int prime1(int num) {
        int i = 0, s = 0;
        label1: for (int n = 2; n <= num; n++) {
            for (int m = 2; m * m <= n; m++) {
                if (n % m == 0)
                    continue label1;
            }
            s++;
            i++;
            //System.out.println("第" + i + "個(gè)素?cái)?shù)是:" + n);
        }
        return s;
    }

    //6N±1法

    private int prime2(int num){
        int i = 0, s = 0;
        for(int n = 2; n <=3; n ++){
            s++;
            i++;
            //System.out.println("第" + i + "個(gè)素?cái)?shù)是:" + n);
        }
        label1: for(int n = 1; ; n++) {
            label2: for (int m = 0; m <= 1; m++) {
                int tmp = 2 * (3 * n + m) - 1;
                if (tmp > num)
                    break label1;
                for(int k = 2; k * k <= tmp; k++)
                    if (tmp % k == 0)
                        if (m == 0)
                            continue label2;
                        else
                            continue label1;
                s++;
                i++;
                //System.out.println("第" + i + "個(gè)素?cái)?shù)是:" + tmp);
            }
        }
        return s;
    }

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        long start = System.currentTimeMillis();
        int sum = new Prime().prime1(num);
        long end = System.currentTimeMillis();
        System.out.println("方法一共" + sum + "個(gè)素?cái)?shù)");
        System.out.println("用時(shí):" + (end - start));
        start = System.currentTimeMillis();
        sum = new Prime().prime2(num);
        end = System.currentTimeMillis();
        System.out.println("方法二共" + sum + "個(gè)素?cái)?shù)");
        System.out.println("用時(shí):" + (end - start));
       
    }
}

輸入:1000000

運(yùn)行結(jié)果:

方法一共78498個(gè)素?cái)?shù)
用時(shí):3434
方法二共78498個(gè)素?cái)?shù)
用時(shí):3453

(看來基本方法比6N±1法還要更快些,奇怪了,我的程序?qū)懙臎]什么問題阿)


【1】求10000以內(nèi)的所有素?cái)?shù)。
素?cái)?shù)是除了1和它本身之外再不能被其他數(shù)整除的自然數(shù)。由于找不到一個(gè)通項(xiàng)公式來表示所有的素?cái)?shù),所以對(duì)于數(shù)學(xué)家來說, 素?cái)?shù)一直是一個(gè)未解之謎。像著名的 哥德巴赫猜想、孿生素?cái)?shù)猜想,幾百年來不知吸引了世界上多少優(yōu)秀的數(shù)學(xué)家。盡管他們苦心鉆研,嘔心瀝血,但至今仍然未見分曉。
自從有了計(jì)算機(jī)之后,人們借助于計(jì)算機(jī)的威力,已經(jīng)找到了2216091以內(nèi)的所有素?cái)?shù)。
求素?cái)?shù)的方法有很多種,最簡(jiǎn)單的方法是根據(jù)素?cái)?shù)的定義來求。對(duì)于一個(gè)自然數(shù)N,用大于1小于N的各個(gè)自然數(shù)都去除一下N,如果都除不盡,則N為素?cái)?shù),否則N為合數(shù)。
但是,如果用素?cái)?shù)定義的方法來編制計(jì)算機(jī)程序,它的效率一定是非常低的,其中有許多地方都值得改進(jìn)。
第一,對(duì)于一個(gè)自然數(shù)N,只要能被一個(gè)非1非自身的數(shù)整除,它就肯定不是素?cái)?shù),所以不
必再用其他的數(shù)去除。
第二,對(duì)于N來說,只需用小于N的素?cái)?shù)去除就可以了。例如,如果N能被15整除,實(shí)際
上就能被3和5整除,如果N不能被3和5整除,那么N也決不會(huì)被15整除。
第三,對(duì)于N來說,不必用從2到N一1的所有素?cái)?shù)去除,只需用小于等于√N(根號(hào)N)的所有素?cái)?shù)去除就可以了。這一點(diǎn)可以用反證法來證明:
如果N是合數(shù),則一定存在大于1小于N的整數(shù)d1和d2,使得N=d1×d2。
如果d1和d2均大于√N,則有:N=d1×d2>√N×√N=N。
而這是不可能的,所以,d1和d2中必有一個(gè)小于或等于√N。
基于上述分析,設(shè)計(jì)算法如下:
(1)用2,3,5,7逐個(gè)試除N的方法求出100以內(nèi)的所有素?cái)?shù)。
(2)用100以內(nèi)的所有素?cái)?shù)逐個(gè)試除的方法求出10000以內(nèi)的素?cái)?shù)。
首先,將2,3,5,7分別存放在a[1]、a[2]、a[3]、a[4]中,以后每求出一個(gè)素?cái)?shù),只要不大于100,就依次存放在A數(shù)組中的一個(gè)單元 中。當(dāng)我們求100—10000之間的素?cái)?shù)時(shí),可依次用a[1]-a[2]的素?cái)?shù)去試除N,這個(gè)范圍內(nèi)的素?cái)?shù)可以不保存,直接打印。

【2】用篩法求素?cái)?shù)。
簡(jiǎn)單介紹一下厄拉多塞篩法。厄拉多塞是一位古希臘數(shù)學(xué)家,他在尋找素?cái)?shù)時(shí),采用了一種與眾不同的方法:先將2-N的各數(shù)寫在紙上:

在2的上面畫一個(gè)圓圈,然后劃去2的其他倍數(shù);第一個(gè)既未畫圈又沒有被劃去的數(shù)是3,將它畫圈,再劃去3的其他倍數(shù);現(xiàn)在既未畫圈又沒有被劃去的第一個(gè)數(shù) 是5,將它畫圈,并劃去5的其他倍數(shù)……依次類推,一直到所有小于或等于N的各數(shù)都畫了圈或劃去為止。這時(shí),表中畫了圈的以及未劃去的那些數(shù)正好就是小于 N的素?cái)?shù)。

這很像一面篩子,把滿足條件的數(shù)留下來,把不滿足條件的數(shù)篩掉。由于這種方法是厄拉多塞首先發(fā)明的,所以,后人就把這種方法稱作厄拉多塞篩法。
在計(jì)算機(jī)中,篩法可以用給數(shù)組單元置零的方法來實(shí)現(xiàn)。具體來說就是:首先開一個(gè)數(shù)組:a[i],i=1,2,3,…,同時(shí),令所有的數(shù)組元素都等于下標(biāo) 值,即a[i]=i,當(dāng)i不是素?cái)?shù)時(shí),令a[i]=0 。當(dāng)輸出結(jié)果時(shí),只要判斷a[i]是否等于零即可,如果a[i]=0,則令i=i+1,檢查下一個(gè)a[i]。
篩法是計(jì)算機(jī)程序設(shè)計(jì)中常用的算法之一。

【3】用6N±1法求素?cái)?shù)。
任何一個(gè)自然數(shù),總可以表示成為如下的形式之一:
6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,…)
顯然,當(dāng)N≥1時(shí),6N,6N+2,6N+3,6N+4都不是素?cái)?shù),只有形如6N+1和6N+5的自然數(shù)有可能是素?cái)?shù)。所以,除了2和3之外,所有的素?cái)?shù)都可以表示成6N±1的形式(N為自然數(shù))。
根據(jù)上述分析,我們可以構(gòu)造另一面篩子,只對(duì)形如6 N±1的自然數(shù)進(jìn)行篩選,這樣就可以大大減少篩選的次數(shù),從而進(jìn)一步提高程序的運(yùn)行效率和速度。

在程序上,我們可以用一個(gè)二重循環(huán)實(shí)現(xiàn)這一點(diǎn),外循環(huán)i按3的倍數(shù)遞增,內(nèi)循環(huán)j為0-1的循環(huán),則2(i+j)-1恰好就是形如6N±1的自然數(shù)。

http://www.aygfsteel.com/renyangok/archive/2006/11/20/82278.html



cAng^Er 2008-05-28 12:34 發(fā)表評(píng)論
]]>
上傳圖片并生成略縮圖 http://www.aygfsteel.com/xiaosao/archive/2008/04/23/195226.htmlcAng^ErcAng^ErWed, 23 Apr 2008 11:10:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195226.htmlhttp://www.aygfsteel.com/xiaosao/comments/195226.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195226.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/195226.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/195226.html參數(shù)說明
FileBox:上傳表單中的表單名
SavePath:保存路徑
ThumbnailWidth:略縮圖寬
ThumbnailHeight:略縮圖高
FilePath:文件保存路徑(輸出參數(shù))
FileName:文件名稱(輸出參數(shù))
LastError:(輸出錯(cuò)誤)
public static bool UploadImages(System.Web.UI.HtmlControls.HtmlInputFile FileBox,string SavePath,Int32 ThumbnailWidth,Int32 ThumbnailHeight,out String FilePath,out String FileName,out string LastError)
{
DateTime datTime=System.DateTime.Now;
String strTemp;
string strFileName = FileBox.PostedFile.FileName;
bool blnResult;
LastError="";
System.Drawing.Image xImage;
System.Drawing.Bitmap xBitmap;
int PhotoHeight,PhotoWidth;
string BasePath=System.Web.HttpContext.Current.Server.MapPath("../");
Rectangle NewPhoto;
System.Drawing.Imaging.ImageFormat xObject;
string Extension="";
FileName="";
FilePath="";

try
{
if(strFileName=="")
{
LastError="請(qǐng)點(diǎn)擊瀏覽選擇要上傳的文件!";
return false;
}
if(Convert.ToDecimal(FileBox.PostedFile.ContentLength)<= 2000000 &&Convert.ToDecimal(FileBox.PostedFile.ContentLength)>1500)
{
//查看擴(kuò)展名是否合法
Extension=Path.GetExtension(strFileName);
Extension=Extension.ToLower();
if(Extension==".gif" || Extension==".jpg" || Extension==".jpeg" || Extension==".bmp")
{
switch(Extension)
{
case ".gif":
xObject=System.Drawing.Imaging.ImageFormat.Gif;
break;
case ".bmp":
xObject=System.Drawing.Imaging.ImageFormat.Bmp;
break;
default:
xObject=System.Drawing.Imaging.ImageFormat.Jpeg;

break;
}
}
else
{
LastError="上傳的文件不是有效的圖片文件,請(qǐng)上傳格式為:.gif.jpg.bmp的文件!";
return false;
}
//-----------------------------
//生成保存的文件路徑及文件名
//-----------------------------
strTemp = datTime.ToShortDateString().Replace( "-", "");
FileName = datTime.ToLongTimeString().Replace(":","")+ Extension;
FilePath = SavePath + strTemp + "/";
Friendlib.Function.CreateDirectory(BasePath + FilePath);
//保存大圖
xImage=System.Drawing.Bitmap.FromStream(FileBox.PostedFile.InputStream);

xImage.Save(BasePath+FilePath+FileName);
xImage.Dispose();
//-----------------------------
//開始生成縮略圖
//-----------------------------
xBitmap=new Bitmap(BasePath+FilePath+FileName);//------------------

PhotoHeight=xBitmap.Height;
PhotoWidth=xBitmap.Width;
// //判斷圖片的形狀
if(Convert.ToDecimal(PhotoHeight)/Convert.ToDecimal(PhotoWidth)>Convert.ToDecimal(ThumbnailHeight)/Convert.ToDecimal(ThumbnailWidth))//高有余
{
PhotoHeight=Convert.ToInt16((Convert.ToDecimal(ThumbnailHeight)/Convert.ToDecimal(ThumbnailWidth))*Convert.ToDecimal(PhotoWidth));
NewPhoto=new Rectangle(0,0,PhotoWidth,PhotoHeight);
}
else if(Convert.ToDecimal(PhotoHeight)/Convert.ToDecimal(PhotoWidth)<Convert.ToDecimal(ThumbnailHeight)/Convert.ToDecimal(ThumbnailWidth))
{
PhotoWidth=Convert.ToInt16((Convert.ToDecimal(ThumbnailWidth)/Convert.ToDecimal(ThumbnailHeight))*Convert.ToDecimal(PhotoHeight));
NewPhoto=new
Rectangle(Convert.ToInt16((Convert.ToDecimal(xBitmap.Width)-Convert.ToDecimal(PhotoWidth))/2),0,PhotoWidth,PhotoHeight);
}
else
{
NewPhoto= newRectangle(0,0,PhotoWidth,PhotoHeight); < BR> }
System.Drawing.Image myBitmap;
myBitmap=xBitmap.Clone(NewPhoto,System.Drawing.Imaging.PixelFormat.DontCare);
System.Drawing.Image.GetThumbnailImageAbort myCallback = new
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image myThumbnail =
myBitmap.GetThumbnailImage(ThumbnailWidth,ThumbnailHeight, myCallback,
IntPtr.Zero); myThumbnail.Save(BasePath + FilePath +"s"+FileName,xObject);
myThumbnail.Dispose(); myBitmap.Dispose(); xBitmap.Dispose(); return true; }
else
{
blnResult=false; LastError="不能上傳大于2M及小于1.5K的圖片!";
}
}< BR> catch (Exception ex) {
throw new System.Exception((ex.Message + ("\r\n" + ex.StackTrace)));
}
return blnResult;
}
private static bool ThumbnailCallback() { return false; }
//http://www.aygfsteel.com/happyfish/archive/2005/05/11/4162.html 原文地址



cAng^Er 2008-04-23 19:10 發(fā)表評(píng)論
]]>
java面試筆試題大匯總 及c/c++面試試題(轉(zhuǎn)載) http://www.aygfsteel.com/xiaosao/archive/2008/04/23/195223.htmlcAng^ErcAng^ErWed, 23 Apr 2008 11:08:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195223.htmlhttp://www.aygfsteel.com/xiaosao/comments/195223.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195223.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/195223.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/195223.html閱讀全文

cAng^Er 2008-04-23 19:08 發(fā)表評(píng)論
]]>
變態(tài)級(jí)JAVA程序員面試32問http://www.aygfsteel.com/xiaosao/archive/2008/04/23/195220.htmlcAng^ErcAng^ErWed, 23 Apr 2008 10:34:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195220.htmlhttp://www.aygfsteel.com/xiaosao/comments/195220.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195220.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/195220.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/195220.html     第二,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實(shí)現(xiàn))interface(接口)?

     第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。

     第四,&和&&的區(qū)別。

     第五,HashMap和Hashtable的區(qū)別。

     第六,Collection 和 Collections的區(qū)別。

     第七,什么時(shí)候用assert。

     第八,GC是什么? 為什么要有GC?

     第九,String s = new String("xyz");創(chuàng)建了幾個(gè)String Object?

     第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

     第十一,short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)?

     第十二,sleep() 和 wait() 有什么區(qū)別?

     第十三,Java有沒有g(shù)oto?

     第十四,數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法?

     第十五,Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?

     第十六,Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?

     第十七,給我一個(gè)你最常見到的runtime exception。

     第十八,error和exception有什么區(qū)別?

     第十九,List, Set, Map是否繼承自Collection接口?

     第二十,abstract class和interface有什么區(qū)別?

     第二十一,abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized?

     第二十二,接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承實(shí)體類(concrete class)?

     第二十三,啟動(dòng)一個(gè)線程是用run()還是start()?

     第二十四,構(gòu)造器Constructor是否可被override?

     第二十五,是否可以繼承String類?

     第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對(duì)象的其它方法?

     第二十七,try {}里有一個(gè)return語句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后?

     第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?

     第二十九,兩個(gè)對(duì)象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對(duì)不對(duì)?

     第三十,當(dāng)一個(gè)對(duì)象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對(duì)象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?

     第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

     第三十二,編程題: 寫一個(gè)Singleton出來。

以下是答案

第一,談?wù)刦inal, finally, finalize的區(qū)別。
final—修飾符(關(guān)鍵字)如果一個(gè)類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個(gè)類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們?cè)谑褂弥胁槐桓淖儭1宦暶鳛閒inal的變量必須在聲明時(shí)給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載
finally—再異常處理時(shí)提供 finally 塊來執(zhí)行任何清除操作。如果拋出一個(gè)異常,那么相匹配的 catch 子句就會(huì)執(zhí)行,然后控制就會(huì)進(jìn)入 finally 塊(如果有的話)。
finalize—方法名。Java 技術(shù)允許使用 finalize() 方法在垃圾收集器將對(duì)象從內(nèi)存中清除出去之前做必要的清理工作。這個(gè)方法是由垃圾收集器在確定這個(gè)對(duì)象沒有被引用時(shí)對(duì)這個(gè)對(duì)象調(diào)用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統(tǒng)資源或者執(zhí)行其他清理工作。finalize() 方法是在垃圾收集器刪除對(duì)象之前對(duì)這個(gè)對(duì)象調(diào)用的。

     第二,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實(shí)現(xiàn))interface(接口)?
匿名的內(nèi)部類是沒有名字的內(nèi)部類。不能extends(繼承) 其它類,但一個(gè)內(nèi)部類可以作為一個(gè)接口,由另一個(gè)內(nèi)部類實(shí)現(xiàn)。

     第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。
Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用上。具體可見http: //www.frontfree.net/articles/services/view.asp?id=704&page=1
注: 靜態(tài)內(nèi)部類(Inner Class)意味著1創(chuàng)建一個(gè)static內(nèi)部類的對(duì)象,不需要一個(gè)外部類對(duì)象,2不能從一個(gè)static內(nèi)部類的一個(gè)對(duì)象訪問一個(gè)外部類對(duì)象

     第四,&和&&的區(qū)別。
&是位運(yùn)算符。&&是布爾邏輯運(yùn)算符。

     第五,HashMap和Hashtable的區(qū)別。
都屬于Map接口的類,實(shí)現(xiàn)了將惟一鍵映射到特定的值上。
HashMap 類沒有分類或者排序。它允許一個(gè) null 鍵和多個(gè) null 值。
Hashtable 類似于 HashMap,但是不允許 null 鍵和 null 值。它也比 HashMap 慢,因?yàn)樗峭降摹?/p>

     第六,Collection 和 Collections的區(qū)別。
Collections是個(gè)java.util下的類,它包含有各種有關(guān)集合操作的靜態(tài)方法。
Collection是個(gè)java.util下的接口,它是各種集合結(jié)構(gòu)的父接口。

第七,什么時(shí)候用assert。
斷言是一個(gè)包含布爾表達(dá)式的語句,在執(zhí)行這個(gè)語句時(shí)假定該表達(dá)式為 true。如果表達(dá)式計(jì)算為 false,那么系統(tǒng)會(huì)報(bào)告一個(gè) AssertionError。它用于調(diào)試目的:
  assert(a > 0); // throws an AssertionError if a < = 0
斷言可以有兩種形式:    
  assert Expression1 ;
  assert Expression1 : Expression2 ;
Expression1 應(yīng)該總是產(chǎn)生一個(gè)布爾值。
Expression2 可以是得出一個(gè)值的任意表達(dá)式。這個(gè)值用于生成顯示更多調(diào)試信息的 String 消息。
斷言在默認(rèn)情況下是禁用的。要在編譯時(shí)啟用斷言,需要使用 source 1.4 標(biāo)記: 
  javac -source 1.4 Test.java
要在運(yùn)行時(shí)啟用斷言,可使用 -enableassertions 或者 -ea 標(biāo)記。
要在運(yùn)行時(shí)選擇禁用斷言,可使用 -da 或者 -disableassertions 標(biāo)記。
要系統(tǒng)類中啟用斷言,可使用 -esa 或者 -dsa 標(biāo)記。還可以在包的基礎(chǔ)上啟用或者禁用斷言。
可以在預(yù)計(jì)正常情況下不會(huì)到達(dá)的任何位置上放置斷言。斷言可以用于驗(yàn)證傳遞給私有方法的參數(shù)。不過,斷言不應(yīng)該用于驗(yàn)證傳遞給公有方法的參數(shù),因?yàn)椴还苁欠駟⒂昧藬嘌裕蟹椒ǘ急仨殭z查其參數(shù)。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測(cè)試后置條件。另外,斷言不應(yīng)該以任何方式改變程序的狀態(tài)。

    
第八,GC是什么? 為什么要有GC? (基礎(chǔ))。
GC是垃圾收集器。Java 程序員不用擔(dān)心內(nèi)存管理,因?yàn)槔占鲿?huì)自動(dòng)進(jìn)行管理。要請(qǐng)求垃圾收集,可以調(diào)用下面的方法之一:
  System.gc()
  Runtime.getRuntime().gc()

     第九,String s = new String("xyz");創(chuàng)建了幾個(gè)String Object?
兩個(gè)對(duì)象,一個(gè)是“xyx”,一個(gè)是指向“xyx”的引用對(duì)象s。

     第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;

     第十一,short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)?
short s1 = 1; s1 = s1 + 1;有錯(cuò),s1是short型,s1+1是int型,不能顯式轉(zhuǎn)化為short型。可修改為s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正確。

     第十二,sleep() 和 wait() 有什么區(qū)別? 搞線程的最愛
sleep()方法是使線程停止一段時(shí)間的方法。在sleep 時(shí)間間隔期滿后,線程不一定立即恢復(fù)執(zhí)行。這是因?yàn)樵谀莻€(gè)時(shí)刻,其它線程可能正在運(yùn)行而且沒有被調(diào)度為放棄執(zhí)行,除非(a)“醒來”的線程具有更高的優(yōu)先級(jí)
(b)正在運(yùn)行的線程因?yàn)槠渌蚨枞?br /> wait()是線程交互時(shí),如果線程對(duì)一個(gè)同步對(duì)象x 發(fā)出一個(gè)wait()調(diào)用,該線程會(huì)暫停執(zhí)行,被調(diào)對(duì)象進(jìn)入等待狀態(tài),直到被喚醒或等待時(shí)間到。

     第十三,Java有沒有g(shù)oto?
Goto—java中的保留字,現(xiàn)在沒有在java中使用。

     第十四,數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法?
數(shù)組沒有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性。
String有有l(wèi)ength()這個(gè)方法。

     第十五,Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?
方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個(gè)類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。子類的對(duì)象使用這個(gè)方法時(shí),將調(diào)用子類中的定義,對(duì)它而言,父類中的定義如同被“屏蔽”了。如果在一個(gè)類中定義了多個(gè)同名的方法,它們或有不同的參數(shù)個(gè)數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。

     第十六,Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?
Set里的元素是不能重復(fù)的,那么用iterator()方法來區(qū)分重復(fù)與否。equals()是判讀兩個(gè)Set是否相等。
equals()和==方法決定引用值是否指向同一對(duì)象equals()在類中被覆蓋,為的是當(dāng)兩個(gè)分離的對(duì)象的內(nèi)容和類型相配的話,返回真值。

     第十七,給我一個(gè)你最常見到的runtime exception。
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,
ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException

     第十八,error和exception有什么區(qū)別?
error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。
exception 表示一種設(shè)計(jì)或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會(huì)發(fā)生的情況。

第十九,List, Set, Map是否繼承自Collection接口?
List,Set是

     Map不是

     第二十,abstract class和interface有什么區(qū)別?
聲明方法的存在而不去實(shí)現(xiàn)它的類被叫做抽象類(abstract class),它用于要?jiǎng)?chuàng)建一個(gè)體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實(shí)現(xiàn)該類的情況。不能創(chuàng)建abstract 類的實(shí)例。然而可以創(chuàng)建一個(gè)變量,其類型是一個(gè)抽象類,并讓它指向具體子類的一個(gè)實(shí)例。不能有抽象構(gòu)造函數(shù)或抽象靜態(tài)方法。Abstract 類的子類為它們父類中的所有抽象方法提供實(shí)現(xiàn),否則它們也是抽象類為。取而代之,在子類中實(shí)現(xiàn)該方法。知道其行為的其它類可以在類中實(shí)現(xiàn)這些方法。
接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實(shí)現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個(gè)有程序體。接口只可以定義static final成員變量。接口的實(shí)現(xiàn)與子類相似,除了該實(shí)現(xiàn)類不能從接口定義中繼承行為。當(dāng)類實(shí)現(xiàn)特殊接口時(shí),它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實(shí)現(xiàn)了該接口的類的任何對(duì)象上調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動(dòng)態(tài)聯(lián)編將生效。引用可以轉(zhuǎn)換到接口類型或從接口類型轉(zhuǎn)換,instanceof 運(yùn)算符可以用來決定某對(duì)象的類是否實(shí)現(xiàn)了接口。

第二十一,abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized?
都不能

     第二十二,接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承實(shí)體類(concrete class)?
接口可以繼承接口。抽象類可以實(shí)現(xiàn)(implements)接口,抽象類是否可繼承實(shí)體類,但前提是實(shí)體類必須有明確的構(gòu)造函數(shù)。

     第二十三,啟動(dòng)一個(gè)線程是用run()還是start()?
啟動(dòng)一個(gè)線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會(huì)立即運(yùn)行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個(gè)線程。

    第二十四,構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。

     第二十五,是否可以繼承String類?
String類是final類故不可以繼承。

     第二十六,當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對(duì)象的其它方法?
不能,一個(gè)對(duì)象的一個(gè)synchronized方法只能由一個(gè)線程訪問。

     第二十七,try {}里有一個(gè)return語句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后?
會(huì)執(zhí)行,在return前執(zhí)行。

    
第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?
有C背景的程序員特別喜歡問這種問題。

     2 <<  3

     第二十九,兩個(gè)對(duì)象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對(duì)不對(duì)?
不對(duì),有相同的hash code。

     第三十,當(dāng)一個(gè)對(duì)象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對(duì)象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?
是值傳遞。Java 編程語言只由值傳遞參數(shù)。當(dāng)一個(gè)對(duì)象實(shí)例作為一個(gè)參數(shù)被傳遞到方法中時(shí),參數(shù)的值就是對(duì)該對(duì)象的引用。對(duì)象的內(nèi)容可以在被調(diào)用的方法中改變,但對(duì)象的引用是永遠(yuǎn)不會(huì)改變的。

    
第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
switch(expr1)中,expr1是一個(gè)整數(shù)表達(dá)式。因此傳遞給 switch 和 case 語句的參數(shù)應(yīng)該是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。

     第三十二,編程題: 寫一個(gè)Singleton出來。
     Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。
一般Singleton模式通常有幾種種形式:
第一種形式: 定義一個(gè)類,它的構(gòu)造函數(shù)為private的,它有一個(gè)static的private的該類變量,在類初始化時(shí)實(shí)例話,通過一個(gè)public的getInstance方法獲取對(duì)它的引用,繼而調(diào)用其中的方法。
public class Singleton {
private Singleton(){}
//在自己內(nèi)部定義自己一個(gè)實(shí)例,是不是很奇怪?
//注意這是private 只供內(nèi)部調(diào)用
private static Singleton instance = new Singleton();
//這里提供了一個(gè)供外部訪問本class的靜態(tài)方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}
第二種形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個(gè)方法比上面有所改進(jìn),不用每次都進(jìn)行生成對(duì)象,只是第一次
//使用時(shí)生成實(shí)例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
其他形式:
定義一個(gè)類,它的構(gòu)造函數(shù)為private的,所有方法為static的。
一般認(rèn)為第一種形式要更加安全些
第三十三 Hashtable和HashMap
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個(gè)實(shí)現(xiàn)

     HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許

     還有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因?yàn)閏ontains方法容易讓人引起誤解。

     最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在
多個(gè)線程訪問Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap
就必須為之提供外同步。

     Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。



cAng^Er 2008-04-23 18:34 發(fā)表評(píng)論
]]>
SQL Server 2000/2005 分頁SQL — 單條SQL語句 http://www.aygfsteel.com/xiaosao/archive/2008/04/23/195199.htmlcAng^ErcAng^ErWed, 23 Apr 2008 10:15:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195199.htmlhttp://www.aygfsteel.com/xiaosao/comments/195199.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/04/23/195199.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/195199.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/195199.html有關(guān)分頁 SQL 的資料很多,有的使用存儲(chǔ)過程,有的使用游標(biāo)。本人不喜歡使用游標(biāo),我覺得它耗資、效率低;使用存儲(chǔ)過程是個(gè)不錯(cuò)的選擇,因?yàn)榇鎯?chǔ)過程是經(jīng)過預(yù)編譯的,執(zhí)行效率高,也更靈活。先看看單條 SQL 語句的分頁 SQL 吧。

方法1:
適用于 SQL Server 2000/2005
SELECT TOP 頁大小 *
FROM table1
WHERE id NOT IN
          (
          
SELECT TOP 頁大小*(數(shù)-1) id FROM table1 ORDER BY id
          )
ORDER BY id

方法2:
適用于 SQL Server 2000/2005
SELECT TOP 頁大小 *
FROM table1
WHERE id >
          (
          
SELECT ISNULL(MAX(id),0
          FROM 
                (
               
SELECT TOP 頁大小*(數(shù)-1) id FROM table1 ORDER BY id
                ) 
A
          )
ORDER BY id

方法3:
適用于 SQL Server 2005

SELECT TOP 頁大小 * 
FROM 
        (
        
SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNumber,* FROM table1
        ) A
WHERE RowNumber > 頁大小*(頁數(shù)-1)

說明,頁大小:每頁的行數(shù);頁數(shù):第幾頁。使用時(shí),請(qǐng)把“頁大小”和“頁大小*(頁數(shù)-1)”替換成數(shù)字。
http://www.cnblogs.com/anjou/archive/2007/10/17/926944.html


cAng^Er 2008-04-23 18:15 發(fā)表評(píng)論
]]>
解析Java對(duì)象的equals()和hashCode()的使用http://www.aygfsteel.com/xiaosao/archive/2008/04/11/192142.htmlcAng^ErcAng^ErFri, 11 Apr 2008 04:11:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/04/11/192142.htmlhttp://www.aygfsteel.com/xiaosao/comments/192142.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/04/11/192142.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/192142.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/192142.html在Java語言中,equals()和hashCode()兩個(gè)函數(shù)的使用是緊密配合的,你要是自己設(shè)計(jì)其中一個(gè),就要設(shè)計(jì)另外一個(gè)。在多數(shù)情況 下,這兩個(gè)函數(shù)是不用考慮的,直接使用它們的默認(rèn)設(shè)計(jì)就可以了。但是在一些情況下,這兩個(gè)函數(shù)最好是自己設(shè)計(jì),才能確保整個(gè)程序的正常運(yùn)行。最常見的是當(dāng) 一個(gè)對(duì)象被加入收集對(duì)象(collection object)時(shí),這兩個(gè)函數(shù)必須自己設(shè)計(jì)。更細(xì)化的定義是:如果你想將一個(gè)對(duì)象A放入另一個(gè)收集對(duì)象B里,或者使用這個(gè)對(duì)象A為查找一個(gè)元對(duì)象在收集對(duì) 象B里位置的鑰匙,并支持是否容納,刪除收集對(duì)象B里的元對(duì)象這樣的操作,那么,equals()和hashCode()函數(shù)必須開發(fā)者自己定義。其他情 況下,這兩個(gè)函數(shù)是不需要定義的。

equals():

它是用于進(jìn)行兩個(gè)對(duì)象的比較的,是對(duì)象內(nèi)容的比 較,當(dāng)然也能用于進(jìn)行對(duì)象參閱值的比較。什么是對(duì)象參閱值的比較?就是兩個(gè)參閱變量的值得比較,我們 都知道參閱變量的值其實(shí)就是一個(gè)數(shù)字,這個(gè)數(shù)字可以看成是鑒別不同對(duì)象的代號(hào)。兩個(gè)對(duì)象參閱值的比較,就是兩個(gè)數(shù)字的比較,兩個(gè)代號(hào)的比較。這種比較是默 認(rèn)的對(duì)象比較方式,在Object這個(gè)對(duì)象中,這種方式就已經(jīng)設(shè)計(jì)好了。所以你也不用自己來重寫,浪費(fèi)不必要的時(shí)間。

對(duì)象內(nèi)容的比較才是設(shè)計(jì)equals()的真正目的,Java語言對(duì)equals()的要求如下,這些要求是必須遵循的。否則,你就不該浪費(fèi)時(shí)間:
  • 對(duì)稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應(yīng)該返回是“true”。
  • 反射性:x.equals(x)必須返回是“true”。
  • 類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應(yīng)該返回是“true”。
  • 還有一致性:如果x.equals(y)返回是“true”,只要x和y內(nèi)容一直不變,不管你重復(fù)x.equals(y)多少次,返回都是“true”。
  • 任何情況下,x.equals(null),永遠(yuǎn)返回是“false”;x.equals(和x不同類型的對(duì)象)永遠(yuǎn)返回是“false”。
hashCode():
這 個(gè)函數(shù)返回的就是一個(gè)用來進(jìn)行赫希操作的整型代號(hào),請(qǐng)不要把這個(gè)代號(hào)和前面所說的參閱變量所代表的代號(hào)弄混了。后者不僅僅是個(gè)代號(hào)還具有在內(nèi)存中才查找對(duì) 象的位置的功能。hashCode()所返回的值是用來分類對(duì)象在一些特定的收集對(duì)象中的位置。這些對(duì)象是HashMap, Hashtable, HashSet,等等。這個(gè)函數(shù)和上面的equals()函數(shù)必須自己設(shè)計(jì),用來協(xié)助HashMap, Hashtable, HashSet,等等對(duì)自己所收集的大量對(duì)象進(jìn)行搜尋和定位。

這些收集對(duì)象究竟如何工作的,想象每個(gè)元對(duì)象hashCode是一個(gè)箱子的 編碼,按照編碼,每個(gè)元對(duì)象就是根據(jù)hashCode()提供的代號(hào)歸入相應(yīng)的箱子里。所有的箱子加起來就是一個(gè)HashSet,HashMap,或 Hashtable對(duì)象,我們需要尋找一個(gè)元對(duì)象時(shí),先看它的代碼,就是hashCode()返回的整型值,這樣我們找到它所在的箱子,然后在箱子里,每 個(gè)元對(duì)象都拿出來一個(gè)個(gè)和我們要找的對(duì)象進(jìn)行對(duì)比,如果兩個(gè)對(duì)象的內(nèi)容相等,我們的搜尋也就結(jié)束。這種操作需要兩個(gè)重要的信息,一是對(duì)象的 hashCode(),還有一個(gè)是對(duì)象內(nèi)容對(duì)比的結(jié)果。

hashCode()的返回值和equals()的關(guān)系如下:
  • 如果x.equals(y)返回“true”,那么x和y的hashCode()必須相等。
  • 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。


為 什么這兩個(gè)規(guī)則是這樣的,原因其實(shí)很簡(jiǎn)單,拿HashSet來說吧,HashSet可以擁有一個(gè)或更多的箱子,在同一個(gè)箱子中可以有一個(gè) 或更多的獨(dú)特元對(duì)象(HashSet所容納的必須是獨(dú)特的元對(duì)象)。這個(gè)例子說明一個(gè)元對(duì)象可以和其他不同的元對(duì)象擁有相同的hashCode。但是一個(gè) 元對(duì)象只能和擁有同樣內(nèi)容的元對(duì)象相等。所以這兩個(gè)規(guī)則必須成立。

設(shè)計(jì)這兩個(gè)函數(shù)所要注意到的:
如果你設(shè)計(jì)的對(duì)象類型并不使用于收集性對(duì)象,那么沒有必要自己再設(shè)計(jì)這兩個(gè)函數(shù)的處理方式。這是正確的面向?qū)ο笤O(shè)計(jì)方法,任何用戶一時(shí)用不到的功能,就先不要設(shè)計(jì),以免給日后功能擴(kuò)展帶來麻煩。

如果你在設(shè)計(jì)時(shí)想別出心裁,不遵守以上的兩套規(guī)則,那么勸你還是不要做這樣想入非非的事。我還沒有遇到過哪一個(gè)開發(fā)者和我說設(shè)計(jì)這兩個(gè)函數(shù)要違背前面說的兩個(gè)規(guī)則,我碰到這些違反規(guī)則的情況時(shí),都是作為設(shè)計(jì)錯(cuò)誤處理。

當(dāng) 一個(gè)對(duì)象類型作為收集型對(duì)象的元對(duì)象時(shí),這個(gè)對(duì)象應(yīng)該擁有自己處理equals(),和/或處理hashCode()的設(shè)計(jì),而且要遵守前面所說 的兩種原則。equals()先要查null和是否是同一類型。查同一類型是為了避免出現(xiàn)ClassCastException這樣的異常給丟出來。查 null是為了避免出現(xiàn)NullPointerException這樣的異常給丟出來。

如果你的對(duì)象里面容納的數(shù)據(jù)過多,那么這兩個(gè)函數(shù) equals()和hashCode()將會(huì)變得效率低。如果對(duì)象中擁有無法serialized的數(shù)據(jù),equals()有可能在操作中出現(xiàn)錯(cuò)誤。想象 一個(gè)對(duì)象x,它的一個(gè)整型數(shù)據(jù)是transient型(不能被serialize成二進(jìn)制數(shù)據(jù)流)。然而equals()和hashCode()都有依靠 這個(gè)整型數(shù)據(jù),那么,這個(gè)對(duì)象在serialization之前和之后,是否一樣?答案是不一樣。因?yàn)閟erialization之前的整型數(shù)據(jù)是有效的 數(shù)據(jù),在serialization之后,這個(gè)整型數(shù)據(jù)的值并沒有存儲(chǔ)下來,再重新由二進(jìn)制數(shù)據(jù)流轉(zhuǎn)換成對(duì)象后,兩者(對(duì)象在serialization 之前和之后)的狀態(tài)已經(jīng)不同了。這也是要注意的。

 
原文 :http://blog.csdn.net/RichardSundusky/archive/2007/02/12/1508028.aspx


cAng^Er 2008-04-11 12:11 發(fā)表評(píng)論
]]>
Groovy輕松入門——通過與Java的比較,迅速掌握Groovy (更新于2007.09.23)http://www.aygfsteel.com/xiaosao/archive/2008/02/29/182943.htmlcAng^ErcAng^ErFri, 29 Feb 2008 07:30:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/02/29/182943.htmlhttp://www.aygfsteel.com/xiaosao/comments/182943.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/02/29/182943.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/182943.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/182943.html原文:http://www.aygfsteel.com/BlueSUN/archive/2007/03/10/103014.html | 山風(fēng)小子
注意:本教程是針對(duì)Groovy最新版本編寫的


Groovy和Java的相同點(diǎn)有:
3+, 4+, 6+, 8+, 10+, 12+, 13, 14, 15, 18+, 20+, 21, 22, 23, 28+, 29+, 30+, 31+, 32+
+表示Groovy不但涵蓋了Java的語法,而且還有增強(qiáng)部分

Groovy和Java的不
點(diǎn)有:
0, 1, 2, 5, 7, 9, 11, 16, 17, 19, 24, 25, 26, 27
 

下面所列序號(hào)不分先后順序:

0. 在Groovy可以用def定義無類型的變量(定義變量方面def與JavaScript中的var相似),和返回值為無類型的方法,而在Java中沒有def
Groovy:
class Man {
  def name 
= "山風(fēng)小子"
  def introduce() {
    
return "I'm $name" // return可以省略
  }
}

1. Java中的equals方法對(duì)應(yīng)Groovy中的== , 而Java中的==(判斷是否引用同一對(duì)象)對(duì)應(yīng)Groovy中的is方法
eg.
Test1.java :
public class Test {
  
public static void main(String[] args) {
    String name1 
= "山風(fēng)小子";
    String name2 
= new String("山風(fēng)小子");
    
// Groovy中寫為 name1 == name2
    if (name1.equals(name2)) {
      System.out.println(
"equal");
    } 
else {
      System.out.println(
"not equal"); 
    }
    
// Groovy中寫為 name1.is(name2)
    if (name1 == name2) {
      System.out.println(
"identical");
    } 
else {
      System.out.println(
"not identical"); 
    } 
}

與Test1.java相對(duì)應(yīng)的
Test1.groovy :
String name1 = "山風(fēng)小子" // 你也可以這樣寫: def name1 = "山風(fēng)小子"  其中的def可以理解為JavaScript中定義變量的var
String name2 = new String("山風(fēng)小子"//請(qǐng)注意Groovy的句尾的分號(hào)時(shí)可選的,即可要可不要,前提是一行代碼一條語句
// Java中寫為 name1.equals(name2)
if (name1  == name2) {
  System.out.println(
"equal");
else {
  System.out.println(
"not equal"); 
}
// Java中寫為 name1  == name2
if (name1.is(name2)) {
  System.out.println(
"identical");
else {
  System.out.println(
"not identical"); 
}

2. Java中的數(shù)組定義int[] a = {1, 2, 3}; 在Groovy寫成int[] a = [1, 2, 3]
3. Java中的for循環(huán)for (int i = 0; i < len; i++) {...} 在Groovy中還可以寫成for (i in 0..len-1) {...} 或者 for (i in 0..<len) {...}
Java:
for (int i =0; i < len; i++) {
  
// do something
}
Groovy:
for (int i =0; i < len; i++) {
  
// do something
}

// 或者
for (i in 0..len-1) {
  
// do something
}

// 或者
for (i in 0..<len) {
  
// do something
}

4. Java中的方法返回寫為return; 或者return obj; 在Groovy的方法中return是可選的
Java:
public String sayHello() {
  
return "Hello, 山風(fēng)小子";
}
Groovy:
public String sayHello() {
  
return "Hello, 山風(fēng)小子"
}
//或者
public String sayHello() {
  
"Hello, 山風(fēng)小子"
}
//或者
String sayHello() {
  
"Hello, 山風(fēng)小子"
}
//或者
public sayHello() {
  
"Hello, 山風(fēng)小子"
}
// 或者
def sayHello() {
  
"Hello, 山風(fēng)小子"
}

5. Java中的inner class即內(nèi)部類,在Groovy中用Closure實(shí)現(xiàn)(Closure是Java7正在考慮的一個(gè)特性,比inner class在語義方面更完善)
6. Groovy中的注釋比Java多了首行注釋#!,其他與Java相同比如單行注釋://    多行注釋:/*  */   或者是  支持javadoc的/**   */
Java:
/*
 * 多行注釋
 
*/

/**
 * javadoc 注釋
 
*/

// 單行注釋

Groovy:
#! 首行注釋,使Unix shell能夠定位Groovy啟動(dòng)程序以運(yùn)行Groovy代碼,例如
#!/usr/bin/groovy

/*

 * 多行注釋
 
*/

/**
 * javadoc 注釋
 
*/

// 單行注釋


7. Java5中的for-each:for (Type t : iteratable) {...}  在Groovy中,for (t in iteratable) {...}
Java:
for (Type t : iterable) {
  
// do something
}

Groovy:
for (t in iterable) {
  
// do something
}

8. Groovy中switch語句與Java中相同,不過支持更多類型了,比如String
9. Groovy的while語句跟Java相同,但廢棄了do-while (考慮到語義方面的問題,而且do-while可以用其他形式的循環(huán)語句代替,使用頻率低)
10. Java中的String常量表示為"Hello, 山風(fēng)小子",在Groovy中可如下表示
// 雙引號(hào)
"Hello, 山風(fēng)小子"

// 單引號(hào)也可以
'Hello, 山風(fēng)小子'

//多行字符串
"""Hello,
山風(fēng)小子"""

//或者
'''Hello,
山風(fēng)小子
'''

// 替代字符串
def name = "山風(fēng)小子"
"Hello, ${name}"
//或者
"Hello, $name"
11.在Groovy中定義類,定義方法與Java中定義類相同,唯一區(qū)別在于Groovy中類,屬性以及方法默認(rèn)都是public的,而在Java中默認(rèn)是package的,另外,在Groovy中可以用def來定義方法,請(qǐng)看注釋。
Java:
public class Hello {
  
private String name = "山風(fēng)小子";
  
public void sayHello() {
    System.out.println(
"Hello, " + name);
  }
}
Groovy:
class Hello {
  
private String name = "山風(fēng)小子"
  
public void sayHello() {
    
//println與Java中System.out.println()相同
    println "Hello, $name"
  }
  
/* sayHello也可以這樣定義
  def sayHello() {
    println "Hello, $name"
  }
   
*/
}

12.對(duì)象創(chuàng)建在Java寫為Thought t = new Thought(); 在Groovy也可以這樣寫,不過還多了種寫法:def t = new Thought();
13.靜態(tài)方法調(diào)用在Java和Groovy中相同,即ClassName.staticMethodName();
14.實(shí)現(xiàn)接口和繼承父類方面Groovy也與Java完全相同,即實(shí)現(xiàn)接口class ClassName implements InterfaceName {...}
      繼承父類:class ClassName extends SuperClass {...}
15.定義接口方面Groovy與Java完全相同,即interface InterfaceName {...}  //在Groovy中默認(rèn)為public的
16.正則表達(dá)式常量在Java中沒有,在Groovy中表示為 /pattern/
17.Hash常量(類型為java.util.HashMap)在Java沒有,在Groovy中表示為 def frequence = ["the": 5, "hello": 2, "world": 2]
18.類變量即static變量,Groovy與Java相同,static String name = "山風(fēng)小子",在Groovy也可寫為static name = "山風(fēng)小子"
19.在varargs方法方面,Groovy與Java稍有區(qū)別,如下所示:
Java:
// Java: 
public void varargsMethod(Type args) {
  
//do something
}

Groovy:
def varargsMethod(Type[] args) {
  
//do something
}

20.引用當(dāng)前對(duì)象,Groovy和Java相同,在Java中用this表示,在Groovy中也用this表示,而且在Groovy中,this可以出現(xiàn)在static范圍中,指向所在類的類對(duì)象,本例中,this等同于
ThisInStaticScope.class(Java寫法ThisInStaticScope(Groovy寫法)
class ThisInStaticScope {
   
static {
        println 
this
    }
   
// 請(qǐng)不要詫異,參數(shù)類型可以省略。如果方法聲明中有修飾關(guān)鍵字比如public,synchronized,static等,則返回值類型可以省略。
    static main(args) {
        println 
this
    }
}

21.子類中調(diào)用父類方法,Groovy和Java也相同,在Java中 super.methodName() ,在Groovy中 super.methodName()
22.命名空間的定義,Groovy和Java相同,在Java中 package edu.ecust.bluesun;   在Groovy中 package edu.ecust.bluesun     (分號(hào)可省略)
23.在導(dǎo)入類方面,Groovy和Java相同,在Java中 import edu.ecust.bluesun.GroovyTest;  在Groovy中 import edu.ecust.bluesun.GroovyTest
24.List常量(類型為java.util.ArrayList)在Java中沒有, 在Groovy中表示為 def list = [3, 11, "Hello", "山風(fēng)小子", "!"]
25.在異常處理方面,Groovy與Java相同,除了不強(qiáng)制程序員捕獲檢查異常(checked exception)外 (這跟C#很像,如果我沒記錯(cuò)的話 :)
        并且在方法聲明時(shí),也可以不寫throws語句。
26.方法的默認(rèn)參數(shù),Java中沒有,Groovy中表示如下:
class Hello {
  
//如果沒有參數(shù)傳入,默認(rèn)打印出 Hello, 山風(fēng)小子
  def greet(name="山風(fēng)小子") {
    println(
"Hello, $name"//也可省略括號(hào)()
  }
}
27.在Groovy中,語句如果單獨(dú)占一行的話,句尾的分號(hào)(;)可以省略,而在Java中每條語句后面必須跟有分號(hào)(;)
28.在Groovy中,如果不是Boolean或boolean類型,非null或非空(空字符串,[],[:])為true,null為false,而Java中對(duì)象不可以表示true或false;如果是Boolean或boolean類型,與Java中的一樣。
29.在Groovy中,萬事萬物都是對(duì)象!而Java中不是這樣,基本類型(primitive type)就不是對(duì)象。
30.在Java中,Class對(duì)象表示為ClassName.class,而在Groovy中,可以直接用ClassName表示Class對(duì)象
31.Groovy會(huì)自動(dòng)導(dǎo)入java.lang.*, java.util.*, java.net.*, java.io.*, java.math.BigInteger, java.math.BigDecimal,   groovy.lang.*, groovy.util.*,而Java則只自動(dòng)導(dǎo)入java.lang.*
32.Groovy不僅有? :三元操作符,還有?:兩元操作符,但Java只有? :三元操作符。
Groovy:
def a = null;
// 如果a為“空”(null,空串"",[],[:]),那么結(jié)果為?:之后的那個(gè)值; 如果不為“空”,那么結(jié)果就是a
def result = a ?"default result"
println result

= "山風(fēng)小子"
result 
= a ?"default result"
println result




由上可知,Groovy幾乎完全兼容Java的語法,難怪‘江南白衣’稱Groovy是Java的‘私生子’;但由于Groovy不僅借鑒了Java 95%以上的特性,而且還借鑒了許多卓越的動(dòng)態(tài)語言,比如Python, Ruby等,使Groovy成為極其高效敏捷的編程語言,而不僅僅是Java的副本。所以其實(shí)Java++可以作為Groovy的別名,即具有動(dòng)態(tài)特性的Java。

最后,我想補(bǔ)充一句:Groovy的特性遠(yuǎn)不至所列的這些,比如還有Mixins,builder系列:MarkupBuilder,SwingBuilder等,很多都是Groovy中有而Java中沒有,因此就不一一列舉了,想繼續(xù)深入學(xué)習(xí)Groovy,可訪問Groovy官方網(wǎng)站:http://groovy.codehaus.org ,里面有很多例子和教程供大家參閱,也可以參考在下的Groovy高效編程系列(其中一些是在下的筆記)。網(wǎng)上也有《Groovy In Action》電子書下載,大家不妨搜一下。


參考文獻(xiàn)
Differences from Java:http://groovy.codehaus.org/Differences+from+Java


cAng^Er 2008-02-29 15:30 發(fā)表評(píng)論
]]>
Groovy和Grails簡(jiǎn)介http://www.aygfsteel.com/xiaosao/archive/2008/02/21/181031.htmlcAng^ErcAng^ErThu, 21 Feb 2008 04:40:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/02/21/181031.htmlhttp://www.aygfsteel.com/xiaosao/comments/181031.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/02/21/181031.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/181031.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/181031.html轉(zhuǎn)載:原文地址 http://dev2dev.bea.com.cn/techdoc/200601194089.html

摘要

  Java Web應(yīng)用程序框架是企業(yè)Java得以成功的重要原因之一。人們懷疑如果沒有Apache Struts框架Java EE是否能夠如此成功。雖然底層編程語言很重要,但通常是框架使編程語言成為引人注目的中心的。如果您經(jīng)常訪問討論論壇,就會(huì)注意到Ruby語言和Ruby On Rails框架之間也是這種情況。Ruby已經(jīng)出現(xiàn)十多年了,然而只是在Ruby On Rails框架流行之后,開發(fā)人員才開始注意到Ruby語言。

  諸如Ruby、PHP和Python之類的腳本語言最近幾年越來越流行,因此,需要開發(fā)一個(gè)Java腳本備選語言和類似Rails的針對(duì)Java環(huán)境的框架。Groovy就是這個(gè)腳本語言,而Grails就是這個(gè)框架。

  在本文中我將討論Groovy的Web開發(fā)功能,然后繼續(xù)討論Grails框架。我將開發(fā)一個(gè)示例Grails Web應(yīng)用程序,并討論此框架的各種特性。

Groovy是什么?

  Groovy是一種語言,其語法類似于Java,但比Java更簡(jiǎn)單。它通常被視為腳本/靈活/動(dòng)態(tài)的語言,但是我不喜歡這類形容詞,因?yàn)槲艺J(rèn)為它們只會(huì)令人困惑。如果說Java是一位明智的中年男子,那么Groovy就是他十幾歲的兒子。Groovy具有父親的許多特點(diǎn),但是更為狂野且更為有趣。他們也可以很好地合作。

  Groovy的規(guī)則比Java少得多。例如,要在Java中獲得標(biāo)準(zhǔn)的"Hello World"輸出,您需要編寫一個(gè)類、一個(gè)具有合適參數(shù)的主方法,等等。但是在Groovy中,如果不想編寫所有樣板代碼,您可以拋開類定義和主方法,僅編寫一行代碼即可打印出"Hello World"。

  以下是打印Hello World的文件 Hello.groovy 的內(nèi)容:

println "Hello World" 

  Java平臺(tái)僅關(guān)心使字節(jié)碼得到執(zhí)行。同樣,此平臺(tái)不強(qiáng)迫您使用Java語言。只要提供了字節(jié)碼,工作就會(huì)進(jìn)行。Groovy代碼會(huì)被編譯為字節(jié)碼,而對(duì)于Java平臺(tái)來說,字節(jié)碼是從Java代碼還是Groovy代碼生成的并沒有任何區(qū)別。

  以下是一個(gè)Groovy例子,它顯示了Groovy對(duì)清單、映射和范圍的內(nèi)置支持,并證明了Groovy的簡(jiǎn)單性及其利用Java的強(qiáng)大功能的能力:

// Print Date
def mydate = new java.util.Date()
println mydate
//Iterate through a map
def numbersMAP = ['1':'ONE', '2':'TWO']
for (entry in numbersMAP) {
println "${entry.key} = ${entry.value}"
}
//Introducing the range
def range = 'a'..'d'
//Lists
def numberlist = [1, 2, 3, 4, 5, 6, 7, 8]
println numberlist;
println "Maximum value: ${numberlist.max()}"

  請(qǐng)注意以上代碼直接使用java.util.Date ,對(duì)收集的內(nèi)置支持減少了使用清單、映射和范圍所需的代碼。還有許多其他有趣的Groovy特性,例如閉包和簡(jiǎn)化的XML處理。您可以在groovy.codehaus.org上找到詳細(xì)清單。

  現(xiàn)在讓我們來討論如何將Groovy用于Web開發(fā)。

使用Groovy進(jìn)行Web開發(fā)

  大多數(shù)Java EE教程都從一個(gè)基本servlet例子開始。對(duì)于Groovy Web開發(fā)來說,您將從groovlet(在groovy中servlet的對(duì)應(yīng)概念)開始。如果您在servlet中擺脫了類和doXX() 方法聲明,那么剩下的內(nèi)容就與groovlet很像了。以下是一個(gè)名為 Login.groovy 的groovlet例子,您需要將它置于Web應(yīng)用程序的最高級(jí)目錄:

def username= request.getParameter("username")
def password= request.getParameter("password")
if (username == "java" && password == "developer") {
response.sendRedirect("home.jsp")
session = request.getSession(true);
session.setAttribute("name", username)
}
else {
println """
<h1>Login Invalid</h1>
<p>Your IP has been logged > ${request.remoteHost}</p>
"""
paramMap = request.getParameterMap()
println "<p>You Submitted:</p>"
for (entry in paramMap) {
println "${entry.key} = ${entry.value}<br/>"
}
}

  您可以僅創(chuàng)建一個(gè)簡(jiǎn)單的HTML表單,然后將此表單的行為屬性發(fā)送到 action="Login.groovy"。然后將以下標(biāo)簽添加到web.xml:

<servlet>
<servlet-name>Groovy</servlet-name>
<servlet-class>groovy.servlet.GroovyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Groovy</servlet-name>
<url-pattern>*.groovy</url-pattern>
</servlet-mapping>

  現(xiàn)在只需將要求的Groovy jar 文件添加到WEB-INF/lib 目錄,您的Groovy Web應(yīng)用程序就準(zhǔn)備好在任意Java EE應(yīng)用服務(wù)器上運(yùn)行了。

  您應(yīng)該已經(jīng)注意到代碼中沒有分號(hào),而且使用了隱式變量如request和response。其他隱式變量有context、application、session、out、sout和 html。

  GSP是JSP在groovy中的對(duì)應(yīng)概念。您無需使用println生成HTML;只需將Groovy代碼嵌入HTML頁面。本文中的例子將在提到Grails時(shí)使用GSP。

  請(qǐng)注意,因?yàn)樗写a最終都要轉(zhuǎn)換為字節(jié)碼,所以groovlet和GSP能夠與servlet和JSP輕松協(xié)作。因此您無需區(qū)分groovlet和GSP或者servlet和JSP。

  現(xiàn)在讓我們討論前途無量的Grails框架。如果成功的話,Grails能夠極大地改變開發(fā)Java Web應(yīng)用程序的方式。Ruby on Rails對(duì)Ruby的影響,Grails也能夠?qū)roovy實(shí)現(xiàn)。

Grails特性和架構(gòu)

  Grails試圖使用Ruby On Rails的“規(guī)約編程”(coding by convention)范例來降低對(duì)配置文件和其他樣板代碼的需求。使用“規(guī)約編程” ,如果文件的名稱本身就能說明此文件的用途,那么您就不需要在配置文件中再次聲明這些內(nèi)容了。此框架會(huì)查看文件名,并自己弄清文件用途。通過使用“規(guī)約編程” ,Grails還將自動(dòng)生成Web應(yīng)用程序中需要的許多內(nèi)容。通過使用Grails,您將能夠在很短的時(shí)間內(nèi)、以最小的復(fù)雜性使Web應(yīng)用程序就緒。請(qǐng)看以下例子。

  Grails基于開源技術(shù),例如Spring、Hibernate和SiteMesh。如果您已經(jīng)擅長(zhǎng)這些技術(shù),那么這是件好事;但是如果您由于某種原因不喜歡這些技術(shù),或者您認(rèn)為不僅需要學(xué)習(xí)Grails,還需要學(xué)習(xí)其他三種框架,那么這就不是件好事了。雖然這些技術(shù)能夠幫助Grails執(zhí)行得更好,但是學(xué)習(xí)四種框架對(duì)于大多數(shù)人來說是一個(gè)很高的門檻。Grails文檔目前主要關(guān)注它與Spring、Hibernate和其他程序的集成,然而我認(rèn)為它需要采用相反的方法,將Grails推行為一個(gè)簡(jiǎn)單快速的Web應(yīng)用程序開發(fā)框架。開發(fā)人員無需擔(dān)心或考慮底層發(fā)生了什么。

  幸運(yùn)的是,一旦您開始使用Grails,您將發(fā)現(xiàn)Grails隱藏了這些框架的大多數(shù)底層復(fù)雜性。如果您忘掉在底層運(yùn)行的是Spring、Hibernate和其他程序,那么事情就會(huì)變得簡(jiǎn)單。

  Grails應(yīng)用程序的三個(gè)層是:

  1. 由視圖和控制器組成的Web層
  2. 由域類和服務(wù)組成的業(yè)務(wù)邏輯層
  3. 由域類和數(shù)據(jù)源組成的持久層

  大多數(shù)框架都有數(shù)十種特性,其中只有很少幾種得到了廣泛使用。對(duì)于Grails來說,這種關(guān)鍵特性是指“規(guī)則編程”(coding by convention)范例和構(gòu)件的自動(dòng)生成。

  Grails的其他特性包括對(duì)Ajax、驗(yàn)證、單元測(cè)試和功能測(cè)試的內(nèi)置支持。它使用免費(fèi)的開源Canoo WebTest項(xiàng)目來實(shí)現(xiàn)Web應(yīng)用程序的功能測(cè)試。Grails還提供與Quartz Scheduler的集成。

  現(xiàn)在是時(shí)候安裝Grails框架并且編寫您的第一個(gè)應(yīng)用程序了。

Grails安裝

  安裝過程非常簡(jiǎn)單。以下是Grails下載頁面:http://grails.org/Download。您可以從http://dist.codehaus.org/grails/grails-bin-0.2.1.zip下載version 0.2.1。請(qǐng)注意Grails源代碼和文檔作為單獨(dú)的下載提供。下載zip文件之后,只需將其內(nèi)容解壓縮到一個(gè)目錄即可,在我的案例中此目錄是 C:\groovy\grails-0.2.1\。

  創(chuàng)建一個(gè)名為GRAILS_HOME 的新環(huán)境變量,并將其值設(shè)為 C:\groovy\grails-0.2.1\。接下來將GRAILS_HOME\bin 添加到PATH 環(huán)境變量。這樣安裝就完成了。通過在命令提示符界面中運(yùn)行g(shù)rails 命令您可以檢查安裝是否成功。您應(yīng)該獲得此命令的使用信息。

  既然您有了一個(gè)運(yùn)行中的Grails安裝,那么您已經(jīng)為創(chuàng)建Grails Web應(yīng)用程序做好了準(zhǔn)備。

開發(fā)Grails應(yīng)用程序:應(yīng)用程序結(jié)構(gòu)

  多年來我一直計(jì)劃開發(fā)一個(gè)可以幫助我管理衣服的應(yīng)用程序——這個(gè)應(yīng)用程序應(yīng)該能夠告訴我我最喜歡的T恤衫放在哪里、是否洗過、是否熨過,等等。總有一天我會(huì)靠銷售這個(gè)應(yīng)用程序掙上幾百萬,但是現(xiàn)在我將把它用作Grails例子。

  第一步是創(chuàng)建一個(gè)Grails項(xiàng)目目錄結(jié)構(gòu)。在這一步我將在C:\groovy\grailsapps 創(chuàng)建一個(gè)新目錄,并在此級(jí)別打開一個(gè)命令提示符窗口。在此窗口中,執(zhí)行命令grails create-app。要求您輸入應(yīng)用程序名稱。輸入 ClothesMgt。Grails將顯示它為您創(chuàng)建的全部目錄和文件。圖1顯示了最后得到的命令結(jié)構(gòu)。

Groovy和Grails簡(jiǎn)介圖-1

  圖1:Grails項(xiàng)目目錄結(jié)構(gòu)

  此命令將創(chuàng)建約800 KB大小的文件和目錄。這里的想法是此框架遵循已經(jīng)建立的Web應(yīng)用程序開發(fā)慣例,因此它創(chuàng)建的文件和目錄在大多數(shù)Web應(yīng)用程序中是有用的。雖然有些人可能不喜歡這種強(qiáng)制使用某種結(jié)構(gòu)的想法,但是這種基于慣例的自動(dòng)生成正是Grails的RAD特性的基礎(chǔ)。

  如果更仔細(xì)地看一下這些目錄,您就會(huì)發(fā)現(xiàn)存在用于諸如控制器、視圖、測(cè)試、配置文件和標(biāo)簽庫之類東西的目錄。您還會(huì)發(fā)現(xiàn)存在一些基本JavaScript和CSS文件。那么現(xiàn)在應(yīng)用程序的基本結(jié)構(gòu)已經(jīng)有了。您只需做些填空,應(yīng)用程序即可就緒。

  請(qǐng)注意自動(dòng)生成目錄和文件的命令是可選的。您可以手動(dòng)創(chuàng)建全部文件和目錄。如果熟悉Apache Ant,那么您甚至可以打開GRAILS_HOME 目錄中的\src\grails\build.xml 文件,來仔細(xì)查看每個(gè)Grails命令的用途。

數(shù)據(jù)庫

  在此例中我將使用一個(gè) 運(yùn)行于localhost的名為Clothes_Grails的MySQL數(shù)據(jù)庫。Grails內(nèi)置一個(gè)HSQL數(shù)據(jù)庫,這對(duì)測(cè)試簡(jiǎn)單的應(yīng)用程序或僅試用Grails非常有用。如果您使用HSQL DB,那么無需執(zhí)行以下幾步。我將使用MySQL來證明您能夠非常輕松地使用HSQL之外的數(shù)據(jù)庫。

  從http://www.mysql.com/products/connector/j/ 下載MySQL驅(qū)動(dòng)器,并將mysql-connector-java-<version number>-stable-bin.jar 文件放置在ClothesMgt\lib 目錄中。接下來您需要編輯 ClothesMgt\grails-app\conf\ApplicationDataSource.groovy文件。

  現(xiàn)在此文件的內(nèi)容應(yīng)該類似以下內(nèi)容:

class ApplicationDataSource {
boolean pooling = true
String dbCreate = "create-drop"
String url = "jdbc:mysql://localhost/Clothes_Grails"
String driverClassName = "com.mysql.jdbc.Driver"
String username = "grails"
String password = "groovy"
}

  現(xiàn)在讓我們看一下如何使用此數(shù)據(jù)庫和對(duì)象關(guān)系映射。

域類

  Grails的對(duì)象關(guān)系映射(GORM)功能在內(nèi)部使用Hibernate 3,但是您無需了解或更改任何Hibernate設(shè)置。Grails具有稱為“域類”的東西,這些域類的對(duì)象被映射到數(shù)據(jù)庫。您可以使用關(guān)系來鏈接域類,它們也提供用于CRUD(創(chuàng)建/讀取/更新/刪除)操作的功能非常強(qiáng)大的動(dòng)態(tài)方法。

  在此例中,我們將創(chuàng)建三個(gè)域類,其名稱分別是Shirt、Trouser和Cabinet。要?jiǎng)?chuàng)建域類,只需運(yùn)行命令 grails create-domain-class。請(qǐng)記住在您的項(xiàng)目目錄(而不是它的上級(jí)目錄)內(nèi)運(yùn)行此命令。這是一個(gè)常見錯(cuò)誤,雖然我已經(jīng)提醒了您,您還是會(huì)犯至少一次這樣的錯(cuò)誤。

  您必須提供給create-domain-class 命令的唯一輸入是類的名稱。運(yùn)行此命令三次,將Shirt、Trouser和Cabinet作為三個(gè)域類的名稱。Grails現(xiàn)在將在目錄 grails-app/domain/中創(chuàng)建這些域類。它們將僅具有兩個(gè)屬性id 和 version。我將為這些類添加屬性,以便使它們更能代表襯衫、褲子和衣櫥。

  清單1:Cabinet.groovy

class Cabinet {
Long id
Long version
String name
String location
def relatesToMany = [ shirts : Shirt, trousers : Trouser ]
Set shirts = new HashSet()
Set trousers = new HashSet()
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Cabinet)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)) )
}
}

  清單2: Trouser.groovy

class Trouser {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Trouser)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32) ) )
}
}

  清單3: Shirt.groovy

class Shirt {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Shirt)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id >>> 32)))
}
}

  我添加的僅有的幾行聲明了字段名稱和顏色,然后聲明了Cabinet、Shirt和Trouser之間的關(guān)系。每個(gè)Shirt和Trouser都屬于Cabinet,而Cabinet具有shirt和trouser的集合。belongsTo 屬性在此案例中是可選的,因?yàn)樵谝粚?duì)多關(guān)系中,Grails會(huì)將“一”這一方視為所有者。因此您就無需顯式聲明了。在這里我進(jìn)行顯式聲明只是為了使這種關(guān)系更明顯。

  接下來我們將討論Grails應(yīng)用程序的控制器和視圖部分。

控制器和視圖

  既然域類已經(jīng)就緒,讓我們使用generate-all命令自動(dòng)生成基本CRUD Web應(yīng)用程序。運(yùn)行g(shù)rails generate-all 命令三次,當(dāng)被詢問時(shí)提供域類名稱。generate-all 命令的目的是生成每個(gè)域類的控制器和視圖,但是由于bug-245,Grails 0.2.1不能生成控制器。您必須手動(dòng)生成控制器,其方法是對(duì)每個(gè)域類使用generate-controller 命令。

  現(xiàn)在您應(yīng)該在grails-app\controllers 目錄中看到三個(gè)控制器。這些控制器負(fù)責(zé)處理Web應(yīng)用程序中針對(duì)特定域類的請(qǐng)求。因此ShirtController.groovy 將處理Web應(yīng)用程序中與Shirt域類相關(guān)的CRUD請(qǐng)求,等等。現(xiàn)在控制器具有多個(gè)閉包,每個(gè)閉包映射到一個(gè)URI。閉包是Groovy語言很好的一個(gè)特性,然而要習(xí)慣它還是需要一些時(shí)間的。清單4顯示了Shirtcontroller.groovy的一段摘錄。

  清單4:ShirtController.groovy 摘錄

class ShirtController {
def index = { redirect(action:list,params:params) }
def list = {
[ shirtList: Shirt.list( params ) ]
}
def show = {
[ shirt : Shirt.get( params.id ) ]
}
def delete = {
def shirt = Shirt.get( params.id )
if(shirt) {
shirt.delete()
flash.message = "Shirt ${params.id} deleted."
redirect(action:list)
}
else {
flash.message = "Shirt not found with id ${params.id}"
redirect(action:list)
}
}
// ...
}

  在此例中,ShirtController 中的list閉包將處理URI是/shirt/list的請(qǐng)求,等等。您可在控制器中使用您習(xí)慣在Java Web應(yīng)用程序中使用的東西,例如請(qǐng)求、會(huì)話和servletContext。

  請(qǐng)注意:閉包也將值作為顯式返回語句返回,或者作為閉包體中的最后一個(gè)語句的值返回。不要因?yàn)镚rails生成的代碼中沒有return 而困惑。

  一旦控制器完成了對(duì)請(qǐng)求的處理,它必須委托給合適的視圖。Grails使用慣例機(jī)制實(shí)現(xiàn)此操作。因此ShirtController 中的list閉包將委托給視圖 /grails-app/views/shirt/list.gsp 或 /grails-app/views/shirt/list.jsp。 盡管您在使用Grails,全部視圖可以是JSP文件而不是GSP。我?guī)缀鯖]有編寫任何代碼,但是我已經(jīng)準(zhǔn)備好了一個(gè)Web應(yīng)用程序。

  讓我們嘗試部署和運(yùn)行我們的應(yīng)用程序。

在Java EE Server上部署和運(yùn)行Grails

  Grails具有一個(gè)內(nèi)置Resin服務(wù)器,您可使用grails run-app 命令運(yùn)行應(yīng)用程序。此命令會(huì)將應(yīng)用程序部署到Resin服務(wù)器并啟動(dòng)服務(wù)器。因此您現(xiàn)在可以在http://localhost:8080/ClothesMgt 訪問此應(yīng)用程序。您還可以同樣輕松地將應(yīng)用程序部署到任意JavaEE服務(wù)器。我嘗試將它部署到Tomcat。要實(shí)現(xiàn)此操作,我所需要做的是運(yùn)行g(shù)rails war 命令,將生成的war文件復(fù)制到Tomcat中的webapps目錄!

  在此案例中生成的war文件的名稱為 ClothesMgt.war。一旦部署到Tomcat,您就應(yīng)該能夠在http://localhost:8080/ClothesMgt/ 上訪問它,并看到如圖2所示的屏幕。

Groovy和Grails簡(jiǎn)介圖-2

  圖2:Grails 應(yīng)用程序

  通過此應(yīng)用程序,能夠獲得Shirt、Trouser和Cabinet的全部CRUD功能。可以顯示衣櫥的全部數(shù)據(jù)、向衣櫥添加新襯衫和褲子、編輯它們的值和刪除記錄——實(shí)現(xiàn)這些操作都無需編寫任何業(yè)務(wù)邏輯、視圖或數(shù)據(jù)訪問代碼。僅在幾分鐘內(nèi)您就在JavaEE服務(wù)器上部署好了一個(gè)合適的Web應(yīng)用程序。很酷吧?!

  讓我們更進(jìn)一步來定制Grails。

創(chuàng)建自定義控制器

  我現(xiàn)在將把新功能和頁面添加到Web應(yīng)用程序,同時(shí)重用已經(jīng)存在的域類。shirt/list 和 trouser/list 會(huì)分別顯示襯衫和褲子的清單,現(xiàn)在讓我們添加一個(gè)新的顯示,來同時(shí)顯示襯衫和褲子的清單。要?jiǎng)?chuàng)建一個(gè)新的顯示,您需要一個(gè)新的控制器和視圖。

  使用 generate-controller 和 generate-views 命令,可以輕松實(shí)現(xiàn)使用域類自動(dòng)生成視圖和控制器。然而,在此案例中我希望創(chuàng)建一個(gè)與域類不直接關(guān)聯(lián)的控制器。因此我將使用grails create-controller命令。當(dāng)被提示輸入控制器名稱時(shí),聲明Display。Grails將在grails-app/controllers/ 目錄創(chuàng)建一個(gè)名為DisplayController.groovy 的控制器,在grails-tests 目錄創(chuàng)建一個(gè)測(cè)試套件。如清單5所示編輯控制器。

  清單5:DisplayController.groovy

class DisplayController {
def index = {redirect(action:list,params:params)}
def list = {
params['max'] = 10
return [ shirtList: Shirt.list( params ),
trouserList: Trouser.list( params )]
}
}

  index 閉包將請(qǐng)求重定向到清單。在list 閉包中我將最大參數(shù)設(shè)為10,然后使用動(dòng)態(tài)方法Shirt.list 和 Trouser.list。然后返回Groovy Map,它有兩個(gè)清單——襯衫清單和褲子清單。

  作為Java開發(fā)人員,當(dāng)看到Shirt.list()時(shí)會(huì)自然認(rèn)為是在Shirt域類中的list 方法。然而,如果打開Shirt.groovy,會(huì)發(fā)現(xiàn)并沒有此方法。對(duì)于Java開發(fā)人員來說,不了解Groovy的特性就使用Grails不僅是令人困惑的,而且是死胡同。動(dòng)態(tài)方法是Grails的特殊特性,它是構(gòu)建于Groovy語言的一個(gè)非常特殊的特性元對(duì)象協(xié)議 (MOP)之上的。如此證明可以使用動(dòng)態(tài)方法查詢域類。因此,在控制器中,您將注意到在域類上調(diào)用的方法似乎在域類中不存在。您可以在這里閱讀關(guān)于使用動(dòng)態(tài)方法查詢的更多信息。可以在這里找到對(duì)Grails控制器和域類中可用的動(dòng)態(tài)方法的參考資料。

  既然控制器能夠處理請(qǐng)求、獲取清單并轉(zhuǎn)發(fā)到視圖,我需要?jiǎng)?chuàng)建相應(yīng)視圖。

創(chuàng)建自定義視圖

  當(dāng)創(chuàng)建控制器時(shí),Grails還在grails-app\views 目錄創(chuàng)建了一個(gè)新的顯示目錄,并將以下映射添加到web.xml 文件中。

<servlet-mapping>
<servlet-name>grails</servlet-name>
<url-pattern>/display/*</url-pattern>
</servlet-mapping>

  目前Grails有一個(gè)generate-views 命令,此命令能夠生成基于域類的視圖,然而沒有能夠自動(dòng)生成視圖的create-view 命令。請(qǐng)看圖3中的例子。

Groovy和Grails簡(jiǎn)介圖-3

  圖3:一個(gè)顯示Trousers的默認(rèn)視圖

  因?yàn)槲蚁M麆?chuàng)建一個(gè)獨(dú)立于域類的視圖,所以讓我們手動(dòng)創(chuàng)建視圖文件。在目錄grails-app\views\display\中,創(chuàng)建一個(gè)名為 list.gsp的文件,如清單6所示。

  清單6:list.gsp

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Display Shirt And Trouser List</title>
<link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}"></link>
</head>
<body>
<div class="nav">
<span class="menuButton"><a href="${createLinkTo(dir:'')}">Home</a></span>
</div>
<div class="body">
<h1>Shirt List</h1>
<table>
<tr>
<th>Id</th><th>Cabinet</th> <th>Color</th><th>Name</th>
</tr>
<g:each in="${shirtList}">
<tr>
<td>${it.id}</td> <td>${it.cabinet.name}</td>
<td>${it.color}</td> <td>${it.name}</td>
</tr>
</g:each>
</table>
<h1>Trouser List</h1>
<table>
<tr>
<th>Id</th> <th>Cabinet</th>
<th>Color</th> <th>Name</th>
</tr>
<g:each in="${trouserList}">
<tr>
<td>${it.id}</td> <td>${it.cabinet.name}</td>
<td>${it.color}</td> <td>${it.name}</td>
</tr>
</g:each>
</table>
</div>
</body>
</html>

  與我之前使用的方式類似,您現(xiàn)在也可以使用run-app 命令運(yùn)行應(yīng)用程序,或者創(chuàng)建一個(gè)war文件并將其部署到Tomcat。您應(yīng)該在http://localhost:8080/ClothesMgt/display/下看到新的視圖,如圖4所示。

Groovy和Grails簡(jiǎn)介圖-4

  圖4:新創(chuàng)建的列出襯衫和褲子清單的視圖

  現(xiàn)在讓我們快速討論一下Grails服務(wù)。

服務(wù)

  如果您想知道如何分開業(yè)務(wù)邏輯以及放置業(yè)務(wù)邏輯的位置,答案在Grails 服務(wù)中。服務(wù)以SomeNameService.groovy 格式命名,且被置于 /grails-app/services/目錄。服務(wù)可利用依賴注入特性,您能夠輕松地從控制器內(nèi)部調(diào)用這些服務(wù)。

  讓我們來看一個(gè)使用服務(wù)的例子。首先,使用create-service 命令創(chuàng)建新服務(wù)。運(yùn)行此命令并命名服務(wù)Order。Grails將創(chuàng)建兩個(gè)文件——grails-app/services/OrderService.groovy 和 grails-tests/OrderTests.groovy。

  現(xiàn)在編輯OrderService.groovy,如清單7所示。當(dāng)引入新的orderGoods() 方法時(shí)會(huì)自動(dòng)生成serviceMethod() 。

  清單7:OrderService.groovy

class OrderService {
boolean transactional = true
def serviceMethod() {
// TODO
}
def orderGoods() {
return "Order Placed - New shirts and trousers \
will be sent shortly."
}
}

  現(xiàn)在編輯DisplayController,如清單8所示。引入使用OrderService的重排閉包。請(qǐng)注意服務(wù)將由Groovy注入。

  清單8:DisplayController.groovy

class DisplayController {
OrderService orderService
def index = {redirect(action:list,params:params)}
def list = {
params['max'] = 10
return [ shirtList: Shirt.list( params )
, trouserList: Trouser.list( params )]
}
def reorder = {
render(orderService.orderGoods())
}
}

  現(xiàn)在當(dāng)您訪問URL http://localhost:8080/ClothesMgt/display/reorder時(shí),重排閉包將調(diào)用 OrderService,響應(yīng)會(huì)被發(fā)回到瀏覽器。您能夠以類似方式將全部業(yè)務(wù)邏輯移入服務(wù),然后使用Grails的注入功能非常輕松地使用它們。

動(dòng)態(tài)方法和屬性

  正如之前提到的,域類沒有能夠從數(shù)據(jù)庫獲取數(shù)據(jù)或更新/刪除現(xiàn)有數(shù)據(jù)的任何方法,例如find()、 findAll() 或 save() 。在控制器中您也沒有編寫諸如 redirect() 或 render() 之類的方法。但是域類和控制器有它們的計(jì)劃目的,且允許所有要求的操作。原因是Grails中動(dòng)態(tài)方法和屬性的存在。動(dòng)態(tài)方法被動(dòng)態(tài)添加到類,就好像功能是在程序中編譯的一樣。

  這些是可用的方法和屬性,無需編寫。這些動(dòng)態(tài)方法涵蓋了大多數(shù)Web應(yīng)用程序開發(fā)中會(huì)碰到的常見情況。對(duì)于域類來說,存在諸如find()、findAll()、list()、executeQuery()、save()和 delete()之類的動(dòng)態(tài)方法。控制器具有諸如session、request和response之類的動(dòng)態(tài)屬性,以及諸如chain()、render()和 redirect()之類的方法。要真正利用Grails的強(qiáng)大功能,您需要了解所有這些動(dòng)態(tài)方法和屬性的功能。

順便介紹一下:自動(dòng)重載和@Property

  Grails的一個(gè)重要特性是能夠在開發(fā)過程中進(jìn)行了更改時(shí)自動(dòng)重載文件。因此只需編輯和保存gsp文件,就會(huì)自動(dòng)重載新文件。然而這里創(chuàng)建的類似OrderService 的事務(wù)服務(wù)不會(huì)被重載。您會(huì)在服務(wù)器控制臺(tái)看到以下消息"[groovy] Cannot reload class [class OrderService] reloading of transactional service classes is not currently possible. Set class to non-transactional first. "

  Grails的自動(dòng)重載功能會(huì)為您節(jié)省許多時(shí)間,您就無需浪費(fèi)時(shí)間來重啟服務(wù)器了。我碰到過一些Grails不能自動(dòng)重載的案例,例如將一個(gè)jsp文件重命名到gsp。然而,Grails的這項(xiàng)功能有望在未來版本中得到進(jìn)一步改進(jìn)。

  在Groovy JSR 06 的之前版本中,您必須使用@Property 來定義Groovy中的新屬性。因此您會(huì)在線看到許多使用@Property的舊的Groovy例子。然而請(qǐng)注意,@Property已經(jīng)從Groovy JSR 06中移除,在Grails 0.2和之后的版本中也不會(huì)再需要它。請(qǐng)參閱@Property 建議來獲得更多細(xì)節(jié)。

結(jié)束語

  在本文中,我介紹了Grails框架的基本特性,并使用Grails創(chuàng)建了一個(gè)應(yīng)用程序。Groovy和Grails最大的好處是一切都運(yùn)行在優(yōu)秀的舊Java和Java EE上——因此您能夠使用Groovy和Grails的RAD特性快速開發(fā)應(yīng)用程序,然后將應(yīng)用程序部署到可靠的Java EE服務(wù)器上。考慮到關(guān)于Ruby和Rails的宣傳噪音,顯然需要一個(gè)Java備選方案。Groovy和Grails看起來非常適合這個(gè)角色。

下載

  下載本文中的代碼:

參考資料



cAng^Er 2008-02-21 12:40 發(fā)表評(píng)論
]]>
刪除.svn文件夾的JS腳本http://www.aygfsteel.com/xiaosao/archive/2008/02/19/180700.htmlcAng^ErcAng^ErTue, 19 Feb 2008 07:59:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2008/02/19/180700.htmlhttp://www.aygfsteel.com/xiaosao/comments/180700.htmlhttp://www.aygfsteel.com/xiaosao/archive/2008/02/19/180700.html#Feedback2http://www.aygfsteel.com/xiaosao/comments/commentRss/180700.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/180700.html今天在網(wǎng)上游蕩發(fā)現(xiàn)了個(gè)好東西~保存下來!一直都苦于無法一下將舊項(xiàng)目下面的.SVN文件夾利落刪除~今天恰巧發(fā)現(xiàn)了一個(gè)方法,在此很是感謝~~
  原文如下:http://www.ljnid.cn/?id=261
   寫了個(gè)JS腳本,可以刪除指定文件夾下面的所有.SVN文件夾
   在windows server 2003下測(cè)試通過,不保證XP可以運(yùn)行
   使用方法:把下面的代碼保存為xxx.js
  在控制臺(tái)用:cscript.exe xxx.js X:\xxx\xx
  其中X:\xxx\xx是你指定的路徑


if(WScript.Arguments.length==0)
WScript.quit();

var fso = new ActiveXObject("Scripting.FileSystemObject");
var fc,folder,folderList=[];
var rootFolder = fso.getFolder(WScript.Arguments(0));

folderList.push(rootFolder);
while(folderList.length>0){
folder = folderList.pop();
fc = new Enumerator(folder.SubFolders);
while(!fc.atEnd())
{
if(fc.item().name =='.svn')
fso.deleteFolder(fc.item().path,true);
else
folderList.push(fc.item());

fc.moveNext();
}
}


cAng^Er 2008-02-19 15:59 發(fā)表評(píng)論
]]>
<又是轉(zhuǎn)來的> 面試java高級(jí)工程師、項(xiàng)目經(jīng)理等的常見問題http://www.aygfsteel.com/xiaosao/archive/2007/11/09/159386.htmlcAng^ErcAng^ErFri, 09 Nov 2007 08:02:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2007/11/09/159386.htmlhttp://www.aygfsteel.com/xiaosao/comments/159386.htmlhttp://www.aygfsteel.com/xiaosao/archive/2007/11/09/159386.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/159386.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/159386.htmlhttp://paulandjoy.javaeye.com/blog/126315
1、 類、對(duì)象的概念:
1) 類:具有共同屬性和行為的對(duì)象的抽象。類是創(chuàng)建對(duì)象的模板。
2) 對(duì)象:現(xiàn)實(shí)世界中的實(shí)體。在計(jì)算機(jī)中,是指可標(biāo)識(shí)的存儲(chǔ)區(qū)域。
3) 類是對(duì)象的抽象、對(duì)象是類的實(shí)例。
2、 抽象:是從特定的實(shí)例中抽取共同性質(zhì)形成一般化概念的過程。
3、 接口與抽象類:
1)接口和抽象類都用于抽象,接口是抽象類的抽象。
2)接口中只有方法聲明,沒有實(shí)現(xiàn)(無方法體);在接口中聲明的方法具有public和abstract屬性,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口(即多繼承),接口以‘,’分隔;接口中的方法必須全部實(shí)現(xiàn)。
3)抽象類可以有部分方法實(shí)現(xiàn),抽象類必須通過繼承才能使用。
4、內(nèi)部類(Inner Class):
1)內(nèi)部類是嵌套在另一個(gè)類中的類。
2)內(nèi)部類用于名稱隱藏和程序代碼的組織,另外內(nèi)部類擁有直接訪問其外部類所有成員(包括private的)的權(quán)限(無需任何關(guān)鍵字修飾)。
3)內(nèi)部類不可以在其他類或main方法里實(shí)例化,必須使用如下方法(非靜態(tài)內(nèi)部類)
外部類.內(nèi)部類 對(duì)象名=new 外部類().new 內(nèi)部類();
靜態(tài)內(nèi)部類調(diào)用方式:
外部類.內(nèi)部類 對(duì)象名=new 外部類.內(nèi)部類();
4)非靜態(tài)內(nèi)部類不可以聲明靜態(tài)成員;靜態(tài)內(nèi)部類的非靜態(tài)成員可以訪問其外部類的靜態(tài)成員,聲明為靜態(tài)的成員不可以訪問外部的非靜態(tài)成員。
5、訪問修飾符限制:
Private protected friendly(default) public
同類 Y Y Y Y
同包不同類 N Y Y Y
同包子類 N Y Y Y
不同包不同類 N N N Y
不同包子類 N Y N Y
6、Static關(guān)鍵字的使用:
1)類成員,直接使用 類名.成員 調(diào)用。
2)靜態(tài)方法只能訪問靜態(tài)成員。
3)靜態(tài)方法不能使用this、super關(guān)鍵字。
4)靜態(tài)方法不能被非靜態(tài)方法重寫或重載。
7、final關(guān)鍵字:
1)被final修飾的變量為常量不能改變。
2)被final修飾的方法不可以重寫。
3)被final修飾的類不能被繼承。
8、abstract關(guān)鍵字:
1)被abstract修飾的類不能實(shí)例化。
2)被abstract修飾的方法只能在子類中實(shí)現(xiàn)。
9、native關(guān)鍵字:非Java語言的編寫,例如JNI技術(shù)。
10、synchronized關(guān)鍵字:多線程的同步訪問控制。
11、分類列舉服務(wù)器和組件技術(shù):
1)服務(wù)器端技術(shù):Jsp、Servlet;
2)組件技術(shù):JavaBean、EJB。
12、Http與Https:Https即多了安全的Http,s(Security Socket Layer)指加密套接字協(xié)議層(簡(jiǎn)寫SSL)。
13、OSI(Open System Interconnection)網(wǎng)絡(luò)抽象模型:
1)由國際標(biāo)準(zhǔn)化組織(ISO)提出。
2)將互聯(lián)網(wǎng)分為七層,從下至上分別為:物理層(physical)、數(shù)據(jù)鏈路層(data link)、網(wǎng)絡(luò)層(network)、傳送層(transport)、會(huì)話層(session)、表示層(presentation)、應(yīng)用層(application)。底層通過提供接口支持上層功能。各層詳解:
物理層:LAN/ATM,為硬件層。
數(shù)據(jù)鏈路層:LAN/ATM
網(wǎng)絡(luò)層:IP協(xié)議,IOS
傳輸層:TCP/UDP協(xié)議,支持Java Socket。
會(huì)話層:
表示層:HTML、XML
應(yīng)用層:HTTP協(xié)議,使用Java Servlet/JSP
<第八層(Web服務(wù)層):SOAP/UDDI>
14、J2EE的容器與服務(wù)器:
容器負(fù)責(zé)EJB組件中生命周期的控制;
服務(wù)器包含在容器外,提供系統(tǒng)級(jí)操作底層服務(wù),包括事務(wù)、事件、多線程……。
15、繼承限制:
父類對(duì)象不可以賦給子類對(duì)象,因?yàn)樽宇惪赡芫哂懈嗟某蓡T,反之可以。
16、邏輯操作:c=(a>b)?a:b;等同于下式
if(a>b) c=a; else c=b;
17、列舉常見集合框架類型:
1)List、Set、Map。由這三個(gè)接口實(shí)現(xiàn)出ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等常用集合框架。
2)Vector屬于重量級(jí)組件不推薦使用。
3)Map類型維護(hù)鍵/值對(duì),Hashtable與HashMap相近但效率略低于HashMap、高于TreeMap,TreeMap優(yōu)點(diǎn)是可以排序。
4)Set類型可裝入唯一值,HashSet效率高于TreeSet但TreeSet可以維護(hù)內(nèi)部元素的排序狀態(tài)。
5)List類型可按某種特定順序維護(hù)元素。ArrayList允許快速隨機(jī)訪問,但如果添加或刪除位于中間的元素時(shí)效率很低;LikedList提供最佳循序訪問及快速的中間位置添加刪除元素,并有addFirst、addLast、getFirst、getLast、removeFirst、removeLast方法。
18、面向?qū)ο蟮奶卣鳎?
1)繼承:通過子類可以實(shí)現(xiàn)繼承,子類繼承父類的所有狀態(tài)和行為,同時(shí)添加自身的狀態(tài)和行為。
2)封裝:將代碼及處理數(shù)據(jù)綁定在一起的一種編程機(jī)制,該機(jī)制保證程序和數(shù)據(jù)不受外部干擾。
3)多態(tài):包括重載和重寫。重載為編譯時(shí)多態(tài),重寫是運(yùn)行時(shí)多態(tài)。重載必須是同類中名稱相同參數(shù)不同(包括個(gè)數(shù)不同和類型不同),但返回類型不同不構(gòu)成重載;重寫發(fā)生于子類對(duì)父類的覆蓋,子類繼承父類方法名相同、參數(shù)列表相同、返回類型相同才構(gòu)成重寫。
19、Java命名規(guī)范:必須以英文字母、下劃線(’_’)或’$’開始,其余可以有數(shù)字但不允許 包含空格,且組合后的名稱不能是Java關(guān)鍵字或保留字。
匈牙利命名法:以m開始為類成員變量,以g開始為全局變量,以v開始為本地局部變量,常量命名一般不以下劃線、美元符開始。
駝峰命名:一般稱由多個(gè)單詞或縮寫組成的變量名,并且該變量名每個(gè)單詞首字母均為大寫(一般類名全部首字母大寫,方法或?qū)傩悦谝粋€(gè)字母小寫)的稱為駝峰命名。
20、Java語言共包含47個(gè)關(guān)鍵字。
21、設(shè)計(jì)模式:
一個(gè)設(shè)計(jì)模式描述了一個(gè)被證實(shí)可行的方案。這些方案非常普遍,是具有完整定義的最常用的模式。一般模式有4個(gè)基本要素:模式名稱(pattern name)、問題(problem)、解決方案(solution)、效果(consequences)。
常見23種模式概述:
1) 抽象工廠模式(Abstract Factory):提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們具體的類。
2) 適配器模式(Adapter):將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。適配器模式使得原本由于接口不兼容而不能一起工作的類可以一起工作。
3) 橋梁模式(Bridge):將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。
4) 建造模式(Builder):將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
5) 責(zé)任鏈模式(Chain of Responsibility):為解除請(qǐng)求的發(fā)送者和接收者之間耦合,而使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它。
6) 命令模式(Command):將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可取消的操作。
7) 合成模式(Composite):將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。它使得客戶對(duì)單個(gè)對(duì)象和復(fù)合對(duì)象的使用具有一致性。
8) 裝飾模式(Decorator):動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就擴(kuò)展功能而言,它能生成子類的方式更為靈活。
9) 門面模式(Facade):為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,門面模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。
10) 工廠方法(Factory Method):定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定將哪一個(gè)類實(shí)例化。Factory Method 使一個(gè)類的實(shí)例化延遲到其子類。
11) 享元模式(Flyweight):運(yùn)用共享技術(shù)以有效地支持大量細(xì)粒度的對(duì)象。
12) 解釋器模式(Interpreter):給定一個(gè)語言,定義它的語法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示解釋語言中的句子。
13) 迭代子模式(Iterator):提供一種方法順序訪問一個(gè)聚合對(duì)象中的各個(gè)元素,而又不需暴露該對(duì)象的內(nèi)部表示。
14) 調(diào)停者模式(Mediator):用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式的內(nèi)部表示。
15) 備忘錄模式(Memento):在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可將該對(duì)象恢復(fù)到保存的狀態(tài)。
16) 觀察者模式(Observer):定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,以便當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。
17) 原始模型模式(Prototype):用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過拷貝這個(gè)原型創(chuàng)建新的對(duì)象。
18) 代理模式(Proxy):為其他對(duì)象提供一個(gè)代理以控制對(duì)這個(gè)對(duì)象的訪問。
19) 單例模式(Singleton):保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
20) 狀態(tài)模式(State):允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為。對(duì)象看起來似乎修改了它所屬的類。
21) 策略模式(Strategy):定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可相互替換。本模式使得算法的變化可獨(dú)立于使用它的客戶。
22) 模板模式(Template Method):定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
23) 訪問者模式(Visitor):表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。該模式可以實(shí)現(xiàn)在不改變各元素的類的前提下定義作用于這些元素的新操作。
1、 你認(rèn)為一個(gè)項(xiàng)目如何進(jìn)行才正確?(比如:盡一切可能快的完成任務(wù)或完全按照類似CMM來操作)
根據(jù)林銳博士的觀點(diǎn):企業(yè)的根本目標(biāo)是合法地賺取盡可能多的利潤,使企業(yè)利益最大化。企業(yè)所有的特定目標(biāo)和行動(dòng)都是圍繞上述根本目標(biāo)開展的,任何背離根本目標(biāo)的行動(dòng)都將對(duì)企業(yè)造成傷害,應(yīng)當(dāng)杜絕。
基于此任何人都不要強(qiáng)調(diào)我將嚴(yán)格遵守XX模式,帶領(lǐng)團(tuán)隊(duì)開發(fā)出具有XX等級(jí)的產(chǎn)品,企業(yè)需要的是能夠帶領(lǐng)團(tuán)隊(duì)按時(shí)、合格的開發(fā)出產(chǎn)品的Manager。
2、 你經(jīng)常看或仔細(xì)研讀過的書有哪些?
不用回答你看過的課本,枚舉幾個(gè)經(jīng)典的當(dāng)然前提是必須真的看過至少瀏覽過主題和目錄。比如《Java編程思想》、《Java模式》、《人月神話》等,由于將來要做的是team中的替補(bǔ)leader或真正的leader所以你必須說出軟工的東西。
3、 你認(rèn)為你應(yīng)聘我們公司的項(xiàng)目經(jīng)理,你自身的優(yōu)勢(shì)在哪?
1)融洽,沒有領(lǐng)導(dǎo)希望你帶領(lǐng)團(tuán)隊(duì)每天打嘴仗然后他還要去開屁股(Sorry,這似乎不很文明),你必須說明你能在以往團(tuán)隊(duì)中與其他人和諧相處。
2)技術(shù),千萬不要謙虛,對(duì)方要的就是技術(shù)過硬、能力出眾的人才,你只需要說明你成功解決過什么難題并且你對(duì)J2EE、XX中間件、XX系統(tǒng)有多么的熟悉。
4、 如果給你一個(gè)Team,公司決定讓你的Team開發(fā)A產(chǎn)品,OK這恰好是你的強(qiáng)項(xiàng),你們很快開發(fā)出來了,但很沮喪的結(jié)果是它(你們的產(chǎn)品)沒有銷路;經(jīng)過討論公司又決定讓你的Team開發(fā)B產(chǎn)品,OK這恰好又是你的強(qiáng)項(xiàng),你們很快開發(fā)出來了,但很沮喪的結(jié)果是它(你們的產(chǎn)品)又沒有銷路。請(qǐng)問你怎么面對(duì)這個(gè)問題,你是否覺得決策層很無能甚至要推翻他或者去一個(gè)更有前途的公司?
不要以為這個(gè)故事很單純,這應(yīng)該是人力在考核你。你一定要告訴她(人力多半是女的),我個(gè)人對(duì)于失敗的項(xiàng)目肯定會(huì)難過(是的,我想了很久才想出“難過”這個(gè)詞,它很中性),不過我認(rèn)為這恰恰認(rèn)證了公司在革新和新技術(shù)探索方面的魄力(自己想怎么說,如果天下人都說這句那才是悲劇呢),我肯定會(huì)以個(gè)人的名義向領(lǐng)導(dǎo)層提出我自己的建議和看法當(dāng)然它未必正確,我不會(huì)離開公司,因?yàn)橛悬c(diǎn)小挫折未嘗不是好事。(你應(yīng)該在這個(gè)問題上好好想想,盡量發(fā)揮到10分鐘)
5、 你認(rèn)為項(xiàng)目中最重要的是哪些過程?
分析、設(shè)計(jì)階段(也可以加上測(cè)試,但千萬別說編碼或開發(fā)階段),根據(jù)《人月神話》的觀點(diǎn):1/3 計(jì)劃;1/6 編碼;1/4 構(gòu)件測(cè)試和早期系統(tǒng)測(cè)試;1/4 系統(tǒng)測(cè)試,所有的構(gòu)件已完成
但根據(jù)國內(nèi)目前的狀況一般公司不會(huì)有很多的分析與設(shè)計(jì)時(shí)間(這取決于公司規(guī)模和時(shí)間成本),這樣在一個(gè)工期很緊張的項(xiàng)目中我們應(yīng)該盡量分配出進(jìn)度優(yōu)先級(jí)來,首先拿出客戶最希望看到的和最能證明成果的東西來,其他的留待2期甚至3期去作,你可以告訴客戶需要進(jìn)一步調(diào)試(專業(yè)人員的欺騙手段,實(shí)際上就是在進(jìn)行后續(xù)的開發(fā))。
6、 如果給你一個(gè)4-6個(gè)人的Team,那么你怎么分配他們、管理他們?
管理能力和經(jīng)驗(yàn)的綜合題,可能沒有人有相同的觀點(diǎn),那你可以按照某些思路來側(cè)面解答:我會(huì)挑選一個(gè)技術(shù)過硬的人作為我的替補(bǔ)和項(xiàng)目的輕騎兵,是的團(tuán)隊(duì)中必須有機(jī)動(dòng)人員,否則你的項(xiàng)目十有八九會(huì)夭折。其他的人會(huì)被平均的分配任務(wù)。
我們會(huì)在每周進(jìn)行全面的任務(wù)分配,每個(gè)人獲取一周的大概工作,然后每天的工作由他自己完成并匯報(bào)。(很好,如果答出這些就差不多了,多說可能會(huì)出現(xiàn)漏洞)
7、 簡(jiǎn)述常用的軟件開發(fā)文檔。
1) 可行性研究報(bào)告(某些公司或模型沒有)
2) 項(xiàng)目開發(fā)計(jì)劃
3) 軟件需求說明書(必有)
4) 數(shù)據(jù)要求說明書
5) 概要設(shè)計(jì)說明書(必有)
6) 詳細(xì)設(shè)計(jì)說明書(必有)
7) 數(shù)據(jù)庫設(shè)計(jì)說明書(必有)
8) 用戶手冊(cè)(一般會(huì)有)
9) 操作手冊(cè)(必有)
10) 模塊開發(fā)卷宗
11) 測(cè)試計(jì)劃(必有)
12) 測(cè)試分析報(bào)告
13) 開發(fā)進(jìn)度月報(bào)
14) 項(xiàng)目開發(fā)總結(jié)報(bào)告
8、 簡(jiǎn)述類的關(guān)系。
1) 當(dāng)一個(gè)類是“一種”另一個(gè)類時(shí):is-a關(guān)系
2) 當(dāng)兩個(gè)類之間有關(guān)聯(lián)時(shí):
一個(gè)類“包含”另一個(gè)類:has-a關(guān)系
一個(gè)類“使用”另一個(gè)類
還可以細(xì)分有聚合和組合(UML寶典)或聚集和組成(包括國內(nèi)某些知名學(xué)術(shù)團(tuán)體都這么說)。
聚集(aggregation)表示整體與各部分之間的關(guān)系。例如汽車與輪胎,沒有了汽車輪胎依然是一個(gè)整體。(用空心菱形表示)
組成是一種整體和部分所屬更強(qiáng)的聚集關(guān)系,每個(gè)部分只能屬于一個(gè)整體,沒有整體部分也就沒有存在的價(jià)值。比如桌子和桌腿,沒有桌子也就沒有桌腿的價(jià)值了。(用實(shí)心菱形表示)



cAng^Er 2007-11-09 16:02 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>JavaScript substr() 和 substring() 方法的區(qū)別 http://www.aygfsteel.com/xiaosao/archive/2007/10/18/153968.htmlcAng^ErcAng^ErThu, 18 Oct 2007 09:55:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2007/10/18/153968.htmlhttp://www.aygfsteel.com/xiaosao/comments/153968.htmlhttp://www.aygfsteel.com/xiaosao/archive/2007/10/18/153968.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/153968.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/153968.html又是轉(zhuǎn)過來的文章,最近在學(xué)JavaScripts,用到了substr()和substring(),上網(wǎng)找了下,看到了這個(gè)
 轉(zhuǎn)載到這里,以便瀏覽

  原文地址:http://www.cnblogs.com/tishifu/archive/2007/08/03/841429.html

substr 方法
返回一個(gè)從指定位置開始的指定長(zhǎng)度的子字符串。

stringvar.substr(start [, length ])

參數(shù)
stringvar

必選項(xiàng)。要提取子字符串的字符串文字或 String 對(duì)象。

start

必選項(xiàng)。所需的子字符串的起始位置。字符串中的第一個(gè)字符的索引為 0。

length

可選項(xiàng)。在返回的子字符串中應(yīng)包括的字符個(gè)數(shù)。

說明
如果 length 為 0 或負(fù)數(shù),將返回一個(gè)空字符串。如果沒有指定該參數(shù),則子字符串將延續(xù)到 stringvar 的最后。

示例
下面的示例演示了substr 方法的用法。

function SubstrDemo(){
   var s, ss;                // 聲明變量。
   var s = "The rain in Spain falls mainly in the plain.";
   ss = s.substr(12, 5);  // 獲取子字符串。
   return(ss);               // 返回 "Spain"。
}


substring 方法
返回位于 String 對(duì)象中指定位置的子字符串。

strVariable.substring(start, end)
"String Literal".substring(start, end)

參數(shù)
start

指明子字符串的起始位置,該索引從 0 開始起算。

end

指明子字符串的結(jié)束位置,該索引從 0 開始起算。

說明
substring 方法將返回一個(gè)包含從 start 到最后(不包含 end )的子字符串的字符串。

substring 方法使用 start 和 end 兩者中的較小值作為子字符串的起始點(diǎn)。例如, strvar.substring(0, 3) 和 strvar.substring(3, 0) 將返回相同的子字符串。

如果 start 或 end 為 NaN 或者負(fù)數(shù),那么將其替換為0。

子字符串的長(zhǎng)度等于 start 和 end 之差的絕對(duì)值。例如,在 strvar.substring(0, 3) 和 strvar.substring(3, 0) 返回的子字符串的的長(zhǎng)度是 3。

示例
下面的示例演示了 substring 方法的用法。

function SubstringDemo(){
   var ss;                         // 聲明變量。
   var s = "The rain in Spain falls mainly in the plain..";
   ss = s.substring(12, 17);   // 取子字符串。
   return(ss);                     // 返回子字符串。
}



cAng^Er 2007-10-18 17:55 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>實(shí)戰(zhàn)SVN For Apache2(二)http://www.aygfsteel.com/xiaosao/archive/2007/10/17/153667.htmlcAng^ErcAng^ErWed, 17 Oct 2007 11:47:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2007/10/17/153667.htmlhttp://www.aygfsteel.com/xiaosao/comments/153667.htmlhttp://www.aygfsteel.com/xiaosao/archive/2007/10/17/153667.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/153667.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/153667.html 在上一篇文章中,我們已經(jīng)實(shí)現(xiàn)了對(duì)SVN和Apache的安裝,并將它們集成在一起工作。這一篇?jiǎng)t主要介紹如何對(duì)SVN For Apache進(jìn)行一些配置。
  1.    在Apache下為SVN建立多個(gè)庫。上篇中雖然也建立了一個(gè)SVN的庫在Apache下,但是我們不可能一個(gè)SVN服務(wù)器上只有一個(gè)項(xiàng)目,或者所有項(xiàng)目共用一個(gè)SVN庫進(jìn)行開發(fā),在Apache上為SVN建立多個(gè)庫可以通過建立多個(gè)虛擬目錄的方式實(shí)現(xiàn)。下面我們就來講講具體的步驟(注意,此篇中的配置和上篇中的配置方式有很大區(qū)別)

    1. 到F盤建立我們的SVN代碼存放位置目錄:SubversionFiles,并在其中建立一個(gè)conf目錄,將會(huì)把對(duì)Apache對(duì)SVN的配置文件都放在這里
    2. 再在F:\SubversionFiles下目錄Test1和Test2,并將它們變成SVN庫(用svnadmin create命令或者用TortoiseSVN來創(chuàng)建都可以)
    3. 在httpd.conf的最后添加如下代碼

      #
      # SVN 項(xiàng)目配置文件,格式:Include 配置文件名
      #為每個(gè)虛擬目錄設(shè)置一個(gè)配置文件,用Include命令加載

      #
      Include F:/SubversionFiles/conf/*.project

      即把F:/SubversionFiles/conf/目錄下的所有*.project文件都包到httpd.conf中來


    4. 在F:/SubversionFiles/conf/創(chuàng)建Test1.project和Test2.project文件,Test1內(nèi)容如下,Test2可以做相應(yīng)的修改

      #SVN項(xiàng)目名

           DAV svn

          #SVN項(xiàng)目的路徑
           SVNPath F:\SubversionFiles\Test1

          #SVN項(xiàng)目的路徑權(quán)限授權(quán)文件存放路徑
          AuthzSVNAccessFile F:\SubversionFiles\conf\Test1.access

      #對(duì)于所有用戶都需要身份驗(yàn)證
          Satisfy Any
           Require valid-user

      #驗(yàn)證方式
          AuthType Basic

          #項(xiàng)目的名稱
           AuthName "My Test1
      "

          #用戶信息
           AuthUserFile  F:\SubversionFiles\conf\user




      以上配置含義是在Apache下建立了一個(gè)叫作Test1的SVN虛擬目錄,指向F:\SubversionFiles\Test1,授權(quán)配置文件是F:\SubversionFiles\conf\Test1.access,用戶信息和密碼文件是F:\SubversionFiles\conf\user


    5.  通過以上配置,我們就在Apache上建立了Test1和Test2兩個(gè)虛擬目錄,也就是兩個(gè)獨(dú)立的SVN庫,我們還需要兩個(gè)文件訪問權(quán)限配置的.access和包含登錄用戶的user。 在F:\SubversionFiles\conf目錄中創(chuàng)建用戶列表文件user,方法在上篇中已經(jīng)說過,也就是htpasswd命令,我們需要?jiǎng)?chuàng)建Xrinehart, X-Killer, Guest三個(gè)用戶。

    6. 接下來,我們?yōu)門est1庫創(chuàng)建它的訪問權(quán)限文件F:\SubversionFiles\conf\Test1.access。在上篇文章中我們是采用對(duì)每個(gè)用戶分別賦予對(duì)應(yīng)權(quán)限的方式,如果用戶比較多,管理起來就會(huì)比較麻煩,這時(shí)我們需要用用戶組來對(duì)用戶進(jìn)行管理。下面我們就來嘗試用用戶組配置訪問權(quán)限。Test1.access文件內(nèi)容如下:


      [groups]
      AdminGroup = Xrinehart
      GuestGroup = guest

      [/]
      @AdminGroup = rw
      @GuestGroup = r

      X-Killer = rw


              在上面的配置中,通過[groups]節(jié)定義了兩個(gè)用戶組:AdminGroup和GuestGroup,并將Xrinehart用戶歸入AdminGroup用戶組,guest用戶歸入GuestGroup。再在下面的[/]定義了他們對(duì)Test1庫的根目錄的操作權(quán)限:AdminGroup組有讀寫權(quán)限,GuestGroup組只有讀權(quán)限,X-Killer用戶擁有讀寫權(quán)限。這里需要注意的是定義權(quán)限的時(shí)候,用戶組需要在前面加@符號(hào)來標(biāo)示。

    7. 為了測(cè)試效果,我們可以將Test2.access文件寫為:

      [groups]
      AdminGroup = Xrinehart, X-Killer
      GuestGroup = guest

      [/]
      @AdminGroup = r
      @GuestGroup = rw


    8. 保存好上面的所有配置文件之后,重新啟動(dòng)Apache服務(wù)器。此時(shí)我們就可以在IE里面通過http://localhost:8080/Test1http://localhost:8080/Test2 來訪問Test1和Test2庫了,你可以測(cè)試一下,用戶權(quán)限是否符合下面這個(gè)列表所示?做到這里,SVN在Apache上建立多個(gè)庫的配置也就算完成了。


                                                       Test1                                            Test2

      Xrinehart                                    rw                                                  r
      X-Killer                                       rw                                                  r
      guest                                          r                                                    rw


cAng^Er 2007-10-17 19:47 發(fā)表評(píng)論
]]>
<轉(zhuǎn)>實(shí)戰(zhàn)SVN For Apache2(一) http://www.aygfsteel.com/xiaosao/archive/2007/10/17/153664.htmlcAng^ErcAng^ErWed, 17 Oct 2007 11:39:00 GMThttp://www.aygfsteel.com/xiaosao/archive/2007/10/17/153664.htmlhttp://www.aygfsteel.com/xiaosao/comments/153664.htmlhttp://www.aygfsteel.com/xiaosao/archive/2007/10/17/153664.html#Feedback0http://www.aygfsteel.com/xiaosao/comments/commentRss/153664.htmlhttp://www.aygfsteel.com/xiaosao/services/trackbacks/153664.html原文地址:http://www.cnblogs.com/Xrinehart/archive/2005/10/27/262759.aspx
  SVN最常見的配置模式便是與Apache集成,這樣SVN可以采用WebDev協(xié)議方式提供服務(wù)。主要的好處有:通過Apache以HTTP方式穿透防火墻,便于在互聯(lián)網(wǎng)環(huán)境使用;提供目錄的版本控制;純2進(jìn)制的文件對(duì)比方式等。下面將介紹如何將SVN集成在Apache上。

  1. 準(zhǔn)備工作:

    1. 下載軟件:
      1. SVN服務(wù)器端程序。到官方網(wǎng)站 的下載二進(jìn)制安裝文件,來到二進(jìn)制包下載部分  ,找到 Windows NT, 2000, XP and 2003部分,然后選擇"this directory",這樣我們可以看到許多下載的內(nèi)容,目前可以下載 svn-1.2.3-setup.exe

      2. TortoiseSVN,客戶端程序。TortoiseSVN是擴(kuò)展Windows Shell的一套工具,可以看作Windows資源管理器的插件,安裝之后Windows就可以識(shí)別Subversion的工作目錄。
        官方網(wǎng)站是TortoiseSVN,下載方式和前面的svn服務(wù)器類似,在Download頁面的我們選擇Official version for Win2k/XP or higher的版本,然后在sourceforge的下載頁面選擇目前的最高穩(wěn)定版本的安裝文件TortoiseSVN-1.2.5.4719-svn-1.2.3.msi。(注意:TortoiseSVN有一個(gè)特殊對(duì)VS.Net運(yùn)行時(shí)一個(gè)BUG修正的版本,在下載頁面有選擇:Special version for Win2k/XP or higher: (We provide NO support for this!) uses _svn folders instead of .svn to work around the VS.NET bug with web projects. If you don't use web projects then please use the official version. )

      3. TortoiseSVN的中文語言包,注意這個(gè)需要下和客戶端程序版本相同的。可以在Download頁面內(nèi)的Language Packs選擇下載。

      4. Apache服務(wù)器程序。可以到Apache官方網(wǎng)站下載最新版本的Apache,并且SVN必須運(yùn)行在Apache2以上版本,在下載頁面選擇Windows的安裝包文件apache_2.0.55-win32-x86-no_ssl.msi

      5. AnkhSVN,可選安裝VS.Net的SVN插件。有0.5和0.6版本選擇,0.6版支持VS2005 Beta2,下載頁面

    2. 停止IIS,因?yàn)锳pache默認(rèn)安裝為80端口,需要關(guān)閉IIS避免端口沖突。可以在安裝好之后再調(diào)整端口。


  2. 開始安裝:

    1. 先安裝Apache服務(wù)器。在到填寫ServerInfo的時(shí)候,若機(jī)器已經(jīng)啟用了AD,安裝程序會(huì)自動(dòng)填寫,否則自己手動(dòng)填寫。安裝完成之后到安裝目錄下找到conf目錄下的httpd.config文件,搜索Listen,并將Listen后面的80改為8080(或者你希望的端口),然后重新啟動(dòng)Apache服務(wù)器,這時(shí)可以用http://localhost:8080 來測(cè)試是否安裝正確。

    2. 再安裝SVN服務(wù)器,沒有什么好說的,一路回車就可以了。(安裝SVN時(shí),請(qǐng)確保Apache服務(wù)器正在運(yùn)行狀態(tài),安裝過程中可能會(huì)將Apache關(guān)閉,重新啟動(dòng)屬于正常現(xiàn)象)

  3. 配置Apache服務(wù)器與SVN集成:


    1. 首先將Subversion安裝目錄bin\下面的兩個(gè)文件:mod_authz_svn.somod_dav_svn.so復(fù)制到Apache安裝目錄modules\目錄下。
    2. 有些文章說需要再修改httpd.conf,并做如下修改:
      找到Apache安裝目錄下的conf目錄,用文本編輯器打開httpd.conf,找到一下兩行:

      #LoadModule dav_module modules/mod_dav.so
      #LoadModule dav_fs_module modules/mod_dav_fs.so

      將每行前面的注釋符“#”去掉。再在所有LoadModule語句的最后添加一下幾行:

      #SVN
      LoadModule dav_svn_module modules/mod_dav_svn.so
      LoadModule authz_svn_module modules/mod_authz_svn.so

      但是我安裝完之后發(fā)現(xiàn)這個(gè)文件已經(jīng)被做了那些修改,大概是新版的SVN安裝程序做了一些優(yōu)化吧。其實(shí)在成功安裝SVN之后,Apache服務(wù)器已經(jīng)和SVN初步集成。如圖:

      Apache.jpg

      注意下面的狀態(tài)欄已經(jīng)是Apache/2.0.55 SVN1.2.3 DAV/2

    3. 建立一個(gè)SVN存放文件的目錄,我在F盤下創(chuàng)建一個(gè)文件夾:F:/SubversionFiles
    4. 接下來我們必須告訴Apache我們的資源庫所在的路徑,可以通過Location指令來完成這個(gè)設(shè)置。因?yàn)椴幌M麨槊總€(gè)單獨(dú)的項(xiàng)目都進(jìn)行單獨(dú)的設(shè)置,所以我們把所有項(xiàng)目都存放在統(tǒng)一的資源庫目錄,那么可以使用SVNParentPath指令來指定存放所有項(xiàng)目的路徑。在httpd.conf文件最后添加下面配置:

      #SVN

      <Location /svn>
          DAV svn
          SVNParentPath "F:/SubversionFiles"
      </Location>

    這樣我們就可以通過http://myhost:8080/svn/<項(xiàng)目名> 來訪問存放于資源庫F:/SubversionFiles中的指定項(xiàng)目。當(dāng)然有可能你并不希望某個(gè)項(xiàng)目提供這樣一種訪問方式,這時(shí)候你可以使用SVNPath為每個(gè)項(xiàng)目進(jìn)行單獨(dú)的設(shè)置,SVNPath的使用方法如下:

        DAV svn
        SVNPath "F:/SubversionFiles/project1"

    同樣把這段配置放在httpd.conf最后,重啟Apache HTTP服務(wù)即可通過http://myhost:8080/svn/project1 來訪問project1項(xiàng)目的資源庫。

    1. 下面作一個(gè)測(cè)試:

      1. 到F:\SubversionFiles下建立一個(gè)子目錄Test,然后到Aapche下的Bin目錄下執(zhí)行svnadmin create F:\SubversionFiles\Test

      2. 打開瀏覽器輸入網(wǎng)址:http://localhost:8080/svn/Test ,應(yīng)該可以正確訪問,但當(dāng)前該項(xiàng)目下還沒有加入任何內(nèi)容,所以顯示為空的

      3. 有一點(diǎn)需要提示的是,現(xiàn)在的訪問是完全匿名的,任何人都可以對(duì)SVN進(jìn)行操作。所以我們接下來利用Apache的權(quán)限管理功能來對(duì)SVN進(jìn)行用戶驗(yàn)證集成

    2. 加入用戶身份驗(yàn)證:

      在確定對(duì)訪問用戶的權(quán)限控制之前,你必須規(guī)劃好是對(duì)整個(gè)資源庫中的所有項(xiàng)目還是單獨(dú)的某一個(gè)項(xiàng)目進(jìn)行統(tǒng)一的身份驗(yàn)證, 也就是我們前面講到的是使用SVNParentPath還是SVNPath的問題。

      最簡(jiǎn)單的身份驗(yàn)證方式是使用Basic HTTP Authentication機(jī)制,該方式通過用戶名和口令對(duì)訪問用戶進(jìn)行身份驗(yàn)證。我們可以直接通過Apache提供的支持進(jìn)行設(shè)置。Apache提供一個(gè)htpasswd工具來管理用戶名和口令。接下來我們利用這個(gè)工具來添加兩個(gè)用戶。

      在命令行窗口中轉(zhuǎn)到Apache所在的目錄,執(zhí)行下列命令

      說明:創(chuàng)建用戶Xrinehart
      輸入:htpasswd –c F:\SubversionFiles\svn_auth_passwd Xrinehart
      說明:使用-c參數(shù)來創(chuàng)建一個(gè)passwd文件
      輸出:
      New password: *****
      Re-type new password: *****
      Adding password for user Xrinehart

      再創(chuàng)建用戶的時(shí)候就不用-c參數(shù),而是用-m參數(shù),因?yàn)槲募?/font>svn_auth_passwd經(jīng)創(chuàng)建。

      打開svn_auth_passwd文件,密碼使用MD5加密過了,而且同樣的密碼加密出來的內(nèi)容卻不相同

      接下來我們必須告訴Apache服務(wù)器如何使用這個(gè)passwd文件,打開httpd.conf找到剛才我們添加的Location配置的位置,修改如下:

      #
      # SVN
      #

        DAV svn
        SVNParentPath "F:/SubversionFiles"

      # how to authenticate a user
       AuthType Basic
       AuthName "Subversion repository"
       AuthUserFile "F:/SubversionFiles/svn_auth_passwd"
       
        # only authenticated users may access the repository
      Require valid-user


      重新啟動(dòng)Apache HTTP服務(wù)器,使用瀏覽器打開 http://localhost:8080/svn/Test 你將會(huì)看到要求登錄的對(duì)話框,輸入你剛設(shè)置的用戶名和口令即可。

      這樣Apache和SVN的集成就基本告成了



]]>
主站蜘蛛池模板: 连山| 伊春市| 张北县| 宣化县| 靖江市| 南雄市| 灌阳县| 高阳县| 靖西县| 新绛县| 东丰县| 乌拉特后旗| 镇巴县| 卫辉市| 南岸区| 龙泉市| 汉阴县| 巴南区| 高阳县| 波密县| 龙江县| 临夏市| 菏泽市| 宁陕县| 阿拉善盟| 津南区| 横峰县| 东方市| 太原市| 乌拉特后旗| 临澧县| 黔南| 万全县| 阜新市| 彩票| 沙田区| 金山区| 北票市| 嘉义市| 潞西市| 四会市|