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

soゝso 2017-05-02 22:26:11 2820
分享到:

先什么都不多说,先看看效果,高仿多说评论已经上线,估计还是有瑕疵,不断完善中。评论链接===> :http://www.sojson.com/other/duoshuo.html

昨天说到了  多说  ,然后简单分析了一个评论基本需求,基本的字段等等。

今天建表,初步把数据拉出来,当然功能不是很完善(后面会逐步把该有功能补上),目前实现了评论,回复评论,以及把原有的数据读取过来。下面看看简单效果图和功能。先看看数据结构,我用咱们网站的工具:http://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>
 * 博客地址:http://www.sojson.com/blog/  <p>
 * <p>
 * 
 * 模拟多说评论实体
 * 
 * <p>
 * 
 * 区分 责任人 日期    说明<br/>
 * 创建 周柏成 2017年5月2日 19:48  <br/>
 *
 * @author zhou-baicheng
 * @email  [email protected]
 * @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>
 * 博客地址:http://www.sojson.com/blog/  <p>
 * <p>
 * 
 * 评论用户实体
 * 
 * <p>
 * 
 * 区分 责任人 日期    说明<br/>
 * 创建 周柏成 2017年5月2日 19:52  <br/>
 *
 * @author zhou-baicheng
 * @email  [email protected]
 * @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 = "//cdn.www.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;
}

效果图如下,测试评论框请看这个地址:http://www.sojson.com/other/duoshuo.html



关于作者
目前就职于国内某电商平台公司打杂。。
相关文章
多说迁移,Java开发模仿自主实现评论(一)
Java 实现多个级域名访问同一个Tomcat(系统)。
N多系统单点登录,实现、解决方案。四种解决方案
单个项目多个级域名简单实现思路
Java 实现在线HTTP接口测试 - HTTP GET/POST拟请求测试工具
Shiro教程()Maven管理Shrio Jar包
Elasticsearch教程(),IK分词器安装
Java 发送Email,Java 邮件发送工具类封装
Shiro教程(十一)Shiro 控制并发登录人数限制实现,登录踢出实现
Java生成验证码合集(一)简单版
最新文章
jQuery Jsonp 请求,捕获异常(404,50X)状态异常 24
Springboot HTTP请求,Springboot HTTP 请求 Demo。Get/Post 149
微信自动关注公众号 JavaScript 脚本,批量关注公众号脚本 361
SOJSON 使用又拍云 CDN 整体架构,解决百度 SEO 方案 116
又拍云(Upyun)刷新CDN,云存储缓存 —JavaAPI 65
JS解密,JavaScript 解密,任何JS加密都能100%解密,以及JS 加密讲解 378
阿里云DNS 解析讲解,SEO配置搜索引擎线路解析 113
百度秒收录教程,怎么做到百度秒收入你的页面,SEO 教程 227
CDN 请求返回 connection reset by peer,被拦截请求解决方案 77
Google AdSense 申请技巧,谷歌广告申请通不过教程 197
最热文章
Elasticsearch教程(四) elasticsearch head 插件安装和使用 111605
Elasticsearch教程(六) elasticsearch Client创建 73984
Elasticsearch教程(八) elasticsearch delete 删除数据(Java) 71202
Elasticsearch教程(二),IK分词器安装 68285
Elasticsearch教程(三),IK分词器安装 (极速版) 54360
Elasticsearch教程(一),全程直播(小白级别) 53421
Elasticsearch教程(五) elasticsearch Mapping的创建 52767
Elasticsearch教程(七) elasticsearch Insert 插入数据(Java) 48595
免费天气API,全国天气 JSON API接口,可以获取五天的天气预报 44385
Elasticsearch权威指南-中文.pdf,Elasticsearch 中文文档下载 41717

骚码加入我们 / 千人QQ群:259217951

入群需要5元,如果没有QQ钱包,可以先Alipay、微信,赞助然后加群主拉进。

二维码生成 来自 >> 二维码生成器

支付扫码

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

正在加载... ...