基于SSM框架的简单问答社区
前言:学习了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