package com.xiaozhi.blog.mongo; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.support.collections.DefaultRedisList; import org.springframework.data.redis.support.collections.RedisList; import org.springframework.stereotype.Repository; import com.google.common.collect.ArrayListMultimap; import com.xiaozhi.blog.utils.KeyUtils; import com.xiaozhi.blog.utils.UserGroupHelper; import com.xiaozhi.blog.vo.Range; import com.xiaozhi.blog.vo.User; import com.xiaozhi.blog.vo.UserGroup; @Repository public class MongoFollowingDao { private static Log logger = LogFactory.getLog(MongoFollowingDao.class); @Autowired private StringRedisTemplate template; @Autowired private MongoTemplate mongoTemplate; @Autowired private MongoUserGroupDao mongoUserGroupDao; public List<String> getFollowings(String uid){ return template.opsForList().range(KeyUtils.followers(uid),0,-1); } /** * 分页获取关注列表 * @param uid * @return */ public List<User> getFollowings(String uid, Range range) { //当前页用户集合 List<String> ids= template.opsForList().range(KeyUtils.following(uid), range.being, range.end-range.being+1); List<String> followers= template.opsForList().range(KeyUtils.followers(uid),0,-1); List<User> users = this.mongoTemplate.find(new Query(Criteria.where("id").in(ids.toArray())),User.class); List<UserGroup> groups = this.mongoUserGroupDao.getGroupByUserId(uid); ArrayListMultimap<String,UserGroup> gMultimap = UserGroupHelper.getUserGroupsMulitMap(groups); for(User user :users){ if(followers.contains(user.getId().toString())){//判断是否相互关注 user.setLink(true); }else{ user.setLink(false); } user.setGroups(gMultimap.get(user.getId()));//设置他所在的用户组 } return users; } /** * 返回总关注数 * @param uid * @return */ public int getFollowingsNum(String uid){ return template.opsForList().size(KeyUtils.following(uid)).intValue(); } /** * 判断是否关注 * @param uid * @param targetUid * @return */ public boolean isFollowing(String uid, String targetUid) { return following(uid).contains(targetUid); } /** * 加关注 * @param targetUser */ public boolean follow(final String targetUid,final String uid) { try { this.mongoTemplate.updateFirst(new Query(Criteria.where("id").is(uid)), new Update().inc("followingNum", 1),User.class);//对自己关注数+1操作 this.mongoTemplate.updateFirst(new Query(Criteria.where("id").is(targetUid)), new Update().inc("followerNum", 1),User.class);//对对方的粉丝数+1操作 } catch (Exception e) { logger.error("==================> Mongo follow error :"+e.toString()); return false; } boolean result = (Boolean) template.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection)throws DataAccessException { try { connection.multi();//事务开启 connection.lPush(KeyUtils.following(uid).getBytes(), targetUid.getBytes()); connection.lPush(KeyUtils.followers(targetUid).getBytes(), uid.getBytes()); connection.exec(); return true; } catch (Exception e) { logger.error("==================> follow error :"+e.toString()); mongoTemplate.updateFirst(new Query(Criteria.where("id").is(uid)), new Update().inc("followingNum", -1),User.class);//对自己关注数-1操作 mongoTemplate.updateFirst(new Query(Criteria.where("id").is(targetUid)), new Update().inc("followerNum", -1),User.class);//对对方的粉丝数-1操作 }finally{ connection.close(); } return false; } }); return result; } /** * 停止关注 * @param targetUser */ public boolean stopFollowing(final String targetUid,final String uid) { try { this.mongoTemplate.updateFirst(new Query(Criteria.where("id").is(uid)), new Update().inc("followingNum", -1),User.class);//对自己关注数-1操作 this.mongoTemplate.updateFirst(new Query(Criteria.where("id").is(targetUid)), new Update().inc("followerNum", -1),User.class);//对对方的粉丝数-1操作 } catch (Exception e) { logger.error("==================> Mongo stopFollowing error :"+e.toString()); return false; } boolean result = (Boolean) template.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection)throws DataAccessException { try { connection.multi();//事务开启 connection.lRem(KeyUtils.following(uid).getBytes(), 0, targetUid.getBytes()); connection.lRem(KeyUtils.followers(targetUid).getBytes(),0, uid.getBytes()); connection.exec(); return true; } catch (Exception e) { logger.error("==================> stopFollowing error :"+e.toString()); //callback mongoTemplate.updateFirst(new Query(Criteria.where("id").is(uid)), new Update().inc("followingNum", 1),User.class);//对自己关注数+1操作 mongoTemplate.updateFirst(new Query(Criteria.where("id").is(targetUid)), new Update().inc("followerNum", 1),User.class);//对对方的粉丝数+1操作 }finally{ connection.close(); } return false; } }); return result; } private RedisList<String> following(String uid) { return new DefaultRedisList<String>(KeyUtils.following(uid), template); } }