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实现评论回复功能

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

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

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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • linux系统安装Memcache

    linux系统安装Memcache

  • 就业更看重本科学历还是研究生学历(大厂面试的员工什么水平)

    前言我是一个普通本科出身的Android程序员,我的学校也不过就是一个普通二本。嗯,我的学弟学妹们也是一样的,都是普通二本。但是和我不同的是,现在的社会越来越浮躁了,浮躁的让人沉不下心认真做事,让人忍不住去想各种有的没的。比如我的这些学弟学妹们。我已经不止一次收到来自他们的私信了,他们问的内容,无一不是表达对自己学历的自卑和对即将离开学校的自己的不自信,还有对面试被拒的伤心。千篇一律的问题,基本内容如下:面试挂了,大厂面试到底更看重学历还是技术?我这样的学历在求职中有什么需要注意点的点吗?

  • eclipse乱码解决

    eclipse乱码解决关于eclipse乱码解决网上好多解决之道,今天遇到了但是试了试怎么都不好使,原因是方法可以,只是不太详细参考网址:https://blog.csdn.net/YouAreMy_Sunshine/article/details/797597921.修改项目编码格式:  鼠标移到项目名,右键-&gt;Properties-&gt;Resource-&gt;TextfileenCodi…

  • 基于Lucene3.5.0如何从TokenStream获得Token

    基于Lucene3.5.0如何从TokenStream获得Token通过学习Lucene3.5.0的doc文档,对不同release版本lucene版本的API改动做分析。最后找到了有价值的改动信息。LUCENE-2302:DeprecatedTermAttributeandreplacedbyanewCharTermAttribute.Thechangeisbackwardscompatible,somixednew/old

  • matlab中如何求插值点,MATLAB插值「建议收藏」

    matlab中如何求插值点,MATLAB插值「建议收藏」4.5插值插值就是在已知数据之间计算估计值的过程,是一种实用的数值方法,是函数逼近的重要方法。在信号处理和图形分析中,插值运算的应用较为广泛,MATLAB提供了多种插值函数,可以满足不同的需求。4.5.1一维数据插值一维数据插值常使用函数interp1,其一般的语法格式为:yi=interp1(x,y,xi,method)。其中y为函数值矢量,x为自变量的取值范围,x与y的长度必须相同;x…

  • oracle隐式转换_oracle查看游标数量

    oracle隐式转换_oracle查看游标数量原文地址:http://blog.itpub.net/29324876/viewspace-1096741/1     Oracle 隐式转换Oracle中对不同类型的处理具有显式类型转换(Explicit)和隐式类型转换(Implicit)两种方式,对于显式类型转换,我们是可控的,但是对于隐式类型转换,当然不建议使用,因为很难控制,有不少缺点,但是我们很难避免

    2022年10月11日

发表回复

您的电子邮箱地址不会被公开。

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