由于多说关闭,多说源码不开放,Java模仿多说评论系统实现(二)
先什么都不多说,先看看效果,高仿多说评论已经上线,估计还是有瑕疵,不断完善中。评论链接===> :https://www.sojson.com/other/duoshuo.html
昨天说到了 多说 ,然后简单分析了一个评论基本需求,基本的字段等等。
今天建表,初步把数据拉出来,当然功能不是很完善(后面会逐步把该有功能补上),目前实现了评论,回复评论,以及把原有的数据读取过来。下面看看简单效果图和功能。先看看数据结构,我用咱们网站的工具:https://www.sojson.com/simple_json.html 分析了下数据。
一、模拟多说评论表结构创建
主要三张表:
so_message:为评论表,所有评论都在这里,有自关联属性,为id和parent_id
so_message_like:为评论点赞(顶)表,一个authorId + 一个messageId为唯一性,也就是一条数据一个用户只能点赞一次。
so_message_author:为评论用户表,一个用户可以评论多个评论,和评论的关系是多对一的关系。
二、数据从多说同步(从多说导出的数据太烂)
多说有数据导出功能,但是导出后,我发现数据不全,而且阅读性差,加上我之前的评论不是太多,而且都是以链接为单位,所以我更偏向单个导出。
/**
* 从多说同步数据
* @param pkey 业务数据Key,其实就是URL
* @return
*/
@RequestMapping(value="synchMessage",method=RequestMethod.GET)
@ResponseBody
public Map<String,Object> synchMessage(String pkey){
Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
String urlKey = StringUtils.strToUrlcode(pkey);
//这是一个临时表,记录这条数据是否已经同步过了
Temp temp = tempService.selectTempByPkey(pkey);
if(null != temp ){
resultMap.put("status", 1);
resultMap.put("message", "不用再加载。");
return resultMap;
}
//这个就是一个普通的HTTP请求的封装
String result = new GetJSON("http://iqingxin.duoshuo.com/api/threads/listPosts.json?thread_key=" +urlKey +"&limit=1000")
.executeMethod(String.class);
//转换为JSON对象
JsonObject json = new Gson().fromJson(result, JsonObject.class);
int total = 0;
if(json.has("cursor")){
JsonObject cursor = json.getAsJsonObject("cursor");
if(null!= cursor && cursor.get("total").getAsInt() == 0 ){
total = cursor.get("total").getAsInt();
//添加标记为已经获取了记录。
tempService.insertTemp(new Temp(pkey, 0));
resultMap.put("status", 8);
resultMap.put("message", "已经完成。");
return resultMap;
}
}
//获取这一个层级即可,不需要再深的层级
JsonObject parentPosts = json.getAsJsonObject("parentPosts");
//json中数据条数
int size = parentPosts.entrySet().size();
//循环获取数据
Set<Entry<String,JsonElement>> keys = parentPosts.entrySet();
for (Entry<String,JsonElement> entry : keys) {
JsonObject jsonObj = entry.getValue().getAsJsonObject();
if(null == jsonObj.get("message") || jsonObj.get("message").isJsonNull()){
continue;
}
//获取message
String m = jsonObj.get("message").getAsString();
if("谢谢您的反馈,已经修改!".equals(m.trim())){
System.out.println(1);
}
//因为可能要执行多次,多说有BUG,有的时候不能获取所有数据
Long id = messageService.selectByMessageAndKey(new SOMessage().setPkey(pkey).setMessage(m));
if(null != id){
continue;
}
SOMessageAuthor messageAuthor = new SOMessageAuthor(jsonObj);
//用户信息
String nickname = messageAuthor.getNickname();
Long authorId = messageAuthorService.selectByNickname(nickname);
if(null == authorId){
messageAuthorService.insertSelective(messageAuthor);
authorId = messageAuthor.getId();
}
SOMessage message = new SOMessage(jsonObj,1/*1级*/,""/*父ID串*/,new Long(0)/*父ID*/,authorId);
message.setPkey(pkey);
messageService.insertSelective(message);
//获取子类。
JsonArray childeren = jsonObj.getAsJsonArray("children");
//存储子类数据,递归存储
exe(childeren, message, pkey, 2);
//添加标记为已经获取了记录。
if(size == total){
tempService.insertTemp(new Temp(pkey, size));
resultMap.put("status", 8);
resultMap.put("message", "已经完成。");
}
}
return resultMap;
}
/**
* 递归调用方法
* @param childeren 子类集合
* @param message 当前message对象
* @param key 评论数据key
* @param level 评论级别
*/
private void exe(JsonArray childeren,SOMessage message ,String key,Integer level){
if(null != childeren && childeren.isJsonArray() && childeren.size()>0 )
A:for (JsonElement jsonElement : childeren) {
JsonObject json = jsonElement.getAsJsonObject();
//如果没有数据,迭代下一条
if(null == json.get("message") || json.get("message").isJsonNull()){
continue A;
}
//获取message
String m = json.get("message").getAsString();
//因为可能要执行多次,多说有BUG,有的时候不能获取所有数据
Long id = messageService.selectByMessageAndKey(new SOMessage().setPkey(key).setMessage(m));
if(null != id){
continue;
}
Long pid = message.getParentId();
String pids = null;
//如果是一级,父ID为0
if(Constant.ZERO.equals(pid)){
pids = "," +message.getId()+"," ;
}else{
pids = message.getPids() +message.getId()+",";
}
//初始化对象
SOMessageAuthor messageAuthor = new SOMessageAuthor(json);
//用户信息
String nickname = messageAuthor.getNickname();
Long authorId = messageAuthorService.selectByNickname(nickname);
if(null == authorId){
messageAuthorService.insertSelective(messageAuthor);
authorId = messageAuthor.getId();
}
SOMessage message2 = new SOMessage(json,level,pids,message.getId()/*父ID*/,authorId);
message2 .setPkey(key);
//插入数据
messageService.insertSelective(message2);
//获取子类。
JsonArray cs = json.getAsJsonArray("children");
if(null != cs && cs.isJsonArray() && cs.size()>0 ){
//递归调用
exe(cs, message2, key, level+1);
}
}
}
三、评论实体(Entity)代码
so_message
的实体对象,包含一些业务数据转换,getter/setter
方法我就不贴出来。
/**
*
* 开发公司:SOJSON在线工具 <p>
* 版权所有:© www.sojson.com<p>
* 博客地址:https://www.sojson.com/blog/ <p>
* <p>
*
* 模拟多说评论实体
*
* <p>
*
* 区分 责任人 日期 说明<br/>
* 创建 周柏成 2017年5月2日 19:48 <br/>
*
* @author zhou-baicheng
* @email so@sojson.com
* @version 1.0,2017年5月2日 19:48 <br/>
*
*/
public class SOMessage implements Serializable{
private static final long serialVersionUID = 1434473283877857750L;
/**评论id**/
private Long id;
/**创建时间**/
private Date createdTime;
private String createdTimeStr;
private String createdYMDHMSStr;//年月日,时分秒全时间
private String createdTimeZooe;//年月日,时分秒全时间,带时区,如:2017-04-26T14:22:27+08:00
/**父类id**/
private Long parentId = Constant.ZERO;
/**顶的次数**/
private Integer likes = 0;
/**浏览器信息**/
private String agent;
/**ip**/
private String ip;
/**ip地址**/
private String iplocation;
/**评价人id**/
private Long authorId;
/**key**/
private String pkey;
/**评价来源**/
private String referer;
/**评价内容**/
private String message;
/**子父类关系id*/
private String pids;
/**层级ID*/
private Integer level;
public SOMessage(JsonObject jsonObj,Integer level,String pids,Long parentId,Long authorId) {
if(null != jsonObj.get("message") && !jsonObj.get("message").isJsonNull()){
this.message = jsonObj.get("message").getAsString();
}
this.authorId = authorId;
if(null != jsonObj.get("agent") && !jsonObj.get("agent").isJsonNull()){
this.agent = jsonObj.get("agent").getAsString();
}
if(null != jsonObj.get("likes") && !jsonObj.get("likes").isJsonNull()){
this.likes = jsonObj.get("likes").getAsInt();
}
if(null != jsonObj.get("ip") && !jsonObj.get("ip").isJsonNull()){
this.ip = jsonObj.get("ip").getAsString();
}
if(null != jsonObj.get("iplocation") && !jsonObj.get("iplocation").isJsonNull()){
this.iplocation = jsonObj.get("iplocation").getAsString();
}
if(null != jsonObj.get("created_at") && !jsonObj.get("created_at").isJsonNull()){
String createdTime = jsonObj.get("created_at").getAsString();
try {
//时间转换
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date date = df.parse(createdTime);
this.createdTime = date;
} catch (Exception e) {
this.createdTime = new Date();
}
}
this.level = level;
this.pids = pids;
this.parentId = parentId;
}
public SOMessage() {
}
public Date getCreatedTime() {
return createdTime;
}
public SOMessage setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
Calendar calendar = Calendar.getInstance();
calendar.setTime(createdTime);
int year = calendar.get(Calendar.YEAR);
//判断是不是今年
if(Constant.NOW_YEAY ==year ){
this.createdTimeStr = DateUtil.dateToString(createdTime, "MM月dd日");
}else{
this.createdTimeStr = DateUtil.dateToString(createdTime, "yyyy年MM月dd日");
}
this.createdYMDHMSStr = DateUtil.dateToString(createdTime, "yyyy-MM-dd ahh:mm:ss");//title 显示
//时间转换
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
this.createdTimeZooe = df.format(createdTime);//带时区的格式化
return this;
}
so_message_author
对应实体,同样getter/setter
方法不贴
/**
*
* 开发公司:SOJSON在线工具 <p>
* 版权所有:© www.sojson.com<p>
* 博客地址:https://www.sojson.com/blog/ <p>
* <p>
*
* 评论用户实体
*
* <p>
*
* 区分 责任人 日期 说明<br/>
* 创建 周柏成 2017年5月2日 19:52 <br/>
*
* @author zhou-baicheng
* @email so@sojson.com
* @version 1.0,2017年5月2日 19:52 <br/>
*
*/
public class SOMessageAuthor implements Serializable{
static final long serialVersionUID = 2147084036057204215L;
/**评论人ID*/
private Long id;
/**第三方ID**/
private String threadId;
/**第三方Type*/
private Integer threadType;
/**头像*/
private String avatarUrl;
/**跳转链接*/
private String url;
/**用户nickname*/
private String nickname;
public SOMessageAuthor() {
}
public SOMessageAuthor(JsonObject jsonObj) {
JsonObject author = jsonObj.get("author").getAsJsonObject();
String name = "SOJSON用户";
this.nickname = name;
if("在线工具".equals(name)){
this.id = new Long(1);
}
String url = "javasciript:void(0);";
if(null != author.get("url") && !author.get("url").isJsonNull()){
url = author.get("url").getAsString();
}
this.url = url;
String qqUid = null;
if(null != author.get("qq_uid") && !author.get("qq_uid").isJsonNull()){
qqUid = author.get("qq_uid").getAsString();
}
this.threadId= qqUid ;
//默认头像
String avatarUrl = "//file.sojson.com/images/default_avatar_50.gif";
if(null != author.get("avatar_url") && !author.get("avatar_url").isJsonNull()){
String img = author.get("avatar_url").getAsString();
if(StringUtils.isNotBlank(img) && !StringUtils.contains(img, "duoshuo")){
avatarUrl = img;
}
}
this.avatarUrl = avatarUrl;
}
so_message_like
对应的实体SOMessageLike
,也同样省略getter/setter
方法。
public class SOMessageLike implements Serializable{
private static final long serialVersionUID = 86165841353511L;
/**自增ID,没什么用*/
private Long id;
/**message id,关联用*/
private Long messageId;
/**点赞(顶) 用户id*/
private Long userId;
/**用户赞(顶)ip地址*/
private String ip;
}
效果图如下,测试评论框请看这个地址:https://www.sojson.com/other/duoshuo.html
版权所属:SO JSON在线解析
原文地址:https://www.sojson.com/blog/222.html
转载时必须以链接形式注明原始出处及本声明。
如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。