4.3 关注、取消关注和关注、粉丝列表

3889 2025-11-03 09:32:12
文章目录 设计Redis的key和Value开发关注、取关的业务开发Controller,接受关注取关请求修改主页的js增加获取关注,粉丝数量,是否关注的业务主

文章目录

设计Redis的key和Value开发关注、取关的业务开发Controller,接受关注取关请求修改主页的js增加获取关注,粉丝数量,是否关注的业务主页的Controller修改页面

关注、粉丝列表业务层表现层修改页面

# 关注、取消关注

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwZ8AhZC-1646567007779)(D:\TyporaNotes\牛客网论坛项目\第三章图片\image-20220306104936732.png)]

设计Redis的key和Value

查询关注列表 查询某个用户关注的实体 传入这个需要查找的用户的userId,再传入关注列表的类型;使用有序集合,放入实体的id,和当前时间,方便后续显示关注时间等功能。查询粉丝列表 查询某个实体拥有的粉丝 传入这个实体的类型和id;使用有序集合,放入关注者的id,和当前时间,方便后续显示关注时间等功能。

private static final String PREFIX_FOLLOWEE = "followee:";

private static final String PREFIX_FOLLOWER = "follower:";

//某个用户关注的实体

//followee:userid:entityType -->zset(entityid,now)

public static String getFolloweeKey(int userId,int entityType)

{

return PREFIX_FOLLOWEE+userId+SPLIT+entityType;

}

//查询某个实体的粉丝列表

//follower:entityType:entityId -->zset(userId,now)

public static String getFollowerKey(int entityType,int entityId)

{

return PREFIX_FOLLOWER+entityType+SPLIT+entityId;

}

开发关注、取关的业务

因为需要设置两个key,启用Redis的业务操作 使用当前时间的ms

@Service

public class FollowService {

@Autowired

private RedisTemplate redisTemplate;

//关注 需要设置关注和粉丝 使用事务

public void follow(int userId,int entityType,int entityId)

{

redisTemplate.execute(new SessionCallback() {

@Override

public Object execute(RedisOperations operations) throws DataAccessException {

String followeeKey= RedisKeyUtil.getFolloweeKey(userId,entityType);

String followerKey=RedisKeyUtil.getFollowerKey(entityType,entityId);

//开始Redis事务

operations.multi();

operations.opsForZSet().add(followeeKey,entityId,System.currentTimeMillis());

operations.opsForZSet().add(followerKey,userId,System.currentTimeMillis());

//提交事务

return operations.exec();

}

});

}

//取关业务 需要设置取消关注和粉丝减一 使用事务

public void unfollow(int userId,int entityType,int entityId)

{

redisTemplate.execute(new SessionCallback() {

@Override

public Object execute(RedisOperations operations) throws DataAccessException {

String followeeKey= RedisKeyUtil.getFolloweeKey(userId,entityType);

String followerKey=RedisKeyUtil.getFollowerKey(entityType,entityId);

//开始Redis事务

operations.multi();

operations.opsForZSet().remove(followeeKey,entityId);

operations.opsForZSet().remove(followerKey,userId);

//提交事务

return operations.exec();

}

});

}

}

开发Controller,接受关注取关请求

当前用户关注某个实体

@Controller

public class FollowController {

@Autowired

FollowService followService;

//从登录的用户中获取User信息

@Autowired

HostHolder hostHolder;

//关注

@RequestMapping(value = "/follow",method = RequestMethod.POST)

@ResponseBody

public String follow(int entityType,int entityId){

User user = hostHolder.getUser();

followService.follow(user.getId(),entityType,entityId);

//返回JSON字符串

return CommunityUtil.getJSONString(0,"已关注!");

}

//取消关注

@RequestMapping(value = "/unfollow",method = RequestMethod.POST)

@ResponseBody

public String unfollow(int entityType,int entityId){

User user = hostHolder.getUser();

followService.unfollow(user.getId(),entityType,entityId);

//返回JSON字符串

return CommunityUtil.getJSONString(0,"已取消关注!");

}

}

修改主页的js

获取userId 使用隐藏框 然后获取按钮的前一个结点的值

$(function(){

$(".follow-btn").click(follow);

});

function follow() {

var btn = this;

if($(btn).hasClass("btn-info")) {

// 关注TA

$.post(

CONTEXT_PATH+"/follow",

{"entityType":3,"entityId":$(btn).prev().val()},

function (data) {

data=$.parseJSON(data);

if(data.code==0)

{

window.location.reload();

}else {

alert(data.msg);

}

}

)

$(btn).text("已关注").removeClass("btn-info").addClass("btn-secondary");

} else {

// 取消关注

$.post(

CONTEXT_PATH+"/unFollow",

{"entityType":3,"entityId":$(btn).prev().val()},

function (data) {

data=$.parseJSON(data);

if(data.code==0)

{

window.location.reload();

}else {

alert(data.msg);

}

}

)

$(btn).text("关注TA").removeClass("btn-secondary").addClass("btn-info");

}

}

增加获取关注,粉丝数量,是否关注的业务

//查询关注的实体数量

public long findFolloweeCount(int userId,int entityType)

{

String followeeKey=RedisKeyUtil.getFolloweeKey(userId,entityType);

return redisTemplate.opsForZSet().zCard(followeeKey);

}

//查询粉丝的数量

public long findFollowerCount(int entityType,int entityId)

{

String followerKey=RedisKeyUtil.getFollowerKey(entityType,entityId);

return redisTemplate.opsForZSet().zCard(followerKey);

}

//查询当前用户是否已经关注该实体

public boolean hasFollowed(int userId,int entityType,int entityId)

{

String followeeKey=RedisKeyUtil.getFolloweeKey(userId,entityType);

//查询当前key是否有分数就知道是否已经关注

return redisTemplate.opsForZSet().score(followeeKey,entityId)!=null;

}

主页的Controller

//关注数量

long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER);

model.addAttribute("followeeCount", followeeCount);

//粉丝数量

long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, userId);

model.addAttribute("followerCount", followerCount);

//是否已经关注

boolean hasFollowed=false;

if(hostHolder.getUser()!=null)

{

hasFollowed=followService.hasFollowed(hostHolder.getUser().getId(),ENTITY_TYPE_USER,userId);

}

model.addAttribute("hasFollowed", hasFollowed);

修改页面

用户头像

nowcoder

注册于 2015-06-12 15:20:12

关注了 5

关注者 123

获得了 87 个赞

关注、粉丝列表

业务层

需要分页,因此需要传入分页的参数;

通过key使用时间倒叙查出目标id(即用户关注的人组成的集合);

遍历ids,通过id查到相应的user信息;

通过key和id查出相应的分数即创建时间,放入到map里;

// 查询某用户关注的人

public List> findFollowees(int userId, int offset, int limit) {

String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);

Set targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);

if (targetIds == null) {

return null;

}

List> list = new ArrayList<>();

for (Integer targetId : targetIds) {

Map map = new HashMap<>();

User user = userService.queryUserById(targetId);

map.put("user", user);

Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);

map.put("followTime", new Date(score.longValue()));

list.add(map);

}

return list;

}

// 查询某用户的粉丝

public List> findFollowers(int userId, int offset, int limit) {

String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);

Set targetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);

if (targetIds == null) {

return null;

}

List> list = new ArrayList<>();

for (Integer targetId : targetIds) {

Map map = new HashMap<>();

User user = userService.queryUserById(targetId);

map.put("user", user);

Double score = redisTemplate.opsForZSet().score(followerKey, targetId);

map.put("followTime", new Date(score.longValue()));

list.add(map);

}

return list;

}

表现层

首先向模板中保存该用户的用户信息,方便修改;设置分页参数 起始页和每页的条数;调用Service查询该用户的关注列表;遍历userList,获取该关注列表里的每一个用户的信息;需要判断登录的用户是否关注了列表里的其他用户,来显示未关注和已关注;

//查找该用户的关注列表

@RequestMapping(path = "/followees/{userId}", method = RequestMethod.GET)

public String getFollowees(@PathVariable("userId") int userId, Page page, Model model) {

//查询当前用户信息

User user = userService.queryUserById(userId);

if (user == null) {

throw new RuntimeException("该用户不存在!");

}

//向模板保存当前用户的信息

model.addAttribute("user", user);

//设置分页参数

page.setLimit(5);

page.setPath("/followees/" + userId);

page.setRows((int) followService.findFolloweeCount(userId, ENTITY_TYPE_USER));

//调用Service查询该用户的关注列表

List> userList = followService.findFollowees(userId, page.getOffset(), page.getLimit());

if (userList != null) {

//遍历userList,获取该关注列表里的每一个用户的信息

for (Map map : userList) {

User u = (User) map.get("user");

map.put("hasFollowed", hasFollowed(u.getId()));

}

}

model.addAttribute("users", userList);

return "/site/followee";

}

//查看该用户的粉丝列表

@RequestMapping(path = "/followers/{userId}", method = RequestMethod.GET)

public String getFollowers(@PathVariable("userId") int userId, Page page, Model model) {

User user = userService.queryUserById(userId);

if (user == null) {

throw new RuntimeException("该用户不存在!");

}

model.addAttribute("user", user);

page.setLimit(5);

page.setPath("/followers/" + userId);

page.setRows((int) followService.findFollowerCount(ENTITY_TYPE_USER, userId));

List> userList = followService.findFollowers(userId, page.getOffset(), page.getLimit());

if (userList != null) {

for (Map map : userList) {

User u = (User) map.get("user");

//判断当前登录的用户是否已经关注粉丝列表里其他人

map.put("hasFollowed", hasFollowed(u.getId()));

}

}

model.addAttribute("users", userList);

return "/site/follower";

}

//判断登录的用户是否关注了列表里的其他用户

private boolean hasFollowed(int userId) {

if (hostHolder.getUser() == null) {

return false;

}

return followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);

}

修改页面

1、修改关注和关注者请求,改为相应的请求,加拼上当前用户的id

关注了 5

关注者 123

获得了 87 个赞

2、遍历usersList集合,修改每一个用户的信息

  • 用户头像

    落基山脉下的闲人

    关注于 2019-04-28 14:13:25

```

用Excel制作自动考勤表,需要掌握哪些Excel函数?|教你十分钟做出来一个asp的增改删功能的网站

友情链接