基于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、用户注册、登录、注销

2、提出问题、修改问题、删除问题

3、对问题进行回答、修改回答、删除回答

4、对回答进行评论、修改评论、删除评论

5、用户关注(取消关注)用户、用户关注(取消关注)问题、用户赞同(取消赞同)回答

三、代码介绍

1、项目结果

2、部分代码

四、效果演示

1、登录

2、注册

3、用户主页面

4、提出问题

5、查看所有问题

6、根据条件查询问题

7、问题及回答信息

8、回答及评论信息

9、用户信息

10、个人资料

11、关注的用户、粉丝、关注的问题、赞同的回答、提出的问题、做出的回答、做出的评论

12、修改、删除问题,修改、删除回答

五、代码/功能优化

六、开发经验

 

一、需求分析

1、社区功能

①用户注册、登录、注销;

②提出问题、修改问题、删除问题;

③对问题进行回答、修改回答、删除回答;

④对回答进行评论、修改评论、删除评论;

⑤用户关注(取消关注)用户、用户关注(取消关注)问题,用户赞同(取消赞同)回答。

2、数据表

(1)用户表

user 用户表
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 问题表 外键
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、数据表关系

(1)user表、question表、answer表、comment表之间的关系

(2)user表、question表、answer表、user_relation_user表、user_relation_question表、user_relation_answer表之间的关系

 

(3)由于有外键约束

①当删除用户时,user_relation_user表、user_relation_question表、user_relation_answer表的该用户关系均会删除,question表、answer表、comment表也会删除该用户的问题、回答及评论;

②当删除问题时,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、用户关注(取消关注)用户、用户关注(取消关注)问题,用户赞同(取消赞同)回答

①用户关注用户、问题,用户赞同回答,首先查询数据库中是否存在对应关系,如果有则提示关注(赞同)失败,如果没有则将关系存入数据库;

②用户取消关注用户、问题,用户取消赞同回答,首先查询数据库中是否存在对应关系,如果有则提示取消关注(赞同)成功,如果有则将数据库中的对应关系删除。

三、代码介绍

1、项目结构

 

2、部分代码

(1)实体类

(2)dao层

java

xml

(3)service层

接口

 

实现类

(4)controller层

 

(5)测试类

 

(6)前端

JavaScript

 

HTML

四、效果演示

1、登录

 

2、注册

3、用户主页面

4、提出问题

5、查看所有问题

6、根据条件查询问题

 

7、问题及回答信息(点击所有问题或者查询问题得到的页面的问题标题链接)

 

在页面可以关注、取消关注问题,仅展示关注问题

①点击关注,如果已经关注,弹出“您已经关注该问题,不能重复关注”,如果没关注,弹出“关注成功”

②点击取消关注,如果已经关注,弹出“取消关注成功”,如果没关注,弹出“您还未关注该问题,不可取消关注”

关注成功

关注失败

回答问题

8、回答及评论信息(点击问题及回答信息页面的回答的详细内容链接)

 

在此页面可以赞同及取消赞同该回答,其显示效果与关注与取消关注问题类型类似,故不展示

评论回答

9、用户信息(在问题及回答页面可点击问题标题右下侧名字链接,在回答及评论页面可点击回答或评论者的名字链接,进入用户详情信息页面)

以上图的回答及评论页面为例,点击评论者周伯通

在此页面可以关注或取消关注用户,与对问题和回答的操作同理,如果已经关注再点击关注、未关注点击取消关注会失败,未关注点击取消关注、已关注点击关注会失败

10、个人资料(在用户页面可进入个人资料)

 

此页面可点击修改用户信息

输入框内容默认为用户信息,用户名不可更改,修改成功会返回个人页面

注销用户会删除数据库内用户信息,直接退出到登录页面,此处不再展示

11、用户页面的个人资料及退出登录按钮下有7个链接,分别可进入对应页面,此处仅挑部分页面展示

①关注的用户

②赞同的回答

③提出的问题

④做出的评论

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

此时需要用到@Parma,修改后的UserRelationDao的类的方法为

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 ·····

3、在JSP页面显示时间的格式问题

如果在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="//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请求发送的请求体中的多个参数

//www.cnblogs.com/huskysir/p/13295631.html

(2)关于在JSP页面识别不了EL表达式的情况

//www.cnblogs.com/huskysir/p/13283569.html

(3)JSP页面中同时遍历多个List集合

//www.cnblogs.com/huskysir/p/13282191.html

(4)如何从默认的index.jsp页面跳转到其他页面

//www.cnblogs.com/huskysir/p/13273734.html

(5)SSM前后端信息交互

//www.cnblogs.com/huskysir/p/13308418.html

 七、GitHub代码地址

//github.com/HuskySir/JAVA

Tags: