由于多说关闭,多说源码不开放,Java模仿多说评论系统实现(二)

JSON 2017-05-02 22:26:11 13630

先什么都不多说,先看看效果,高仿多说评论已经上线,估计还是有瑕疵,不断完善中。评论链接===> :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

转载时必须以链接形式注明原始出处及本声明。

本文主题:

如果本文对你有帮助,那么请你赞助我,让我更有激情的写下去,帮助更多的人。

关于作者
一个低调而闷骚的男人。
相关文章
多说迁移,Java开发模仿自主实现评论(一)
Java 实现多个级域名访问同一个Tomcat(系统)。
Java 实现在线HTTP接口测试 - HTTP GET/POST拟请求测试工具
Java拟WSS websocket ssl请求,Java WSS拟请求代码示例
Java获取浏览器请求头(User-Agent),分析浏览器信息,系统信息的几种办法。
N多系统单点登录,实现、解决方案。四种解决方案
MyEclipse8.5 注册码生成 Java代码实现方式。永久免费
微信支付功能--PC端生成维码,实现扫描支付功能
单个项目多个级域名简单实现思路
Java生成验证码合集()GIF版,Java生成动图验证码
最新文章
PHP变量剖析 11
SQL全外连接剖析 119
SQL自然连接剖析 147
springboot启动原理 245
SQL右连接【RIGHT JOIN】详解及图解 450
SQL左链接【LEFT JOIN】详解及图解 357
SQL非等值连接剖析 262
SQL等链接剖析 291
SQL内连接详解及图解 385
python之numpy常用的100种数值相关方法及代码示例 231
最热文章
最新MyEclipse8.5注册码,有效期到2020年 (已经更新) 679241
苹果电脑Mac怎么恢复出厂系统?苹果系统怎么重装系统? 674561
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 599031
免费天气API,天气JSON API,不限次数获取十五天的天气预报 565278
Jackson 时间格式化,时间注解 @JsonFormat 用法、时差问题说明 551715
我为什么要选择RabbitMQ ,RabbitMQ简介,各种MQ选型对比 509186
Elasticsearch教程(四) elasticsearch head 插件安装和使用 479645
Jackson 美化输出JSON,优雅的输出JSON数据,格式化输出JSON数据... ... 262820
Java 信任所有SSL证书,HTTPS请求抛错,忽略证书请求完美解决 244092
Elasticsearch教程(一),全程直播(小白级别) 225127
支付扫码

所有赞助/开支都讲公开明细,用于网站维护:赞助名单查看

查看我的收藏

正在加载... ...