一、環境搭建
1、準備
(1)開發工具
- 編譯器:IntelliJ IDEA 2018.3.5
- 資料庫管理系統:mysql
- 伺服器:tomcat9
- 資料庫視覺化介面:sqlyog
- 程式碼管理工具:svn
- 專案管理工具:maven
(2)新建maven專案
並在pom.xml配置檔案中匯入基本的依賴,後續在使用的過程中匯入其他的依賴。
(3)新增專案到svn
在伺服器端新建一個倉庫,並將IDEA中新建的專案進行提交
(4)配置spring
- annotation.xml:掃描註解,只掃描service層的註解,dao層由mybatis管理,controller層由springmvc管理
- jdbc.xml:讀取jdbc的配置檔案的資料,獲取dataSource
- jdbc.properties:jdbc的配置檔案
- property.xml:讀取jdbc配置,這樣配置的好處是list中可以配置多個配置檔案的讀取
- transation.xml:配置事務、開啟事務註解
- mybatis.xml:掃描dao層的註解、獲取sessionFactory
- application-context.xml:引入以上關於spring的配置檔案
(5)springmvc
- springmvc-back.xml:掃描controller層的包、檢視解析器(後臺)、配置springmvc支援上傳圖片
- springmvc-front.xml:掃描controller層的包、檢視解析器(前臺)
- web.xml:配置springmvc的前端控制器、引入spring的核心配置檔案、spring的監聽器、處理中文亂碼的過濾器
二、後臺
1、景點分類資訊
(1)顯示全部類別
顯示全部的分類資訊實際上是一個帶有條件的分頁查詢,條件為類別的名稱,分頁的引數為起始行和每一頁的大小。
在dao層需要執行一個帶有條件的分頁查詢獲取符合條件的分類的資訊,還需要獲取分類的總記錄數將獲取到的資料作為service層pagination的引數,pagination還需要頁號、每頁數作為引數
在service層pagination獲取到以上三個引數後就建立成功了,然後將查詢到的分類資料寫入到pagination物件中。
在controller層會將頁面提交的條件:頁號和分類的名稱封裝到分類物件裡面作為引數傳遞到service層,並獲取到pagination物件,將路徑和引數作為pagination的引數
頁面中直接遍歷pagination,進行分頁顯示;遍歷pagination裡面的list(分類資訊),將分類資訊顯示在頁面上
(2)圖片上傳
配置springmvc支援上傳圖片
搭建圖片伺服器,也就是說需要一臺專門儲存上傳的圖片的伺服器:https://www.cnblogs.com/zhai1997/p/13337064.html,在伺服器的webapp目錄下建立資料夾作為圖片儲存的根目錄
圖片的上傳採用的是Jersey(需要導包),利用該框架上傳圖片需要該圖片的完整路徑
由於需要避免圖片的重名,採用當前時間加隨機數拼接的方式來生成圖片名稱,將名稱與獲取到的副檔名、伺服器地址和儲存圖片的目錄進行拼接即可得到圖片的完整路徑
在頁面的input標籤內將name屬性定義為pic,controller層獲取到該屬性,可以根據pic獲取圖片的字尾
提交圖片是用的jQuery Form外掛,它是一個優秀的Ajax表單外掛,可以非常容易地、無侵入地升級HTML表單以支援Ajax。將圖片提交到controller後,通過回撥函式獲取到圖片的全路徑和圖片在伺服器內部的地址(改地址將被儲存到資料庫),將圖片的全路徑賦給src屬性進行圖片的顯示,圖片在伺服器的地址寫在隱藏域。
(3)新增景區分類
在controller層獲取到表單資料,最終執行insert語句將資料持久化到資料庫。然後重定向到分類顯示頁面顯示分類資訊
(4)刪除一個分類
刪除的時候需要攜帶被刪除的分類的id(用於確定分類並刪除),分類的名稱(運用jq獲取到輸入框中分類的名稱)兩個引數。將引數傳遞到controller層,分類名在重定向之後會重新顯示到頁面上,id則最終被傳遞到dao層根據id刪除分類
(5)刪除多個分類
要先實現多選的核取方塊,保證一次可以選中多個要刪除的分類資訊
刪除的時候用到提交圖片是用的jQuery Form外掛,要確保要刪除的元素在form表單內部。在提交的時候被選中的核取方塊的值(值是分類的id)將被提交到controller,並將分類的名稱作為引數攜帶到controller層,分類名不為空的時候要進行回顯,將被選中的分類的id作為引數最終傳遞到dao層,在dao層採用foreach標籤取出陣列中的資料
(6)修改
分為兩步:
- 去修改頁面,在頁面中需要向controller傳遞被修改的分類的id,根據id獲取到分類物件後在修改頁面進行該分類的資訊的回顯。其中被修改的分類的id要寫在隱藏域內,因為執行修改的sql語句需要藉助於id對分類進行修改
- 填寫相關資訊後將表單提交到controller中,並將分類物件傳遞到dao層執行根據id修改分類資訊的語句
2、景區資訊管理
(1)顯示全部景區資訊
與分類資訊相比,對sql語句進行了優化,如:查詢的時候根據欄位是否為空來確定是否查詢此欄位,通過減少欄位的查詢提高系統的執行效率,避免了對全表進行查詢;通過mybatis的sql標籤將sql語句封裝為單獨的模組,使用的時候根據id呼叫該模組,可以減少程式碼的冗餘。
(2)景區描述
通過fck上傳景區相關的圖片,通過頁面請求controller層的方法對圖片進行處理,fck是支援多個圖片的上傳的
(3)新增景區
在頁面獲取到使用者輸入的資訊,提交後傳遞到controller層直接封裝為model不用手動獲取引數在進行分裝,這也就體現出了springmvc相比於傳統的mvc模式的優勢
由於景區的有一些屬性的值不是單一的,例如:門票屬性分為兒童票、成人票等。為了能夠唯一確定一個景區的某一使用者的票就需要使用sku,即景區的最小儲存單元。在service層新增景區的時候還要新增景區的最小儲存單元。
三、前臺
主頁面顯示、景區詳情、支付模組
(1)顯示大分類、小分類、景點
大分類(國內、國外等)、小分類(踏青、展館、遊樂場、文化古蹟、動植物園、歷史名城等)景點,是採用的foreach標籤的的巢狀來進行顯示的,其中景點的顯示是由大分類的ID和小分類的ID共同決定的
採用分頁查詢,每一個大分類下的小分類是採用的分頁查詢,為了頁面的美觀和使用者友好性只顯示八個景區的資訊。
為了解決訪問網站首頁的空指標問題,需要在訪問首頁的連結中新增大分類和小分類的引數,因為採用是onclick事件,而首次載入的時候並未點選任何的分類,因此需要在初始化的時候傳遞引數。如果沒有初始化引數,獲取景區的條件查詢沒有查詢的條件就會出現空指標異常。
(2)更多景點資訊
根據景區大分類的ID(國內、國外、周邊遊)獲取景區的資訊,即:獲取某一個大類的所有景區資訊並展示
(3)檢視某一景點資訊
根據景點ID查詢景點資訊和該景點的門票資訊
(4)門票預定
需要獲取景點和門票資訊進行展示,並獲取購票者的資訊寫入到資料庫中
(5)支付模組
運用的是支付寶的沙箱環境,只是模擬付款流程
註冊模組
(1)郵箱註冊
使用js的validation表單校驗外掛來在頁面對輸入的郵箱、密碼、驗證碼進行格式、非空、長度等的校驗
將使用者的郵箱、密碼、使用者狀態(初始值為0)、啟用碼寫入到資料庫後,會傳送一個郵件提醒使用者點選連結啟用賬戶,該連結是訪問controller層的方法,根據啟用碼來更新啟用碼對應的使用者的狀態(啟用後為1)
(2)手機註冊
採用的是手機號註冊,獲取註冊的時候輸入的手機號,並向這個手機號傳送啟用碼,工具類負責啟用碼的傳送,在service層將啟用碼與手機號拼接,在controller層再分別取出手機號與啟用碼,目的是保證註冊的手機號與工具類傳送啟用碼的手機號是同一個。所有的驗證都正確的情況下將該賬號的狀態設定為1,並將使用者的註冊資訊寫入到資料庫。
註冊頁面點選獲取啟用碼其實是傳送ajax請求,請求引數是手機號,返回值是傳送啟用碼是否成功的布林值。點選的同時開始60s倒數計時,防止使用者一直獲取啟用碼。
手機驗證的原理是:工具類根據使用者輸入的手機號向該手機號傳送驗證碼,並且工具類會返回驗證碼。在service層將啟用碼與手機號拼接,在controller層再分別取出手機號與啟用碼,目的是保證註冊的手機號與工具類傳送啟用碼的手機號是同一個。如果controller層從session中獲取到的驗證碼與從表單接收到的驗證碼是一致的則證明驗證成功,否則,使用者需要重新輸入。
登入模組
登入模組分為手機號登入與郵箱登入,採用郵箱/手機號+密碼+圖片驗證碼的方式進行,圖片驗證碼可以防止黑客對使用者賬號的暴力破解。
優化:
1、freemarker的應用
在後臺景區管理處有景區靜態化的按鈕,點選後前臺的景區詳情頁就是訪問的靜態頁面(html),減少了前臺的資料庫的訪問,但是存在一個問題就是當對景區修改後存在靜態頁與資料庫中的資料不一致的問題,此時就可以點選按鈕對已經存在不一致的景區進行手動的靜態化,使得資料保持一致。
使用freemarker需要先匯入相應的依賴,然後就是建立模板物件、獲取資料,由模板物件和資料就可以生成目標物件了(html頁面),這裡是使用景區的ID與景區的分類ID獲取到景區資訊河景區的門票資訊,然後是根據模板生成靜態頁面,前臺訪問靜態頁面即可。
2、sql語句
- 只對需要的欄位進行查詢
brandQuery.setFields("bid,bname");//傳遞分類的欄位
取出需要查詢的欄位並執行查詢操作:
<sql id="scenicspotSelector"> SELECT <if test="fields != null"> ${fields} </if>
- 進行欄位的非空校驗,如果欄位為空就不會對該欄位進行查詢
<if test="sid != null"> and sid=#{sid} </if> <if test="description != null"> and description=#{description} </if> <if test="location != null"> and location=#{location} </if>
否則將導致引擎放棄使用索引而進行全表掃描
- mybatis的sql標籤進行語句的模組化封裝,實現了XML檔案中sql語句的複用
<select id="getScenicSpotListWithPage" parameterType="com.zhb.core.query.scenicspot.ScenicSpotQuery" resultMap="scenicspot"> <include refid="scenicspotSelector" /> <include refid="scenicspotListWhere" /> <include refid="scenicspotListLimit1" /> </select>
3、使用單獨的伺服器來儲存圖片,減少主伺服器的壓力