前言:學習了Spring、SpringMVC、MyBatis框架后,開發了一套簡單的問答社區,前端采用Bootstrap開發框架。
版本信息
IDEA:2020.1.2
JDK:14.0.1
Maven:3.6.3
Tomcat:9.0.36
MySql:8.0.20
Bootstrap:3.3.7
JQuery:3.5.1
本文目錄
一、需求分析
1、社區功能
2、數據表
3、數據表關系
二、功能實現
1、用戶注冊、登錄、注銷
七、GitHub項目地址
一、需求分析
1、社區功能
①用戶注冊、登錄、注銷;
②提出問題、修改問題、刪除問題;
③對問題進行回答、修改回答、刪除回答;
④對回答進行評論、修改評論、刪除評論;
⑤用戶關注(取消關注)用戶、用戶關注(取消關注)問題,用戶贊同(取消贊同)回答。
(1)用戶表
用戶表 | |
---|---|
user_id | 用戶編號 |
user_name | 用戶名 |
user_nickname | 用戶昵稱 |
user_avatar | 用戶頭像 |
user_sex | 用戶性別 |
user_email | 用戶郵箱 |
user_password | 用戶密碼 |
user_register_time | 用戶注冊時間 |
user_last_login_time | 用戶最近一次登錄的時間 |
user_last_login_ip | 用戶最近一次登錄的IP地址 |
user_status |
(2)問題表
問題表 | 外鍵 | |
---|---|---|
question_id | 問題編號 | |
question_user_id | 問題的提問者用戶編號(關聯用戶表) | user表user_id |
question_title | 問題標題 | |
question_content | 問題內容 | |
question_view_count | 問題瀏覽量 | |
question_follow_count | 問題關注量 | |
question_answer_count | 問題回答量 | |
question_update_time | 問題更新時間 | |
question_create_time | 問題創建時間 | |
question_status | 問題狀態 |
(3)回答表
answer | 回答表 | 外鍵 |
---|---|---|
answer_id | 回答編號 | |
answer_user_id | 回答的回答者用戶編號(關聯用戶表) | user表user_id |
answer_question_id | 回答所對應的問題編號(關聯問題表) | question表question_id |
answer_content | 回答內容 | |
answer_view_count | 回答瀏覽量 | |
answer_agree_count | 回答贊同量 | |
answer_update_time | 回答更新時間 | |
answer_create_time | 回答創建時間 | |
answer_status | 回答狀態 |
(4)評論表
comment | 評論表 | 外鍵/備注 |
---|---|---|
comment_id | 評論編號 | |
comment_user_id | 評論的評論者用戶編號(關聯用戶表) | user表user_id |
comment_answer_id | 評論所對應的回答編號(關聯回答表) | answer表answer_id |
comment_last_id | 評論上一條評論編號 | 為Null表示一級評論,否則為二級及以上評論(對評論的評論) |
comment_content | 評論內容 | |
comment_time | 評論時間 |
comment_last_id本打算用作辨別回答下的一級評論(對回答的評論)和二級及以下評論(即對評論進行回復的評論),但感覺過於復雜,所有目前並未使用該字段。
(5)用戶與用戶關系表
user_relation_user | 用戶關注用戶關系表 | 外鍵 |
---|---|---|
from_user_id | 發起用戶編號 | user表user_id |
to_user_id | 關注用戶編號 | user表user_id |
(6)用戶與問題關系表
user_relation_question | 用戶關注問題關系表 | 外鍵 |
---|---|---|
from_user_id | 發起用戶編號 | user表user_id |
to_question_id | 關注問題編號 | question表question_id |
(7)用戶與回答關系表
user_relation_answer | 用戶與回答關系表 | 外鍵 |
---|---|---|
from_user_id | 發起用戶編號 | user表user_id |
to_answer_id | 贊同回答編號 | answer表answer_id |
3、數據表關系
(2)user表、question表、answer表、user_relation_user表、user_relation_question表、user_relation_answer表之間的關系
(3)由於有外鍵約束
②當刪除問題時,user_relation_question表的用戶關系會刪除,question表、answer表也會刪除問題及回答;
③當刪除回答時,user_relation_answer表的用戶關系會刪除,answer表、comment表也會刪除回答及評論。
二、功能實現
1、用戶注冊、登錄、注銷
①用戶注冊時,查找數據庫中是否已經存在注冊的用戶名,如果不存在,則將用戶填入的注冊信息,以及設置當前時間為用戶注冊時間、最近一次登錄時間,存入數據庫;
②用戶登錄時,首先前端先進行限制數據的輸入格式,密碼與確認密碼相同,進入后端查找數據庫中是否存在該用戶,不存在則顯示用戶名不存在。若存在該用戶名,再將密碼和數據庫中密碼進行匹配,匹配成功則登錄成功,反之失敗;
③用戶登錄后,可點擊注銷按鈕,根據存入session域中的登錄用戶編號刪除數據庫中用戶。
注意:記錄最近一次登錄IP功能還未實現,user_last_login_ip一直默認為null。user_status用來判斷用戶狀態或身份,比如1為普通用戶,0為管理員,2為禁用等,目前未開通這些功能,一直默認user_status=1。
2、提出問題、修改問題、刪除問題
①提出問題,根據session域中的登錄用戶編號及輸入的問題信息,以及設置當前時間為問題創建時間、更新時間,存入數據庫;
②修改問題,根據問題編號查出數據庫中的該問題信息,根據輸入修改問題信息,以及設置當前時間為問題更新時間,再存入數據庫;
③刪除問題,根據問題編號刪除數據庫中的問題。
3、對問題進行回答、修改回答、刪除回答
①進行回答,根據登錄用戶編號、問題編號、輸入的回答信息,以及設置當前時間為回答創建時間、更新時間,存入數據庫;
②修改回答,根據回答編號查出數據庫中的該回答信息,根據輸入修改回答信息,以及設置當前時間為回答更新時間,再存入數據庫;
③刪除回答,根據回答編號刪除數據庫中的回答。
4、對回答進行評論、修改評論、刪除評論
①進行評論,根據登錄用戶編號、回答編號、輸入的評論信息,以及設置當前時間為評論時間,存入數據庫;
②修改評論,根據評論編號查出數據庫中的該評論信息,根據輸入修改評論信息,以及設置當前時間為評論時間,再存入數據庫;
③刪除評論,根據評論編號刪除數據庫中的評論。
注意:評論時間及最新的評論時間,修改后立即更新時間,查看不到首次評論時間。
5、用戶關注(取消關注)用戶、用戶關注(取消關注)問題,用戶贊同(取消贊同)回答
①用戶關注用戶、問題,用戶贊同回答,首先查詢數據庫中是否存在對應關系,如果有則提示關注(贊同)失敗,如果沒有則將關系存入數據庫;
②用戶取消關注用戶、問題,用戶取消贊同回答,首先查詢數據庫中是否存在對應關系,如果有則提示取消關注(贊同)成功,如果有則將數據庫中的對應關系刪除。
三、代碼介紹
2、部分代碼
(2)dao層
java
xml
(3)service層
接口
實現類
(6)前端
JavaScript
HTML
四、效果演示
在頁面可以關注、取消關注問題,僅展示關注問題
①點擊關注,如果已經關注,彈出“您已經關注該問題,不能重復關注”,如果沒關注,彈出“關注成功”
關注成功
在此頁面可以贊同及取消贊同該回答,其顯示效果與關注與取消關注問題類型類似,故不展示
9、用戶信息(在問題及回答頁面可點擊問題標題右下側名字鏈接,在回答及評論頁面可點擊回答或評論者的名字鏈接,進入用戶詳情信息頁面)
以上圖的回答及評論頁面為例,點擊評論者周伯通
此頁面可點擊修改用戶信息
輸入框內容默認為用戶信息,用戶名不可更改,修改成功會返回個人頁面
注銷用戶會刪除數據庫內用戶信息,直接退出到登錄頁面,此處不再展示
①關注的用戶
②贊同的回答
③提出的問題
④做出的評論
12、修改、刪除問題,修改、刪除回答,修改、刪除評論
可在用戶頁面“提出的問題”、“做出的回答”、“做出的評論”鏈接進入后的頁面點擊問題標題、回答內容、評論內容鏈接進入對應信息頁面,然后對其進行修改、刪除,此處僅以做出的回答舉例
①用戶頁面,點擊做出的回答鏈接
②進入回答頁面,點擊回答內容的鏈接
③進入回答詳細頁面,點擊修改回答按鈕
④進入修改回答頁面,顯示原回答內容
1、question表可不需要question_answer_count字段,直接從answer表查詢某問題下有多少回答即可,本項目因為多次需要查詢問題時顯示問題有多少評論量,故也作為一個屬性。但因為question表內question_answer_count值在新增answer時加1,在刪除answer時減1,此過程在service層實現,如果直接對數據庫操作,question表的question_answer_count字段的值可能不正確;
2、對問題、回答、評論等進行新增、更新、刪除時有時會進入一個成功或失敗提示頁面,可以進行代碼優化讓其直接返回之前的信息頁面,然后進行彈窗提示成功或失敗信息,不需要單獨進入一個提示頁面;
3、user表的user_avtar(用戶頭像)、user_last_login_ip(用戶最近一次登錄的IP地址)、user_status(用戶狀態)等字段並未使用,可以在后續開發中加上這些字段對應的功能;
4、comment表中的comment_last_id字段表示評論的上一條評論編號,利用該字段可以實現對評論進行評論, 此目的主要是想實現回復功能,考慮到有些復雜本項目並未實現此功能
六、開發經驗
在開發過程中,熟悉了許多過程,也在一些細節的地方浪費了許多時間,經過不斷學習測試得出了一些經驗,現挑一些印象深刻的進行歸納
1、Dao層的類的方法傳入參數為多個時,需要用到@Parma
比如對user_relation_user表進行新增某用戶關注某用戶時,對應的UserRelationDao的類的方法為
1 void saveUserFollowUser(Integer from_user_id,Integer to_user_id);
UserRelationMapper.xml對應的xml語句
1 <!-- 新增某用戶關注某用戶 --> 2 <insert id="saveUserFollowUser" parameterType="java.lang.Integer" > 3 INSERT INTO user_relation_user (from_user_id,to_user_id) 4 VALUES (#{from_user_id},#{to_user_id}) 5 </insert>
此時會報錯,因為找不到from_user_id與to_user_id
1 void saveUserFollowUser(@Param("from_user_id") Integer from_user_id,@Param("to_user_id") Integer to_user_id);
2、JSP頁面發送url請求時要用<%=path%>加上后續路徑(JSP頭部加上<% String path = request.getContextPath();%>)
此處的內容關於JSP文件的絕對路徑與相對路徑,相關介紹網上已經很詳細了
1 <a href="Question/DisplayAllQuestionList"><button type="button" class="btn btn-success btn-lg" style="width: 150px;">查看所有問題</button></a>
對應的Controller類的方法為
1 /** 2 * 表現層 問題 3 */ 4 @Controller 5 @RequestMapping(value = "/Question") 6 public class QuestionController { 7 8 ······ 9 10 /** 11 * 進入所有問題列表頁面 12 * @param model 13 * @return 14 */ 15 @RequestMapping(value = "/DisplayAllQuestionList") 16 public String DisplayAllQuestionList(Model model) { 17 ...... 18 } 19 20 ······ 21 }
此時的請求可能會出錯,我在運行過程中出現了404的問題,如圖所示
此時修改為如下方式即可
1 <% String path = request.getContextPath();%> 2 3 ...... 4 5 <a href="<%=path%>/Question/DisplayAllQuestionList"><button type="button" class="btn btn-success btn-lg" style="width: 150px;">查看所有問題</button></a> 6 ·····
如果在java中用java.util.Date接收MySQL中的datetime,然后直接在JSP頁面顯示,會輸出以下格式
此時的代碼為
1 ······ 2 <td> 3 <p>${question.question_create_time}</p> 4 </td> 5 ······
使用Jstl語句的格式化輸出
1 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 2 3 ······ 4 5 <td> 6 <fmt:formatDate value="${question.question_create_time}" pattern="yyyy-MM-dd HH:mm:ss"/> 7 </td> 8 9 ······
此時會輸出以下格式
4、在之前發表過的隨筆有過以下總結
(1)@Controller類的方法如何解析ajax請求發送的請求體中的多個參數
https://www.cnblogs.com/huskysir/p/13295631.html
(2)關於在JSP頁面識別不了EL表達式的情況
https://www.cnblogs.com/huskysir/p/13283569.html
(3)JSP頁面中同時遍歷多個List集合
https://www.cnblogs.com/huskysir/p/13282191.html
(4)如何從默認的index.jsp頁面跳轉到其他頁面
https://www.cnblogs.com/huskysir/p/13273734.html
(5)SSM前后端信息交互
https://www.cnblogs.com/huskysir/p/13308418.html
七、GitHub項目地址
https://github.com/HuskySir/JAVA/tree/master/QA_Community