1 Model:Feed
package com.cyq.model;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.Date;
import java.util.Map;
public class Feed {
private int id;
private int type;
private int userId;
private Date createdDate;
private String data; //读取的数据
private JSONObject dataJSON = null;读取数据的辅助变量
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public int getType() { return type; }
public void setType(int type) { this.type = type; }
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
public Date getCreatedDate() { return createdDate; }
public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; }
public String getData() { return data; }
public void setData(String data) {
this.data = data;
dataJSON = JSONObject.parseObject(data);
}
public String get(String key) {
return dataJSON == null ? null : dataJSON.getString(key);
}
}
Util: RedisKeyUtil
package com.cyq.util;
public class RedisKeyUtil {
private static String SPLIT = ":";
// 获取粉丝
private static String BIZ_FOLLOWER = "FOLLOWER";
// 关注对象
private static String BIZ_FOLLOWEE = "FOLLOWEE";
// 某个实体的粉丝key
public static String getFollowerKey(int entityType, int entityId) {
return BIZ_FOLLOWER + SPLIT + String.valueOf(entityType) + SPLIT + String.valueOf(entityId);
}
// 每个用户对某类实体的关注key
public static String getFolloweeKey(int userId, int entityType) {
return BIZ_FOLLOWEE + SPLIT + String.valueOf(userId) + SPLIT + String.valueOf(entityType);
}
}
FeedHandler:监听事件
package com.cyq.async.handler;
import com.alibaba.fastjson.JSONObject;
import com.cyq.async.EventHandler;
import com.cyq.async.EventModel;
import com.cyq.async.EventType;
import com.cyq.model.*;
import com.cyq.service.*;
import com.cyq.util.JedisAdapter;
import com.cyq.util.RedisKeyUtil;
import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class FeedHandler implements EventHandler {
@Autowired
FollowService followService;
@Autowired
UserService userService;
@Autowired
FeedService feedService;
@Autowired
JedisAdapter jedisAdapter;
@Autowired
QuestionService questionService;
private String buildFeedData(EventModel model) {
Map<String, String> map = new HashMap<String ,String>();
// 触发用户是通用的
User actor = userService.getUser(model.getActorId());
if (actor == null) {
return null;
}
map.put("userId", String.valueOf(actor.getId()));
map.put("userHead", actor.getHeadUrl());
map.put("userName", actor.getName());
//事件为评论或关注,实体类型为问题
if (model.getType() == EventType.COMMENT ||
(model.getType() == EventType.FOLLOW && model.getEntityType() == EntityType.ENTITY_QUESTION)) {
Question question = questionService.getById(model.getEntityId());
if (question == null) {
return null;
}
map.put("questionId", String.valueOf(question.getId()));
map.put("questionTitle", question.getTitle());
return JSONObject.toJSONString(map);
}
return null;
}
@Override
public void doHandle(EventModel model) {
// 为了测试,把model的userId随机一下
Random r = new Random();
model.setActorId(1+r.nextInt(10));
// 构造一个新鲜事
Feed feed = new Feed();
feed.setCreatedDate(new Date());
feed.setType(model.getType().getValue());
feed.setUserId(model.getActorId());
feed.setData(buildFeedData(model));
if (feed.getData() == null) {
return; // 不支持的feed
}
feedService.addFeed(feed);
/**
*拉方式
*/
// 获得所有粉丝
List<Integer> followers = followService.getFollowers(EntityType.ENTITY_USER, model.getActorId(), Integer.MAX_VALUE);
// 0为系统队列
followers.add(0);
/**
*推方式
*/
// 给所有粉丝推事件
for (int follower : followers) {
String timelineKey = RedisKeyUtil.getTimelineKey(follower);
jedisAdapter.lpush(timelineKey, String.valueOf(feed.getId()));
// 限制最长长度,如果timelineKey的长度过大,就删除后面的新鲜事
}
}
@Override
public List<EventType> getSupportEventTypes() {
return Arrays.asList(new EventType[]{EventType.COMMENT, EventType.FOLLOW});
}
}
FeedService
package com.cyq.service;
import com.cyq.dao.FeedDAO;
import com.cyq.model.Feed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class FeedService {
@Autowired
FeedDAO feedDAO;
public List<Feed> getUserFeeds(int maxId, List<Integer> userIds, int count) {
return feedDAO.selectUserFeeds(maxId, userIds, count);
}
public boolean addFeed(Feed feed) {
feedDAO.addFeed(feed);
return feed.getId() > 0;
}
public Feed getById(int id) {
return feedDAO.getFeedById(id);
}
}
feedController
//取数据
package com.cyq.controller;
import com.cyq.model.*;
import com.cyq.service.*;
import com.cyq.util.JedisAdapter;
import com.cyq.util.RedisKeyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Controller
public class FeedController {
private static final Logger logger = LoggerFactory.getLogger(FeedController.class);
@Autowired
FeedService feedService;
@Autowired
FollowService followService;
@Autowired
HostHolder hostHolder;
@Autowired
JedisAdapter jedisAdapter;
//推:一一获得粉丝给他推
@RequestMapping(path = {"/pushfeeds"}, method = {RequestMethod.GET, RequestMethod.POST})
private String getPushFeeds(Model model) {
int localUserId = hostHolder.getUser() != null ? hostHolder.getUser().getId() : 0;
List<String> feedIds = jedisAdapter.lrange(RedisKeyUtil.getTimelineKey(localUserId), 0, 10);
List<Feed> feeds = new ArrayList<Feed>();
for (String feedId : feedIds) {
//推
Feed feed = feedService.getById(Integer.parseInt(feedId));
if (feed != null) {
feeds.add(feed);
}
}
model.addAttribute("feeds", feeds);
return "feeds";
}
//拉(推和拉一种方式即可):一一获得关注者的动态
@RequestMapping(path = {"/pullfeeds"}, method = {RequestMethod.GET, RequestMethod.POST})
private String getPullFeeds(Model model) {
int localUserId = hostHolder.getUser() != null ? hostHolder.getUser().getId() : 0;
List<Integer> followees = new ArrayList<>();
if (localUserId != 0) {
// 关注的人
followees = followService.getFollowees(localUserId, EntityType.ENTITY_USER, Integer.MAX_VALUE);
}
List<Feed> feeds = feedService.getUserFeeds(Integer.MAX_VALUE, followees, 10);
model.addAttribute("feeds", feeds);
return "feeds";
}
}