zoukankan      html  css  js  c++  java
  • 基于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、修改、删除问题,修改、删除回答

    五、代码/功能优化

    六、开发经验

    七、GitHub项目地址

     

    一、需求分析

    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=" 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=" 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="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/QuestionPlatform

  • 相关阅读:
    《sql必知必会》笔记
    HTTP抓包与调试(Firefox插件)
    软件测试方法和技术实践(学习笔记)
    java基础(一章)
    java基础(二章)
    final关键字(最终的)
    算术运算符与控制台输入
    eclipse自动补全的设置
    Java关于Properties用法的总结(一)
    使用Struts2标签遍历集合
  • 原文地址:https://www.cnblogs.com/huskysir/p/13308511.html
Copyright © 2011-2022 走看看