【正文】
后再輸出。這樣的做法是極不可取的!因為字符串的多次拼接會使運行效率大大下降,原因是每次給strTemp賦值時,都會重新分配這個變量的大小,運行效率就可想而知。2)用Form提交數(shù)據(jù)的基本技術(shù)。在這個頁面中還有兩處需要注意,第一處是Form的定義,如下代碼:form method=post actiom= nameform1另外一處是“添加”按鈕的定義,如下代碼:input type=submit name=Submit value=添加在這兩行HTML代碼中,“action=””表示當(dāng)此表單提交時,而提交動作無疑是由“添加”按鈕來實現(xiàn)的,所以這里必須設(shè)置“添加按鈕type=submit”。,實現(xiàn)原理就是將表單中的數(shù)據(jù)庫利用ADO對象或SQL語句寫到數(shù)據(jù)庫中。此處為了演示Command對象的用法。雖然把著幾句曲調(diào)后程序仍然可以運行,但實際上他們非常關(guān)鍵。在這行代碼中,首先是關(guān)閉和釋放當(dāng)前記錄集,然后在調(diào)用CloseConn關(guān)閉連接,這樣操作之后才可以將剛才使用過的連接放到連接池中,供其他頁面使用。 修改類別(部分),圖63為修改類別的運行界面。從圖中可以看到修類別似乎要比天家類別簡單一些,事實上也的確如此,所以在本系統(tǒng)中沒有將它單獨做成一頁,而是將其放在類別列表頁中,當(dāng)通過url參數(shù)傳入的id不是“0”時,將顯示修改界面。圖63 修改類別運行界面與添加類別頁面類似,當(dāng)單擊[保存]按鈕時,會將表單中的數(shù)據(jù)發(fā)送到其action屬性所指向的文件。但這時就產(chǎn)生了一個問題,那就是頁面上只有一個類別名字,通過表單如何傳送類別的id呢?下面來回答這個問題。:input type = text name = name value = %=szSuperName%input type = hidden name = id value = %=intID%input type = submit name = Submit value = 保存在這三個“input”元素中,顯然第一個是用來顯示類別名稱的文本框,最后一個是[保存]按鈕,那么第二個“hidden”是什么呢?沒錯,它的作用就是用來傳遞類別的id,表單元素“hidden”的特征就是可以象文本框一樣通過表單提交數(shù)據(jù),但本身并不相識出來。明白了這個問題之后。所不同的是,,并且要先用下面的sql語句從數(shù)據(jù)庫中檢索出待修該的字段。SELLECT * FROM ProductType WHERE id=amp。nID上面sql語句中的nid就是傳入的類別編號。 ,在這個頁面中,仍然要注意操作完數(shù)據(jù)庫以后,要手工釋放連接。另外,這個頁面也沒有進(jìn)行數(shù)據(jù)合法性檢查,即檢查所修改的類別名稱是否已經(jīng)存在,或者是否有其他問題等,事實上這類問題在一個完善的系統(tǒng)中是必不可少的。 刪除類別,類別id通過url參數(shù)傳入,因此首先要從request的querystring集合中取出類別id,并需要將其兩邊的空格和可能存在的單引號去除。然后,分別檢查是否存在下級類型和此類所屬的產(chǎn)品,如果不存在,則可以將此類型刪除。在實現(xiàn)此項功能時,有一個非常得關(guān)注的安全問題,此頁面中所要刪除的類別id是由url參數(shù)傳入的,這就使一些專門的“高手”有了可乘之機。調(diào)用這個文件的url類似如下:……對于這樣的鏈接,就會有人模仿輸入:……這樣,如果你原來有一個sql語句是如下的話:strSQL=DELETE FROM ProductType WHERE id=amp。intID接受這樣的輸入,你的sql語句最終極有可能變成下面這樣:DELETE FROM ProductType WHELE id=2 or 1=1這條小小的語句就可以很恐怖地將你producttype表中的數(shù)據(jù)一下子全部刪除!當(dāng)然,只是最壞的情況,在大多數(shù)情況下由于本頁面其他代碼影響及數(shù)據(jù)庫完整性限制,情況并沒有這么糟,比如這種情況在本頁就基本不會發(fā)生。在這里提出的目的是要告訴大家,在接收通過url參數(shù)傳入的數(shù)據(jù)時,要格外小心,可以從以下幾個方面來考慮安全情況:● 用戶是否有權(quán)訪問此頁,未登陸的管理員無法訪問此頁。● 對獲取的參數(shù)進(jìn)行驗證,如本例中根據(jù)實際情況知道輸入的必定是數(shù)字,于是就用isnumeric函數(shù)來判斷輸入是否合法。在其他應(yīng)用中我們可以根據(jù)具體情況判斷,如只能是字符、不包括空格等?!?要注意,從form中獲取的值同樣存在此問題,如經(jīng)常會有人在登陸文本框中做類似的文章。 商品(商品)維護(hù)模塊商品維護(hù)模塊的功能主要由以下幾個文件來實現(xiàn):● 顯示商品列表:● 添加商品頁面:● 保存添加的商品信息:● 刪除商品:● 修改商品界面:● 保存商品修改結(jié)果:● 上傳圖片界面:● 保存上傳圖片:● 推薦或取消推薦商品:商品維護(hù)模塊可以說是在所有管理模塊中最復(fù)雜的一個,也是整個系統(tǒng)的核心,所以我們在類別管理模塊的基礎(chǔ)上對這個模塊的重點內(nèi)容加以詳細(xì)講解。商品維護(hù)與類別管理相比,難點在于不僅涉及數(shù)據(jù)較多,而且還涉及商品圖片上傳、推薦或取消推薦商品等。下面,與類別管理類似,首先來看商品列表的實現(xiàn)。 顯示商品列表,圖64為管理商品列表的運行結(jié)果,可以看到她與類別維護(hù)截面非常相似,這樣便于網(wǎng)站管理人員使用。圖64 管理商品列表運行結(jié)果此頁的原理是每次訪問此頁是,都會從request對象的querystring集合和form 集合中尋找以下三個參數(shù):→ page:當(dāng)前頁號,位于querystring集合中,如果找不到,默認(rèn)為“1”?!? mykeyword:過濾產(chǎn)品的關(guān)鍵字,位于form集合中,如果找不到,默認(rèn)為空?!? producttype:產(chǎn)品類型編號,位于form集合中,如果找不到,默認(rèn)為“0”。然后根據(jù)mykeyword和producttype的值來組織sql語句從product表中檢索數(shù)據(jù)。組織過程如下面的代碼所示:39。組織SQL語句,注意這里WHERE 1=1的妙用strSQL = SELECT * FROM product WHERE 1 = 1if not (myKeyword = or IsEmpty(myKeyword) ) thenstrSQL = strSQL amp。 AND name like 39。% amp。 myKeywordamp。 %39。 end ifif ProductType0 thenstrSQL = strSQL amp。 AND ProductType = amp。 ProductTypeend ifstrSQL = strSQL amp。 ORDER by id desc這段sql語句中,在第一行可以看有“where 1=1”這樣的代碼,它使用得非常巧妙,這樣,在下面添加mykeyword和producttype條件時可以放心地在前面寫得非常巧妙,這樣,在下面添加mykeyword和producttype條件時可以放心地在前面寫“and name ……”,而不必?fù)?dān)心由于if語句的條件不成立所帶來的sql語法錯誤。另外,由于本頁需要在下拉列表中顯示所有的類別名稱,并且在商品列表中也有相應(yīng)的列需要顯示類別名稱,所以需要在檢索product表之前先從producttype表中檢索出所有的類別編號和名稱。在這個頁面代碼中要注意以下幾個技巧。1) 將通用的功能寫成簡單函數(shù)。在頁面的開頭,typetoselect函數(shù)的作用是將數(shù)據(jù)庫中的類別田間到下拉列表框中。大家應(yīng)該記得在添加類別時也用到了這個功能,不過在這里將這個功能封裝成一個函數(shù),在使用時只要如下調(diào)用即可:%call typetoselect(ntypeid,szctrlname)%其中,通過第一個參數(shù)ntypeid傳入類別編號,設(shè)定在顯示時所選中的類別:通過第二參數(shù)szctrlname以字符串的形式傳入表單中select元素的名稱(name屬性),在從request對象的form集合中獲取參數(shù)時使用。如在本頁中,獲取用戶在下拉列表框中選中的商品類型編號用下面的語句:39。獲取用戶選中的類別對應(yīng)的類別編號producttype=pealstring((producttype))這時也許就有人問,?由這個問題,可以引出下面的技巧。2)合理使用request對象。許多初學(xué)者對常見的用request對象獲取參數(shù)時所使用的以下三種方法的區(qū)別不太明白:→ (var)→ (var)→ request(var)簡單的說,;,但此時表單的method屬性必須設(shè)為“post”,關(guān)于表單method屬性設(shè)為“post”和“get”的區(qū)別,請參見下一個技巧。對于第三種方式,用request(var)這種非限定性的方式來獲取參數(shù),雖然可以省略集合名,直接在querystring和form等集合中獲取變量值,但微軟及其他專業(yè)人士則強烈反對這種做法,因為這會使查詢效率降低,而且還會由于變量重名而帶來讓人費神的邏輯錯誤,事實上,request對象一共有5個集合,當(dāng)使用非限定性的方式查找參數(shù)時,會依次從這5個集合中查找,然后返回第一個查找到的結(jié)果。這5個集合的查找順序是:→ querystring→ form→ cookies→ clientcertificate→ servervariables可以看到,雖然querystring和form排的比較靠前,對效率的影響也許并不很嚴(yán)整,但養(yǎng)成一個良好的編程習(xí)慣對開發(fā)和維護(hù)都非常有好處。3)form中method屬性取值為“get”和“post”的區(qū)別。二者的區(qū)別如下:● get:form中的數(shù)據(jù)會追加到action屬性所指定的url后面,此時只能從querystring集合中查找參數(shù)?!?post:form中的數(shù)據(jù)不會追加到action屬性所指定的url后面,此時原url后面本身的參數(shù)仍用querysting獲取。最后要注意,在form中一般需要有一個“type=submit”的input元素來提交表單數(shù)據(jù)。 添加商品,圖65為在商品列表頁面中單擊[添加]按鈕后所看到的添加商品頁面。從圖中可以看到,在添加商品時仍需用一個下拉列表框指定它所屬的類別,顯然,我們剛才所做的typetoselect函數(shù)可以派上用場了。圖65 添加商品頁面在前面介紹的知識基礎(chǔ)之上,此頁面實現(xiàn)起來非常容易,首先調(diào)用剛才做好的typetoselect函數(shù)顯示類別列表框,然后剩下的就純屬頁面設(shè)計的任務(wù)了。不過這里一定要對輸入進(jìn)行驗證,包括輸入是否為空,所輸入的價格必須是數(shù)字,以及輸入長度的限制等。由于這些是純html和javascript技巧,這里從略。在添加商品界面中單擊[添加]按鈕,先面來看這個文件的實現(xiàn)。,其實現(xiàn)原理與添加類別很相似,就是將一個表單中的數(shù)據(jù)利用ado對象或sql語句寫入到數(shù)據(jù)庫中,不過由于數(shù)據(jù)庫較大,此處就變得復(fù)雜多了。在這個頁面中,仍然要注意操作完數(shù)據(jù)庫以后,要手工釋放連接。另外,這里只進(jìn)行了簡單的數(shù)據(jù)驗證,如果提交的價格不是數(shù)字的話,將它們默認(rèn)置為“1”,而不能直接用cint 轉(zhuǎn)為“0”,否則在將來計算商品打折時由于分母為“0”會出錯。 修改商品,圖66為修改商品的運行界面。從圖中可以看到,修改商品與添加商品的見面非常相似,事實上也的確如此,所不同的是。圖66 修改商品運行界面在編寫修改商品頁面中,應(yīng)該注意:1)盡量利用客戶瀏覽器驗證。在這個頁面中,注意下面的代碼:form method=post action= onSubmit=return checkForm()其中“onSubmit=return checkForm()”的意思就是當(dāng)提交這個表單時,將觸發(fā)checkForm()函數(shù),并根據(jù)這個函數(shù)的返回值決定是否提交表單。這些過程都是在客戶模塊完成的,也就是說是在向服務(wù)器傳送數(shù)據(jù)之前。因此,通常在這里放置一些輸入驗證的內(nèi)容,因為在客戶模塊利用瀏覽器驗證要比在服務(wù)器驗證速度快得多,同時也可以大大減輕服務(wù)器負(fù)擔(dān)。但這并不意味著服務(wù)器可以不進(jìn)行驗證,為了防止有人故意繞過客戶模塊驗證而企圖對服務(wù)器上的數(shù)據(jù)進(jìn)行惡意破壞或窺探,在服務(wù)器端仍要進(jìn)行必要的驗證,記住只是必要的驗證,否則便失去了客戶模塊驗證的意義。2)合理的頁面結(jié)構(gòu)設(shè)計在一個頁面中,如果JSP腳本代碼與HTML頁面代碼混雜在一起,不僅極不方便將來的代碼維護(hù),而且會導(dǎo)致頁面執(zhí)行效率大大下降。合理的解決辦法是采用Include語句將其包含近來,或者將JSP腳本的執(zhí)行結(jié)果即可。這點在上面的代碼中體現(xiàn)得非常好,在頁面開始部分,根據(jù)參數(shù)傳入的商品ID檢索數(shù)據(jù)庫,讀出商品信息,并將其存儲VBScript局部變量中,然后在下面的HTML代碼中用%=var%將其輸出,也即將商品信息顯示在文本框中。 刪除商品,商品ID通過URL參數(shù)傳入,因此首先要從Requesst的QueryString集合中取出商品ID,并需要將其兩邊的空格和可能存在的單引號去掉,然后組織SQL語句刪除,SQL語句的組織過程如下:strSQL=“DELETE FROM Product WHERE id=”amp。 nID這里要注意的是安全問題,必須對其合法性進(jìn)行判斷。 上傳商品圖片,在商品列表中單擊上傳圖片的鏈接即可彈出上傳圖片的窗口,如圖67所示:圖67 上傳圖片窗口此頁的原理是每次訪問此頁時,都會從Request對象的QueryString集合中尋找以下兩個參數(shù): id:需要上傳圖片的商品編號。 type:上傳的圖片類型,分為大圖片和小圖片兩種,取值分別是“bigImg”和“smallImg”。然后在hidden區(qū)域中保存他們的值,如下面的代碼所示: input type =39。hidden name=type value=%(type)% input type =39。hidden name=i