javaweb项目连接MySQL数据库_php实现评论回复功能

javaweb项目连接MySQL数据库_php实现评论回复功能Java+MySQL实现评论功能设计开发一、背景项目初始版本上线,有时间写点东西记录一下项目中的心得体会,通过这个项目学习了很多,要写下来的有很多,先从评论功能开始吧。由于项目需要增加评论功能,之前并无此方面的经验,因此项目开始的一段时间都在寻思着如何进行评论功能的设计。上网搜索一波…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

                                                Java+MySQL实现评论功能设计开发

一、背景

      项目初始版本上线,有时间写点东西记录一下项目中的心得体会,通过这个项目学习了很多,要写下来的有很多,先从评论功能开始吧。由于项目需要增加评论功能,之前并无此方面的经验,因此项目开始的一段时间都在寻思着如何进行评论功能的设计。上网搜索一波发现有很多优秀的第三方评论插件可以使用,本来准备直接采用的,但是心里始终有点疙瘩,可能是评论数据放在别人那里不放心的原因,或可能是想一探这些评论系统的究竟,因此最终决定自行设计开发这么一套评论功能。效果截图如下所示,采用的是MySQL数据库,编程语言用的Java。(更多内容,可参阅程序员在旅途)

javaweb项目连接MySQL数据库_php实现评论回复功能

二、评论系统的概述:

       评论功能是用户表达对某一主题的想法的很好的一种方式,优秀的评论系统能很好地提高社区的活跃度。各大主流网站也都提供了相应的评论支持。比如:贴吧,新闻类门户网站(APP),UC浏览器等等。

      各大网站侧重点不同,对评论功能的要求就不一样,设计出来的评论系统自然就不一样。可能会有:①只可以进行评论,不可以回复,②既可以进行评论,也可以进行回复,然后在这个基础上可能会增加一些额外的功能,比如评论的折叠,审核,优选等。另外,一个良好的UI显示也是非常重要的,能给用户一个直观的视觉上的体验也是评论功能不可或缺的一个要素,毕竟用户都是具有很强的审美能力的,用户的使用体验决定了项目的需求。

      对于本项目,设计的是,既可以评论,也可以进行回复,评论和回复分开存储。在显示上,评论和回复显示的位置不同,回复相较于评论向右靠一些,这样,看起来比较舒适,当然也可以设置成其他的样式。评论会显示评论者头像,回复不会。

      评论的管理:后台系统应该具备基本的评论管理功能,比如:删除,折叠,优选,排序。这些功能的实现依赖于数据库表的设计,所以,在开始设计的时候,要想清楚自己的项目需要哪些功能。

三、数据库表的设计:

     本评论功能采用评论和回复分离的方式进行存储,一共设计了两张表,一张用户评论表(comment),一张针对评论的回复表(comment_reply)。评论表主要保存对文章或者回答的评论,回复表保存对每一条评论的回复。

      评论表(comment)如下图:主要包括了:评论ID(作为回复表的主键),回答(文章)ID,评论者ID,评论内容,点赞数,评论时间,审核状态

javaweb项目连接MySQL数据库_php实现评论回复功能

     评论回复表(comment_reply)如下图:主要包括了:评论ID,用户ID,被回复人ID,回复内容,点赞数,回复时间。

javaweb项目连接MySQL数据库_php实现评论回复功能

      两张表通过comment_id联系起来(并没有设置主外键,主要是不想维护起来太麻烦),获取某一答案的评论及回复步骤:根据answer_id找到所有的评论,然后,遍历所有的评论,根据comment_id查询到所有的回复(评论者的基本信息,例如头像,名称等需要额外查询)。需要注意的是,在评论和回复数据较多的情况下做好分页处理。

四、程序的实现: 

      采用Java语言进行编程的实现,使用的SSM框架。主要的功能代码如下所示(因为项目有通知功能,看的时候可以略过这部分,跟单纯的评论功能没有太大关系,但是一般要有通知,后面有时间会写站内通知的设计与开发博客):

   4.1 添加评论代码如下:(获取到评论相关的参数,然后进行向数据库表插入)

public int addComment(Comment comment) {
	try {
		Answer commentAnswer = answerMapper.selectByPrimaryKey(comment.getAnswerId());
		Long commentId = IDUtils.genItemId();//评论ID
		Date createtime = new Date();
		//1,填补comment对象的其他参数,进行插入
		comment.setCommentId(commentId);
		comment.setState(1);//状态: 0 待审核,1通过,2不通过
		comment.setPraseCount(0);//一开始插入的点赞数设置为0
		comment.setCreatetime(createtime);
		comment.setUpdatetime(createtime);
		commentMapper.insert(comment);//插入comment记录
		//2,跟新Answer的相关一条数据,提示评论数+1
		commentAnswer.setCommentNum((commentAnswer.getCommentNum()==null?0:commentAnswer.getCommentNum()) + 1);
		answerMapper.updateByPrimaryKeySelective(commentAnswer);
		//3,向提醒表插一条数据。这条评论是发给谁的,通知表里面的userId就是谁
		if (comment.getUserId() != commentAnswer.getUserId()) { //自己评论自己不会有通知
			Remind remind = new Remind();
			remind.setRemindId(commentId);
			remind.setUserId(commentAnswer.getUserId());
			remind.setFromUserId(comment.getUserId());
			//commentType:1评论回答,2评论别人的评论,3关注,4支持,5反对,6添加回答
			remind.setRemindType(1);
			//已读:0否,1是
			remind.setReadStatus(0);//否
			remind.setCreatetime(createtime);
			//插入通知内容,以json的形式存储
			RemindContent remindComment = new RemindContent();
			remindComment.setContentId(commentAnswer.getAnswerId());
			remind.setContent(JsonUtils.objectToJson(remindComment));//通知内容。回答问题的Id
			remindMapper.insert(remind);
		}
		//返回1代表成功
		return 1;
	} catch (Exception e) {
		e.printStackTrace();
		return 2;
	}
}

 4.2 添加回复代码:(前台会传来评论的ID,然后,封装成回复对象进行插入,一个评论ID会对应很多回复)

public int addCommentReply(CommentReply commentReply) {
    Long commentId = IDUtils.genItemId();//评论ID
    Date createtime = new Date();
	commentReply.setPraseCount(0);
	commentReply.setCreatetime(createtime);
	int retVal = commentReplyMapper.insert(commentReply);
	  
    //3,向提醒表插一条数据。这条评论是发给谁的,通知表里面的userId就是谁
	if (commentReply.getReplyuserId() != commentReply.getUserId()) {
	    Remind remind = new Remind();
		remind.setRemindId(commentId);
	    remind.setUserId(commentReply.getReplyuserId());
		remind.setFromUserId(commentReply.getUserId());
		//commentType:1评论回答,2评论别人的评论,3关注,4支持,5反对,6添加回答
		remind.setRemindType(2);
		//已读:0是,1否
		remind.setReadStatus(1);
		remind.setCreatetime(createtime);
		remind.setContent(commentReply.getCommentId()+"");
		remindMapper.insert(remind);
	}
	return retVal;
}

 4.3获取某一回答的评论和回复(评论分页返回,但是回复没有分页,后面会优化,使用的是pagehelper插件):

public PageBean<CommentStatus> listAnswerComments(Long answerId,Integer pageNum,Integer pageSize) {
try {
	CommentExample commentExample = new CommentExample();
	commentExample.setOrderByClause("createtime DESC");
	Criteria commentCriteria = commentExample.createCriteria();
	commentCriteria.andAnswerIdEqualTo(answerId);
	PageHelper.startPage(pageNum, pageSize);
	List<Comment> commentList = commentMapper.selectByExampleWithBLOBs(commentExample);//获取具有分页结果的评论数据
	List<CommentStatus> commentStatusList = new ArrayList<>();
	for (Comment comment : commentList) {
		CommentStatus commentStatus = new CommentStatus(); //评论返回的具体对象
			
		CommentReplyExample example = new CommentReplyExample();
		com.pn.mini.model.CommentReplyExample.Criteria criteria = example.createCriteria();
		criteria.andCommentIdEqualTo(comment.getCommentId());
		List<CommentReply> commentReplyList = commentReplyMapper.selectByExample(example);
		List<CommentReplyStatus> commentReplyStatusList = new ArrayList<>();
		for (CommentReply commentReply2 : commentReplyList) {
			UserBaseInfo commentUser = userBaseInfoMapper.selectByPrimaryKey(commentReply2.getUserId());
			UserBaseInfo commentReplyUser = userBaseInfoMapper.selectByPrimaryKey(commentReply2.getReplyuserId());
			CommentReplyStatus commentReplyStatus = new CommentReplyStatus();
			commentReplyStatus.setCommentId(commentReply2.getCommentId());
			commentReplyStatus.setContent(commentReply2.getContent());
			commentReplyStatus.setCreatetime(commentReply2.getCreatetime());
			commentReplyStatus.setPraseCount(commentReply2.getPraseCount());
			commentReplyStatus.setReplyuserId(commentReply2.getReplyuserId());
			commentReplyStatus.setReplyuserName(commentReplyUser.getUserName());
			commentReplyStatus.setUserId(commentUser.getUserId());
			commentReplyStatus.setUserName(commentUser.getUserName());
			commentReplyStatusList.add(commentReplyStatus);
		}
		UserBaseInfo commentUserBaseInfo = userBaseInfoMapper.selectByPrimaryKey(comment.getUserId());
		CommentIntegrate commentIntegrate = new CommentIntegrate();
		commentIntegrate.setAnswerId(comment.getAnswerId());
		commentIntegrate.setAvatar(commentUserBaseInfo.getAvatar());
		commentIntegrate.setCommentId(comment.getCommentId());
		commentIntegrate.setContent(comment.getContent());
		commentIntegrate.setCreatetime(comment.getCreatetime());
		commentIntegrate.setPraseCount(comment.getPraseCount());
		commentIntegrate.setState(comment.getState());
		commentIntegrate.setUpdatetime(comment.getUpdatetime());
		commentIntegrate.setUserId(comment.getUserId());
		commentIntegrate.setUserName(commentUserBaseInfo.getUserName());
		//拼接一条评论的返回对象
		commentStatus.setCommentIntegrate(commentIntegrate);
		commentStatus.setCommentReplyStatusList(commentReplyStatusList);
		commentStatusList.add(commentStatus);
	}
	PageBean<CommentStatus> recCommentItemBean = null;//接口返回的对象
	PageInfo<Comment> pageInfo = new PageInfo<>(commentList);
	recCommentItemBean = new PageBean<>(commentStatusList);
	recCommentItemBean.setDataList(commentStatusList);
	recCommentItemBean.setPageNum(pageInfo.getPageNum());
	recCommentItemBean.setPages(pageInfo.getPages());
	recCommentItemBean.setPageSize(pageInfo.getPageSize());
	recCommentItemBean.setSize(pageInfo.getSize());		 
    recCommentItemBean.setTotal(pageInfo.getTotal());
	return recCommentItemBean;
			
	} catch (Exception e) {
		e.printStackTrace(); //出现异常返回null,controller根据此判断此处调用是否成功
		return null;
	}	
}

 4.4  优化思考:

   ① 回复没有分页返回,回复数据量大的时候需要分页,在在获取回复的时候分页一下即可。

   ② 获取一条信息,需要再去查询用户表,获取用户的信息,这样就会导致获取一条回答的评论和回复需要查询N次数据表,思考的是增加冗余字段(用户名,用户头像),然后减少这方面的查询开销,当用户头像和名称更改的时候,同步更改这里面的数据,但是一般用户的这方面信息更改较少,总的来说,增加这个冗余字段还是能很大程度提高效率的。

  ③优化后的数据库表如下(忽略hot_value这样的字段,不同项目有不同需求):

javaweb项目连接MySQL数据库_php实现评论回复功能

javaweb项目连接MySQL数据库_php实现评论回复功能

五:总结与反思(后续优化的方向):

       虽然评论功能开发完毕,在目前也可以正常的使用,待使用程序的用户的增加,流量的扩大后仍需要继续优化,不然在用户的使用体验上可能会很糟糕,尤其是当数据量大的时候,用户访问可能会感觉到有些慢。不足之处其一:在于获取评论的回复,每次读取数据的时候,需要遍历每一条评论,然后去查找这个评论下的所有回复,之后返回这些数据,这样就会造成获取一片文章的评论需要多次查找数据库,效率就会很低,下一步准备从数据库设计和程序实现两个方面去思考如何优化;其二在于:所有文章的评论都在一张表里面,评论的回复也都在一张表里面,这样就会导致表的条目很多,下一步优化的思路集中于分表操作,具体的实现还在思考中。。。。

     评论功能的设计还有很多需要优化的地方,欢迎对这方面有了解的小伙伴一起交流。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187200.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 计算机硬件基础知识点

    sailan1.计算机的组成控制器运算器存储器输入设备输出设备2.CPU基础三大核心组件CPU的工作流程x86架构64位内核态与用户态多线程与多核三、存储器RAMROMCMOS硬盘1.计算机的组成控制器计算机的指挥系统,指挥计算机所有组件的工作;运算器计算机的运算系统,负责运算数学运算逻辑运算等;存储器计算机的记忆功能,负责数据的存取,分主存储器与辅存储器(又称内存,外存);内存:如内存条,基于电工作存储速度快,断电数据丢失,临时存储;外存:如硬盘,光盘,存取速度慢,断电数据不丢失,

    2022年4月7日
    35
  • ASP.NET 如何获得文件夹大小

    ASP.NET 如何获得文件夹大小例如可以用以下方法:其中参数path所传递的值是所要查看的文件夹的绝对路径!首先要导入System.IOC#//获取某个文件夹的大小public static long getDirectorySize(string path)  {  DirectoryInfo dirInfo=new DirectoryInfo(path);  long sumS

    2022年7月15日
    16
  • 扩展kmp求最长回文子串_算法-字符串之最长回文子串

    扩展kmp求最长回文子串_算法-字符串之最长回文子串上一篇KMP算法之后好几天都没有更新,今天介绍最长回文子串。首先介绍一下什么叫回文串,就是正着读和倒着读的字符顺序都是一样的,eg:level,noon。而回文子串,顾名思义,就是主串中满足回文性质的子串。求解的常规思想,就是先求出主串的所有子串,在判断是否是回文串,然后选出最长的,这一种方法的时候复杂度较高,是O(n^3),所以一般不采用这种方法,下面介绍两种方法求解。1.中心扩展法中心扩展法…

    2022年5月6日
    36
  • gbase导出sql_gbase修改字段名称

    gbase导出sql_gbase修改字段名称喵了个咪的。到目前为止,自己已经用过SQLSERVER,MySQL,Oracle,SQLite,加上南大通用GBASE五种数据库了。虽然每种都用的不深注:GBASE提供了C的API,查看手册即可。不支持string。用C++配置GBASE:对方提供了32位和64位windows下的库。在程序中添加gbase.herrmsg.h两个头文件,导入gbaseclient.liblibgb…

    2025年6月19日
    2
  • pycharm的字体设置_pycharm怎么设置字体

    pycharm的字体设置_pycharm怎么设置字体设置的路径是File->settings->Editor->FileandCodeTemplates->PythonScript再来看下效果:设置OK

    2022年8月29日
    2
  • 新安装idea,需要设置好的几个地方。

    设置编码格式。 设置maven。 如果不设置,那之前下载的jar包还得重新下载。 设置快捷键。 我使用eclipse的快捷键。 设置主题。 设置字体。 设置JDK. 未完待续。。。。。。

    2022年3月13日
    70

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号