版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p> Web程序設(shè)計(jì)說(shuō)明書(shū)</p><p> 姓名 LL </p><p> 專業(yè) 計(jì)算機(jī)科學(xué)與技術(shù) </p><p> 考號(hào) 0901051319 </p><p><b> 1 需求分析</b></p>
2、<p><b> 1.1 功能需求</b></p><p> 本系統(tǒng)實(shí)現(xiàn)如下功能:</p><p><b> 用戶管理</b></p><p> 用戶分為管理員和普通用戶</p><p> 普通用戶擁有創(chuàng)建并管理書(shū)架、上傳并管理圖書(shū),評(píng)論、收藏、舉報(bào)圖書(shū)等功能。</p&
3、gt;<p> 管理員除了擁有普通用戶的所有功能外,還可以管理系統(tǒng)圖書(shū)分類、舉報(bào)信息和用戶信息。</p><p> 管理員登錄后,可以在管理中心中封鎖、解鎖用戶。</p><p><b> 分類管理</b></p><p> 添加分類:管理員可以添加小說(shuō)分類,分類不可以重名。</p><p> 修
4、改分類:管理員可以修改分類的名字,分類不可以重名。</p><p> 刪除分類:管理員可以刪除分類,當(dāng)分類下有小說(shuō)存在時(shí),無(wú)法成功刪除分類。</p><p><b> 書(shū)架管理</b></p><p> 添加書(shū)架:用戶登錄后可以添加書(shū)架,書(shū)架的名字可以重名。</p><p> 修改書(shū)架:用戶登錄后可以修改自己創(chuàng)建
5、的書(shū)架,書(shū)架名字可以重名。</p><p> 刪除書(shū)架:用戶登錄后可以刪除自己創(chuàng)建的書(shū)架,當(dāng)書(shū)架下有小說(shuō)存在時(shí),無(wú)法成功刪除書(shū)架。</p><p> 訂閱書(shū)架:用戶登錄后可以訂閱網(wǎng)站上的任意一個(gè)書(shū)架。</p><p><b> 小說(shuō)管理</b></p><p> 上傳小說(shuō):用戶登錄后可以上傳TXT格式的小說(shuō),小說(shuō)
6、不得大于5M,并且需要有固定格式的章節(jié)信息,比如“第X卷 第X章 XXXX”。小說(shuō)上傳成功后會(huì)自動(dòng)生成小說(shuō)章節(jié)索引,方便用戶按章節(jié)閱讀小說(shuō)。如果上傳小說(shuō)時(shí)用戶沒(méi)有指定小說(shuō)摘要,則會(huì)自動(dòng)以小說(shuō)前六章的章節(jié)標(biāo)題組成摘要。</p><p> 修改小說(shuō):用戶登錄后可以修改自己上傳的小說(shuō)信息,更改小說(shuō)的所屬分類和書(shū)架等信息。</p><p> 刪除小說(shuō):用戶登錄后可以刪除自己上傳的小說(shuō),小說(shuō)刪除
7、時(shí),會(huì)連帶刪除小說(shuō)的評(píng)論等信息。</p><p> 收藏小說(shuō):用戶登錄后可以收藏網(wǎng)站上的任意一部小說(shuō)。</p><p> 舉報(bào)小說(shuō):用戶可以舉報(bào)自己認(rèn)為有不良信息或者不合法信息的小說(shuō),管理員會(huì)及時(shí)處理舉報(bào)信息。</p><p> 評(píng)論小說(shuō):用戶登錄后可以對(duì)網(wǎng)站上的任意一部小說(shuō)發(fā)表評(píng)論。</p><p><b> 統(tǒng)計(jì)信息&l
8、t;/b></p><p> 統(tǒng)計(jì)小說(shuō)閱讀量:網(wǎng)站會(huì)對(duì)小說(shuō)的閱讀次數(shù)進(jìn)行統(tǒng)計(jì),以作為熱門(mén)小說(shuō)的排名依據(jù)。</p><p> 統(tǒng)計(jì)小說(shuō)評(píng)論量:網(wǎng)站會(huì)對(duì)小說(shuō)的評(píng)論次數(shù)進(jìn)行統(tǒng)計(jì),以作為熱門(mén)小說(shuō)的排名依據(jù)。</p><p> 統(tǒng)計(jì)小說(shuō)收藏量:網(wǎng)站會(huì)對(duì)小說(shuō)的收藏次數(shù)進(jìn)行統(tǒng)計(jì),以作為熱門(mén)小說(shuō)的排名依據(jù)。</p><p> 統(tǒng)計(jì)書(shū)架小說(shuō)數(shù):網(wǎng)
9、站會(huì)對(duì)各個(gè)書(shū)架中小說(shuō)的數(shù)量進(jìn)行統(tǒng)計(jì)。</p><p> 統(tǒng)計(jì)分類小說(shuō)數(shù):網(wǎng)站會(huì)對(duì)各個(gè)分類中小說(shuō)的數(shù)量進(jìn)行統(tǒng)計(jì)。</p><p> 1.2 數(shù)據(jù)庫(kù)需求分析</p><p> 不管對(duì)數(shù)據(jù)庫(kù)設(shè)計(jì)還是對(duì)系統(tǒng)設(shè)計(jì)來(lái)說(shuō),需求分析都是第一步。需求的目的就是搞清楚用戶要做什么,如果需求做的仔細(xì),可以在后面的設(shè)計(jì)和實(shí)現(xiàn)中少做很多無(wú)用功,其重要性是不言自明的。做需求分析需要有點(diǎn)心
10、理學(xué)的知識(shí),要能充分的跟客戶進(jìn)行交流,能抓住問(wèn)題的關(guān)鍵所在,最終能夠快速的搞清楚系統(tǒng)所要實(shí)現(xiàn)的業(yè)務(wù)。</p><p> 需求分析的方法在軟件工程中都有說(shuō)明,不管哪種方法,最重要的都是與用戶的溝通和交流,引導(dǎo)用戶正確的確認(rèn)問(wèn)題。用戶需求具體體現(xiàn)在各種信息的提供、保存、更新和查詢,這就要求數(shù)據(jù)庫(kù)結(jié)構(gòu)能充分滿足各種信息的輸出和輸入。</p><p> 根據(jù)用戶的需求設(shè)計(jì)數(shù)據(jù)庫(kù)如下:</
11、p><p> 用戶:編號(hào),郵箱,昵稱,密碼,頭像,角色,注冊(cè)日期,狀態(tài),書(shū)架數(shù),小說(shuō)數(shù)。</p><p> 分類:編號(hào),名稱,小說(shuō)數(shù)。</p><p> 小說(shuō):編號(hào),書(shū)名,作者,大小,細(xì)節(jié),狀態(tài),分類編號(hào),書(shū)架編號(hào),文件路徑,上傳日期,上傳用戶,閱讀量,評(píng)論量,收藏量。</p><p> 書(shū)架:編號(hào),名稱,創(chuàng)建者,創(chuàng)建日期,小說(shuō)數(shù)。<
12、;/p><p><b> 3 數(shù)據(jù)庫(kù)設(shè)計(jì)</b></p><p> 3.1 數(shù)據(jù)庫(kù)概念結(jié)構(gòu)設(shè)計(jì)</p><p> 在需求分析的基礎(chǔ)上,設(shè)計(jì)出能夠滿足用戶需求的各種實(shí)體以及它們之間的關(guān)系,現(xiàn)將各實(shí)體及實(shí)體之間的E-R圖描述如下:</p><p><b> (1)分類實(shí)體:</b></p>
13、;<p> 圖3.2 分類實(shí)體圖</p><p><b> ?。?)用戶實(shí)體:</b></p><p> 圖3.3 用戶實(shí)體圖</p><p><b> ?。?)書(shū)架實(shí)體:</b></p><p> 圖3.4 書(shū)架實(shí)體圖</p><p><b>
14、 ?。?)小說(shuō)實(shí)體:</b></p><p><b> 、</b></p><p> 圖3.5 小說(shuō)實(shí)體圖</p><p><b> ?。?)總體ER圖:</b></p><p> 圖3-6 ER圖總圖</p><p> 3.2 數(shù)據(jù)庫(kù)邏輯結(jié)構(gòu)設(shè)計(jì)<
15、;/p><p> 現(xiàn)在把數(shù)據(jù)庫(kù)概念設(shè)計(jì)的E-R圖轉(zhuǎn)化為關(guān)系數(shù)據(jù)。在關(guān)系數(shù)據(jù)庫(kù)中,數(shù)據(jù)關(guān)系由數(shù)據(jù)表組成的,而表的結(jié)構(gòu)體現(xiàn)在表的字段上。具體為:確定數(shù)據(jù)庫(kù)中數(shù)據(jù)表的組成;確定數(shù)據(jù)表中字段的構(gòu)成,主鍵字段和有關(guān)字段的約束條件;依據(jù)表中主鍵字段建立數(shù)據(jù)表之間的關(guān)系。數(shù)據(jù)的合理性問(wèn)題:數(shù)據(jù)表內(nèi)記錄不重復(fù);數(shù)據(jù)字段不可分割,具有最小數(shù)據(jù)單位的特點(diǎn);數(shù)據(jù)表內(nèi)字段或字段之間互不依賴。具體結(jié)構(gòu)如下圖所示:</p>&l
16、t;p><b> 1. 用戶表</b></p><p><b> 表3-1 用戶表</b></p><p><b> 2. 分類表</b></p><p> 表3-2 小說(shuō)分類表</p><p><b> 3. 小說(shuō)表</b><
17、/p><p><b> 表3-3 小說(shuō)表</b></p><p><b> 4.書(shū)架表</b></p><p><b> 表3-4 書(shū)架表</b></p><p><b> 5.書(shū)架訂閱表</b></p><p> 表3-5
18、 書(shū)架訂閱表</p><p><b> 6.小說(shuō)評(píng)論表</b></p><p> 表3-6 小說(shuō)評(píng)論表</p><p><b> 7.小說(shuō)收藏表</b></p><p> 表3-7 小說(shuō)收藏表</p><p><b> 8.小說(shuō)舉報(bào)表</b>&
19、lt;/p><p> 表3-8 小說(shuō)舉報(bào)表</p><p><b> 9小說(shuō)閱讀表</b></p><p><b> 表3-9閱讀表</b></p><p> 4 界面描述和代碼實(shí)現(xiàn)</p><p><b> 4.1 用戶管理</b></p&
20、gt;<p> 用戶管理模塊主要包括用戶注冊(cè)、登錄及信息修改。</p><p> 用戶注冊(cè):用戶填寫(xiě)注冊(cè)信息并通過(guò)校驗(yàn)后可以成功注冊(cè)成為會(huì)員,其中郵箱作為登錄名,不能重復(fù)。</p><p> 圖4-1 用戶注冊(cè)頁(yè)面</p><p> 以Ajax的方式進(jìn)行注冊(cè)校驗(yàn),成功后方才跳轉(zhuǎn)頁(yè)面,如果出錯(cuò),則在不刷新的情況下在當(dāng)前頁(yè)面提示錯(cuò)誤信息。</
21、p><p> public String signup() throws Exception {</p><p> result = new HashMap<String, Object>();</p><p> Map<String, Object> errors = new HashMap<String, Object>()
22、;</p><p> // Validate email address</p><p> if (!ValidatorUtil.validEmail(user.getEmail())) {</p><p> errors.put("user.email", "郵箱格式不正確");</p><p>
23、; // If the email has been taken</p><p> } else if (userDao.findByEmail(user.getEmail()) != null) {</p><p> errors.put("user.email", "郵箱已經(jīng)被占用");</p><p><b&
24、gt; }</b></p><p> // Validate username</p><p> if (!ValidatorUtil.validUsername(user.getName())) {</p><p> errors.put("user.name", "用戶名格式不正確");</p&g
25、t;<p> // Validate password</p><p> if (!ValidatorUtil.validPassword(user.getPass()))</p><p> errors.put("user.pass", "密碼格式不正確");</p><p><b> }&l
26、t;/b></p><p> logger.info(String.format("signing up user[name=%s, email=%s]", </p><p> user.getName(), user.getEmail()));</p><p> // Add the user</p><p>
27、; if (!errors.isEmpty()) {</p><p> result.put("approved", false);</p><p> result.put("message", "注冊(cè)失敗,請(qǐng)檢查注冊(cè)信息是否填寫(xiě)正確");</p><p> result.put("err
28、ors", errors);</p><p> } else if (!userDao.insert(user)) {</p><p> result.put("approved", false);</p><p> result.put("message", "注冊(cè)失敗,服務(wù)器正忙,請(qǐng)稍后再試&qu
29、ot;);</p><p><b> } else {</b></p><p> result.put("approved", true);</p><p> result.put("message", "注冊(cè)成功,正在中轉(zhuǎn)頁(yè)面");</p><p>&l
30、t;b> }</b></p><p> return SUCCESS;</p><p><b> }</b></p><p> 用戶登錄:用戶填寫(xiě)登錄信息后點(diǎn)擊登錄,進(jìn)行Ajax校驗(yàn),成功后跳轉(zhuǎn)到個(gè)人頁(yè)面。</p><p> 圖4-2 用戶登錄頁(yè)面</p><p>
31、用戶登錄的前臺(tái)相關(guān)代碼:</p><p><b> /**</b></p><p> * Script to implement user related works, such as signin, signup, validation and..</p><p><b> *</b></p><
32、;p> * @author GreatGhoul</p><p> * @version 1.0 2010-04-25 22:35</p><p> * @require</p><p> * : jquery.1.3.2.min.js</p><p> * : status-1.0.3.js</p>&
33、lt;p><b> */</b></p><p> $(function() {</p><p> var signupForm = $('#signup-form');</p><p> var signinForm = $('#signin-form');</p><p>
34、; function signup() {</p><p><b> $.ajax({ </b></p><p> url: 'dosignup.do', </p><p> data: signupForm.serialize(), </p><p> type: 'POST'
35、, </p><p> dataType: 'json',</p><p> error: function() {</p><p> signupForm.lock(false, '注冊(cè)失敗,請(qǐng)檢查您的網(wǎng)絡(luò)連接');</p><p><b> },</b></p>
36、<p> success: function(data) {</p><p> signupForm.lock(false, data.result.message);</p><p> if (data.result.approved) {</p><p> setTimeout(function() {</p><p>
37、 window.location = 'signin.do';</p><p><b> }, 3000);</b></p><p><b> } else {</b></p><p> signupForm.errs(data.result.errors);</p><p>
38、;<b> }</b></p><p><b> }</b></p><p><b> });</b></p><p> signupForm.lock(true, '正在提交注冊(cè)信息...');</p><p> return false;</
39、p><p><b> }</b></p><p> function signin() {</p><p><b> $.ajax({ </b></p><p> url: 'dosignin.do', </p><p> data: signinFor
40、m.serialize(), </p><p> type: 'POST', </p><p> dataType: 'json',</p><p> error: function() {</p><p> signinForm.lock(false, '登錄失敗,請(qǐng)檢查您的網(wǎng)絡(luò)連接'
41、);</p><p><b> },</b></p><p> success: function(data) {</p><p> signinForm.lock(false, data.result.message);</p><p> if (data.result.approved) {</p>
42、;<p> setTimeout(function() {</p><p> window.location = 'home.do';</p><p><b> }, 1000);</b></p><p><b> }</b></p><p><b>
43、 }</b></p><p><b> });</b></p><p> signinForm.lock(true, '正在提交注冊(cè)信息...');</p><p> return false;</p><p><b> }</b></p><
44、;p> signupForm.submit(signup);</p><p> signinForm.submit(signin);</p><p><b> });</b></p><p> 用戶信息修改:提供原始密碼后,用戶可以修改昵稱或者使用新的密碼。</p><p> 圖4.3 用戶信息修改頁(yè)面&
45、lt;/p><p><b> 4.2 分類管理</b></p><p> 管理員有權(quán)利對(duì)系統(tǒng)的小說(shuō)分類管理,小說(shuō)的分類名不能重復(fù)。管理員可以添加分類、修改分類、刪除分類,要?jiǎng)h除含有小說(shuō)的分類,需要先轉(zhuǎn)移分類中的小說(shuō),否則不能成功刪除分類。</p><p> 圖4-4 分類管理頁(yè)面</p><p> 以下這段代碼用于更
46、新分類,用于返回更新信息的JSON格式的結(jié)構(gòu)是固定的,在書(shū)架,小說(shuō)管理中都遵循這一格式,統(tǒng)一了操作接口。</p><p> public String update() {</p><p> logger.info(String.format("updating cate[id=%d] ==> cate[name=%s]",</p><p&
47、gt; cate.getId(), cate.getName()));</p><p> result = new HashMap<String, Object>();</p><p> List<String> errors = new ArrayList<String>();</p><p> result.put(&
48、quot;approved", false);</p><p> result.put("message", "更新分類失敗");</p><p> if (cate == null || cate.getId() == null) {</p><p> errors.add("分類不存在"
49、);</p><p> } else if (!ValidatorUtil.validCateName(cate.getName())) {</p><p> errors.add("分類名的長(zhǎng)度應(yīng)該在1到20個(gè)字體之間,不能含有空格");</p><p><b> } else {</b></p>&l
50、t;p> Cate cate1 = cateDao.findById(cate.getId());</p><p> if (cate1 == null) {</p><p> errors.add("要修改的分類不存在");</p><p> } else if (cate1.getName().equals(cate.getNa
51、me())) {</p><p> errors.add("分類名已經(jīng)存在");</p><p> } else if (!cateDao.update(cate)) {</p><p> errors.add("服務(wù)器正忙,請(qǐng)稍候再試");</p><p><b> } else {
52、</b></p><p> result.put("approved", true);</p><p> result.put("message", "更新分類成功");</p><p><b> }</b></p><p><b>
53、 }</b></p><p> result.put("errors", errors);</p><p> return SUCCESS;</p><p><b> }</b></p><p><b> 4.3 書(shū)架管理</b></p>&l
54、t;p> 用戶登錄后可以創(chuàng)建書(shū)架,并可以編輯或刪除自己創(chuàng)建的書(shū)架。在“我的書(shū)架”頁(yè)面會(huì)羅列當(dāng)前用戶的所有書(shū)架,如圖:</p><p> 圖4-5 書(shū)架列表頁(yè)面</p><p> (1) 添加書(shū)架:點(diǎn)擊書(shū)架列表中的“添加書(shū)架”,可以打開(kāi)添加書(shū)架窗口,填寫(xiě)書(shū)架名稱后點(diǎn)擊確認(rèn)按鈕即可添加一個(gè)書(shū)架。</p><p><b> 圖4-6 添加書(shū)架<
55、;/b></p><p> (2) 修改書(shū)架:點(diǎn)擊要修改的書(shū)架名后面的“修改”即可打開(kāi)書(shū)架修改窗口,填寫(xiě)新的名稱后點(diǎn)擊確認(rèn)按鈕,即可修改書(shū)架的名稱。</p><p><b> 圖4-7 修改書(shū)架</b></p><p> (3) 刪除書(shū)架:點(diǎn)擊要?jiǎng)h除的書(shū)架后面的“刪除”會(huì)提示是否確認(rèn)刪除,如果點(diǎn)擊“是”,且書(shū)架中書(shū)架數(shù)為0,則可以成
56、功刪除書(shū)架,否則不會(huì)刪除書(shū)架。</p><p> 刪除書(shū)架的代碼如下:</p><p> public String delete() {</p><p> User user = (User) getSessionMap().get("curUser");</p><p> if (user == null) r
57、eturn "signin";</p><p> if (bookDao.findByShelf(shelf).size() > 0) {</p><p> addActionMessage("要?jiǎng)h除書(shū)架,請(qǐng)先清空書(shū)架中的小說(shuō)");</p><p> return ERROR;</p><p&g
58、t; } else if (!shelfDao.delete(shelf)) {</p><p> addActionMessage("刪除書(shū)架失敗,服務(wù)器正忙,請(qǐng)稍候再試。");</p><p> return ERROR;</p><p><b> } else {</b></p><p>
59、; return SUCCESS;</p><p><b> }</b></p><p><b> }</b></p><p><b> 4.4小說(shuō)管理</b></p><p> 用戶可以上傳小說(shuō),并對(duì)自己上傳的小說(shuō)進(jìn)行管理。在首頁(yè)、個(gè)人頁(yè)面、書(shū)架展示等頁(yè)面會(huì)羅列出用
60、戶上傳的小說(shuō),點(diǎn)擊即可查看詳情。</p><p> 網(wǎng)站的首頁(yè)會(huì)羅列出所有小說(shuō)分類,熱門(mén)的書(shū)架、小說(shuō)等,點(diǎn)擊鏈接即可查看相關(guān)條目。</p><p><b> 圖4-8 網(wǎng)站首頁(yè)</b></p><p> 個(gè)人頁(yè)面會(huì)羅列出用戶最近上傳的小說(shuō)和創(chuàng)建的所有書(shū)架。</p><p><b> 圖4-9 用戶首頁(yè)&
61、lt;/b></p><p> (1) 上傳小說(shuō):點(diǎn)擊頂端導(dǎo)航中的“上傳小說(shuō)”,在打開(kāi)的頁(yè)面中填寫(xiě)相關(guān)信息,并選定要上傳的文件(文件要求txt格式,小于5M,而且章節(jié)目錄比較標(biāo)準(zhǔn) )。其中小說(shuō)簡(jiǎn)介可以選填,如果用戶不填寫(xiě),則自動(dòng)以前6章的章節(jié)標(biāo)題拼接成簡(jiǎn)介。</p><p> 圖4-10 小說(shuō)上傳頁(yè)面</p><p> 上傳小說(shuō)的相關(guān)代碼:</p&
62、gt;<p> public String execute() throws IOException {</p><p> User user = (User) getSessionMap().get("curUser");</p><p> if (user == null) {</p><p> return "
63、;signin";</p><p><b> }</b></p><p> if (book.getAuthor() == null || book.getAuthor().trim().isEmpty()){</p><p> book.setAuthor("未知");</p><p
64、><b> }</b></p><p> if (book.getDesc() != null && book.getAuthor().length() > 200) {</p><p> book.setDesc(book.getDesc().substring(0, 199));</p><p><b
65、> }</b></p><p> if (upload == null || !upload.exists()) {</p><p> addActionMessage("只能上傳txt類型的文件,且文件不能超過(guò)5M。");</p><p> return ERROR;</p><p><b
66、> } else {</b></p><p> if (book.getName() == null || book.getName().trim().isEmpty()) {</p><p> addActionMessage("請(qǐng)?zhí)顚?xiě)小說(shuō)名稱");</p><p><b> }</b></
67、p><p> if (book.getShelf() == null) {</p><p> addActionMessage("請(qǐng)為小說(shuō)指定一個(gè)書(shū)架");</p><p><b> }</b></p><p> if (getActionMessages().isEmpty()) {</p
68、><p> String toPath = "/uploads/" + System.currentTimeMillis() + "-" + uploadFileName;</p><p> File toFile = new File(ServletActionContext.getServletContext()</p><p
69、> .getRealPath(toPath));</p><p> FileUtils.copyFile(upload, toFile);</p><p> book.setUploadFile(toPath);</p><p> book.setSize(toFile.length());</p><p><b>
70、 try {</b></p><p> BookParser.parseDetail(toFile, book);</p><p> } catch (IOException e) {</p><p> addActionMessage("未能生成索引");</p><p> book.setDetai
71、l("[]");</p><p><b> }</b></p><p> book.setUploadUser(user);</p><p> if (bookDao.insert(book)) {</p><p> cateDao.countBooks(book.getCate());<
72、;/p><p> shelfDao.countBooks(book.getShelf());</p><p> return SUCCESS;</p><p><b> } else {</b></p><p> addActionMessage("服務(wù)器錯(cuò)誤,上傳文件失敗");</p>
73、;<p> return ERROR;</p><p><b> }</b></p><p><b> } else {</b></p><p> return ERROR;</p><p><b> }</b></p><p>
74、<b> }</b></p><p><b> }</b></p><p> Struts2配置:</p><p> <action name="doBookUpload" class="bookUploadAction"></p><p>
75、; <interceptor-ref name="fileUpload"></p><p> <param name="maximumSize">5242880</param></p><p> <param name="allowedTypes">text/plain<
76、/param></p><p> </interceptor-ref></p><p> <interceptor-ref name="basicStack" /></p><p> <result name="signin" type="redirect">
77、signin.do</result></p><p> <result name="success">/WEB-INF/views/book-upload-success.jsp</result></p><p> <result name="error">/WEB-INF/views/error.
78、jsp</result></p><p><b> </action></b></p><p> 生成索引的相關(guān)代碼:</p><p> public static void parseDetail(File file, Book book) throws IOException {</p><
79、p> JSONArray detail = new JSONArray();</p><p> StringBuilder desc = new StringBuilder();</p><p> InputStreamReader istream = new InputStreamReader(new FileInputStream(file), "GBK"
80、;);</p><p> BufferedReader stream = new BufferedReader(istream);</p><p> //RandomAccessFile stream = new RandomAccessFile(file, "r");</p><p> int headLineNumber = 1,
81、tailLineNumber = 1; // 初始行號(hào)為1</p><p> int lineNumber = 0;</p><p> String chapterTitle = "前言";</p><p> String line = null;</p><p> int chapterCount = 0;<
82、;/p><p> while ((line = stream.readLine()) != null) {</p><p> lineNumber++;</p><p> if (line.matches(CHAPTER_RE)) {</p><p> if (chapterCount <= 6) {</p><
83、p> desc.append(line);</p><p> desc.append("\r\n");</p><p><b> }</b></p><p> chapterCount++;</p><p> tailLineNumber = lineNumber - 1;</p
84、><p> JSONObject chapter = new JSONObject();</p><p> chapter.put("title", chapterTitle);</p><p> chapter.put("head", headLineNumber);</p><p> chapt
85、er.put("tail", tailLineNumber);</p><p> detail.add(chapter);</p><p> chapterTitle = line;</p><p> headLineNumber = tailLineNumber;</p><p><b> }</
86、b></p><p><b> }</b></p><p> tailLineNumber = lineNumber;</p><p> JSONObject chapter = new JSONObject();</p><p> chapter.put("title", chapte
87、rTitle);</p><p> chapter.put("head", headLineNumber);</p><p> chapter.put("tail", tailLineNumber);</p><p> detail.add(chapter);</p><p> stream.c
88、lose();</p><p> istream.close();</p><p> book.setDetail(detail.toString());</p><p> if (book.getDesc() != null && book.getDesc().trim().isEmpty()) {</p><p>
89、 book.setDesc(desc.toString());</p><p><b> }</b></p><p><b> }</b></p><p> (2) 修改小說(shuō)信息:點(diǎn)擊書(shū)架展示頁(yè)面中小說(shuō)名稱后面的“修改”,即可跳轉(zhuǎn)到小說(shuō)信息修改頁(yè)面,可以重新填寫(xiě)小說(shuō)的名稱,作者,簡(jiǎn)介,分類及書(shū)架信息。</p&g
90、t;<p> 圖4-11 小說(shuō)修改頁(yè)面</p><p> (3) 小說(shuō)查看:點(diǎn)擊小說(shuō)名稱的鏈接可以打開(kāi)小說(shuō)查看頁(yè)面,在該頁(yè)面上可以看到小說(shuō)的基本信息和評(píng)論列表,在評(píng)論框中輸入評(píng)論后點(diǎn)擊提交可以發(fā)表評(píng)論。</p><p> 圖4-12小說(shuō)查看頁(yè)面</p><p> (3) 小說(shuō)閱讀:點(diǎn)擊小說(shuō)查看頁(yè)面的“閱讀小說(shuō)”鏈接可以打開(kāi)小說(shuō)閱讀器,如果是第一
91、次閱讀該小說(shuō),則會(huì)從第一章開(kāi)始閱讀,如果以前已經(jīng)閱讀過(guò)該小說(shuō),則會(huì)自動(dòng)載入上次閱讀的章節(jié)。</p><p> 圖4-13說(shuō)閱讀頁(yè)面</p><p> 后臺(tái)獲取章節(jié)內(nèi)容的相關(guān)代碼:</p><p> public static String getChapterDetail(File file, ReadDetail detail) throws IOExcep
92、tion {</p><p> InputStreamReader istream = new InputStreamReader(new FileInputStream(file), "GBK");</p><p> BufferedReader stream = new BufferedReader(istream);</p><p>
93、 int lineNumber = 0;</p><p> StringBuilder sb = new StringBuilder();</p><p> String line = null;</p><p> while ((line = stream.readLine()) != null) {</p><p> lineNu
94、mber++;</p><p> if (lineNumber >= detail.getHead() && lineNumber <= detail.getTail()) {</p><p> sb.append("<p>" + line + "</p>");</p><p
95、><b> }</b></p><p><b> }</b></p><p> stream.close();</p><p> istream.close();</p><p> return sb.toString();</p><p><b>
96、 }</b></p><p> 前臺(tái)載入閱讀頁(yè)面的相關(guān)代碼:</p><p> <script type="text/javascript"></p><p> function escapeXML(xml) {</p><p> var text = xml;</p>&l
97、t;p> text = text.replace(/</g, '<');</p><p> text = text.replace(/>/g, '>');</p><p> text = text.replace(/&/g, '&');</p><
98、p> text = text.replace(/\t/g, ' ');</p><p> text = text.replace(/\s/g, ' ');</p><p> return text;</p><p><b&
99、gt; }</b></p><p> function readChapter(chapter) {</p><p> Status.show('正在加載章節(jié) ' + chapter.title);</p><p><b> $.ajax({</b></p><p> url:
100、39;bookChapter.do',</p><p><b> data: {</b></p><p> 'book.id': ${book.id},</p><p> 'detail.title': chapter.title,</p><p> 'detail
101、.head': chapter.head,</p><p> 'detail.tail': chapter.tail</p><p><b> },</b></p><p> type: 'POST',</p><p> dataType: 'json',&
102、lt;/p><p> error: function() {</p><p> Status.show('讀取章節(jié)失敗,請(qǐng)檢查您的網(wǎng)絡(luò)連接');</p><p><b> },</b></p><p> success: function(data) {</p><p> S
103、tatus.show(data.result.message);</p><p> if (data.result.approved) {</p><p> $('#main-head').html(chapter.title);</p><p> $('#main-body').html(data.chapterContent
104、);</p><p><b> }</b></p><p><b> }</b></p><p><b> });</b></p><p><b> }</b></p><p> function showChpater(
105、node, head, tail) {</p><p> readChapter({</p><p> title: node.innerHTML,</p><p> head: head,</p><p> tail: tail</p><p><b> });</b></p&g
106、t;<p><b> }</b></p><p> $(function() {</p><p> // 在目錄中添加一個(gè)章節(jié)</p><p> function appendChapter(chapter) {</p><p> var chapterNode = document.create
107、Element('LI');</p><p> chapterNode.innerHTML = '<a href="#" '</p><p> + 'onclick="showChpater(this, ' + head + ', ' + tail + ')">&
108、#39; </p><p> + escapeXML(trim(chapter)) + '</a>';</p><p> menu.appendChild(chapterNode);</p><p><b> }</b></p><p> var chapterList = $(
109、9;#chapter-list');</p><p> var chapters = eval('(' + '${book.detail}' + ')');</p><p> var curChapter = eval('(' + '${read.detail==null?"null":
110、read.detail}' + ')')</p><p> // building chapters.</p><p> Status.show("正在生成章節(jié)列表...");</p><p> for (var i = 0; i < chapters.length; i++) {</p><
111、;p> var chapter = chapters[i];</p><p> chapterList.append($('<li><a href="javascript:;" onclick="showChpater(this, ' + chapter.head + ', ' + chapter.tail + ')
112、;">'</p><p> + escapeXML($.trim(chapter.title)) + '</a></li>'));</p><p><b> }</b></p><p> Status.hide();</p><p> if (!c
113、urChapter || !curChapter.title) {</p><p> curChapter = chapters[0];</p><p><b> }</b></p><p> readChapter(curChapter);</p><p> $('.font-ctrl').cl
114、ick(function() {</p><p> var mainBody = $('#main-body');</p><p> var fontSize = parseInt(mainBody.css('font-size'));</p><p> var action = $(this).html();</p>
115、;<p> switch (action) {</p><p> case 'A+':</p><p> fontSize++;</p><p><b> break;</b></p><p> case 'A-':</p><p> fo
116、ntSize--;</p><p><b> break;</b></p><p><b> case 'A':</b></p><p> fontSize = 16;</p><p><b> break;</b></p><p&g
117、t;<b> default:</b></p><p><b> }</b></p><p> if (fontSize < 12) fontSize = 12;</p><p> if (fontSize > 20) fontSize = 20;</p><p> mainB
118、ody.css('font-size', '' + fontSize + 'px');</p><p><b> });</b></p><p><b> });</b></p><p><b> </script></b></p
119、><p> (4) 刪除小說(shuō):點(diǎn)擊小說(shuō)列表中小說(shuō)后面的“刪除”會(huì)彈出小說(shuō)刪除確認(rèn)框,如果點(diǎn)擊是則會(huì)刪除該小說(shuō),刪除小說(shuō)會(huì)連帶刪除小說(shuō)的評(píng)論、閱讀記錄等信息。</p><p> 刪除小說(shuō)的相關(guān)代碼:</p><p> User user = (User) getSessionMap().get("curUser");</p><
120、;p> if (user == null) return "signin";</p><p> Book book1 = bookDao.findById(book.getId());</p><p> if (book1 == null) {</p><p> addActionMessage("該小說(shuō)可能已經(jīng)刪除了。&
121、quot;);</p><p><b> } else {</b></p><p> Cate cate = book1.getCate();</p><p> Shelf shelf = book1.getShelf();</p><p> if (!bookDao.delete(book)) {</p&
122、gt;<p> addActionMessage("刪除小說(shuō)錯(cuò)誤,服務(wù)器正忙,請(qǐng)稍后再試");</p><p><b> } else {</b></p><p> cateDao.countBooks(cate);</p><p> shelfDao.countBooks(shelf);</p&
123、gt;<p> return SUCCESS;</p><p><b> }</b></p><p><b> }</b></p><p> return ERROR;</p><p><b> }</b></p><p> 4
124、.5統(tǒng)一的錯(cuò)誤頁(yè)面</p><p> 站使用統(tǒng)一的錯(cuò)誤頁(yè)面展示出錯(cuò)信息,給用戶更好的使用體驗(yàn)。</p><p> 圖4-13說(shuō)閱讀頁(yè)面</p><p><b> 5 體 會(huì)</b></p><p> 通過(guò)本次畢業(yè)設(shè)計(jì),我對(duì)MVC結(jié)構(gòu)有了更深入的理解,對(duì)軟件工程方法有更客觀的認(rèn)識(shí),對(duì)Struts2、Spring、
125、Hibernate有了更進(jìn)一步的掌握??偨Y(jié)起來(lái)有以下幾點(diǎn):</p><p> 需求分析很重要。設(shè)計(jì)之初做了全面的需求分析,對(duì)應(yīng)用的功能進(jìn)行了完整的分析,但是因?yàn)闆](méi)有考慮時(shí)間問(wèn)題,導(dǎo)致許多需要都沒(méi)有實(shí)現(xiàn),需求是個(gè)無(wú)底洞,以后做設(shè)計(jì)時(shí),我一定綜合開(kāi)發(fā)成本確認(rèn)需求方案。</p><p> 功能考慮不夠全面。在做軟件功能設(shè)計(jì)時(shí),因?yàn)槿狈﹂_(kāi)發(fā)經(jīng)驗(yàn),許多細(xì)節(jié)都沒(méi)有關(guān)注到,比如用戶注冊(cè)的確認(rèn)問(wèn)題,看
126、著雖然是個(gè)不怎么上進(jìn)心眼的功能,但一旦出錯(cuò),直接關(guān)系一個(gè)用戶的去留,我沒(méi)有在這方面下功夫,是不正確的。</p><p> 單元測(cè)試:因?yàn)闀r(shí)間緊迫,我并沒(méi)有對(duì)各位模塊進(jìn)行完整的單元測(cè)試,雖然真初有進(jìn)行過(guò)一些嘗試,但最后還是放棄了,這必然對(duì)系統(tǒng)埋下了隱患。使得我面對(duì)一些恑異的錯(cuò)誤時(shí),變得手足無(wú)措,浪費(fèi)了一些不必要的時(shí)間?;仡櫰饋?lái),還是因?yàn)殚_(kāi)發(fā)計(jì)劃混亂所至,如果起初就制定嚴(yán)格的開(kāi)發(fā)計(jì)劃,并貫徹實(shí)施,就不會(huì)在這方面栽跟
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 課程設(shè)計(jì)說(shuō)明書(shū)
- 課程設(shè)計(jì)說(shuō)明書(shū)
- 前門(mén)課程設(shè)計(jì)說(shuō)明書(shū)
- javaweb課程設(shè)計(jì)說(shuō)明書(shū)
- 后蓋課程設(shè)計(jì)說(shuō)明書(shū)
- 鍋爐課程設(shè)計(jì)說(shuō)明書(shū)
- 空調(diào)課程設(shè)計(jì)說(shuō)明書(shū)
- 蝸輪課程設(shè)計(jì)說(shuō)明書(shū)
- 采礦課程設(shè)計(jì)說(shuō)明書(shū)
- 機(jī)床課程設(shè)計(jì)說(shuō)明書(shū)
- caxa課程設(shè)計(jì)說(shuō)明書(shū)
- 化工課程設(shè)計(jì)說(shuō)明書(shū)
- vb課程設(shè)計(jì)說(shuō)明書(shū)
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
- 課程設(shè)計(jì)說(shuō)明書(shū).doc
評(píng)論
0/150
提交評(píng)論