4-four: 我收到的赞

news2025/4/17 19:13:04

我收到的赞

重构点赞功能(用上节的功能较为麻烦,需要将用户发布的帖子和评论所获得的赞加起来)

  • 以用户为key,记录点赞数量
  • increment(key), decrement(key)。

开发个人主页

  • 以用户为key,查询点赞数量

1.在Redis.Util中增加方法

// 某个用户的赞
    // like:user:userId -> int
    public static String getUserLikeKey(int userId) {
        return PREFIX_USER_LIKE + SPLIT + userId;
    }

2.重构点赞方法: 在LikeService中增加业务,需要保证事务性

package com.nowcoder.community.service;

import com.nowcoder.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

@Service
public class LikeService {

    @Autowired
    private RedisTemplate redisTemplate;

    // 点赞
    public void like(int userId, int entityType, int entityId, int entityUserId) {//将实体的作者传进来
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
                String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId);//作者的实体

                boolean isMember = operations.opsForSet().isMember(entityLikeKey, userId);

                operations.multi();//开启事务
                //执行
                if (isMember) {
                    operations.opsForSet().remove(entityLikeKey, userId);
                    operations.opsForValue().decrement(userLikeKey);
                } else {
                    operations.opsForSet().add(entityLikeKey, userId);
                    operations.opsForValue().increment(userLikeKey);
                }

                return operations.exec();//提交
            }
        });
    }

    // 查询某实体点赞的数量
    public long findEntityLikeCount(int entityType, int entityId) {
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
        return redisTemplate.opsForSet().size(entityLikeKey);
    }

    // 查询某人对某实体的点赞状态
    public int findEntityLikeStatus(int userId, int entityType, int entityId) {
        String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
        return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;
    }

    // 查询某个用户获得的赞
    public int findUserLikeCount(int userId) {
        String userLikeKey = RedisKeyUtil.getUserLikeKey(userId);
        Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey);
        return count == null ? 0 : count.intValue();
    }

}

4 LikeController.java

package com.nowcoder.community.controller;

import com.nowcoder.community.entity.User;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.util.CommunityUtil;
import com.nowcoder.community.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@Controller
public class LikeController {

    @Autowired
    private LikeService likeService;

    @Autowired
    private HostHolder hostHolder;

    @RequestMapping(path = "/like", method = RequestMethod.POST)
    @ResponseBody
    public String like(int entityType, int entityId, int entityUserId) {
        User user = hostHolder.getUser();

        // 点赞
        likeService.like(user.getId(), entityType, entityId, entityUserId);

        // 数量
        long likeCount = likeService.findEntityLikeCount(entityType, entityId);
        // 状态
        int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);
        // 返回的结果
        Map<String, Object> map = new HashMap<>();
        map.put("likeCount", likeCount);
        map.put("likeStatus", likeStatus);

        return CommunityUtil.getJSONString(0, null, map);
    }

}

5. 对页面做处理

在帖子详情页面,新添加传入相应的参数,
在这里插入图片描述
在处理的JS文件中也要传入新的参数

function like(btn, entityType, entityId,entityUserId) {
    $.post(
        CONTEXT_PATH + "/like",
        {"entityType":entityType,"entityId":entityId,"entityUserId":entityUserId},
        function(data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                $(btn).children("i").text(data.likeCount);
                $(btn).children("b").text(data.likeStatus==1?'已赞':"赞");
            } else {
                alert(data.msg);
            }
        }
    );
}

对实体的作者新添加了一个KEY,这个KEY会随着点赞次数的增加而自增,相应的随着取消点赞而自减,然后,可以查看最后这个KEY的数量,从而判断用户收到了多少的赞。

个人主页的编码

1. 在UserController.java中增加代码

(注意,可以查看自己的主页,也可以查看他人的主页)

    // 个人主页
    @RequestMapping(path = "/profile/{userId}", method = RequestMethod.GET)
    public String getProfilePage(@PathVariable("userId") int userId, Model model) {
        User user = userService.findUserById(userId);
        if (user == null) {//判断用户是否存在,防止错误攻击
            throw new RuntimeException("该用户不存在!");
        }

        // 用户
        model.addAttribute("user", user);//用户的基本信息传递给页面
        // 点赞数量
        int likeCount = likeService.findUserLikeCount(userId);//注意要将service对象注入
        model.addAttribute("likeCount", likeCount);//将数量发送给页面
        return "/site/profile";//返回指定模板
    }

2. 在Index.html中增加代码

在这里插入图片描述
在这里插入图片描述
profile.html

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
	<link rel="stylesheet" th:href="@{/css/global.css}" />
	<title>牛客网-个人主页</title>
</head>
<body>
	<div class="nk-container">
		<!-- 头部 -->
		<header class="bg-dark sticky-top" th:replace="index::header">
			<div class="container">
				<!-- 导航 -->
				<nav class="navbar navbar-expand-lg navbar-dark">
					<!-- logo -->
					<a class="navbar-brand" href="#"></a>
					<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
						<span class="navbar-toggler-icon"></span>
					</button>
					<!-- 功能 -->
					<div class="collapse navbar-collapse" id="navbarSupportedContent">
						<ul class="navbar-nav mr-auto">
							<li class="nav-item ml-3 btn-group-vertical">
								<a class="nav-link" href="../index.html">首页</a>
							</li>
							<li class="nav-item ml-3 btn-group-vertical">
								<a class="nav-link position-relative" href="letter.html">消息<span class="badge badge-danger">12</span></a>
							</li>
							<li class="nav-item ml-3 btn-group-vertical">
								<a class="nav-link" href="register.html">注册</a>
							</li>
							<li class="nav-item ml-3 btn-group-vertical">
								<a class="nav-link" href="login.html">登录</a>
							</li>
							<li class="nav-item ml-3 btn-group-vertical dropdown">
								<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
									<img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/>
								</a>
								<div class="dropdown-menu" aria-labelledby="navbarDropdown">
									<a class="dropdown-item text-center" href="profile.html">个人主页</a>
									<a class="dropdown-item text-center" href="setting.html">账号设置</a>
									<a class="dropdown-item text-center" href="login.html">退出登录</a>
									<div class="dropdown-divider"></div>
									<span class="dropdown-item text-center text-secondary">nowcoder</span>
								</div>
							</li>
						</ul>
						<!-- 搜索 -->
						<form class="form-inline my-2 my-lg-0" action="search.html">
							<input class="form-control mr-sm-2" type="search" aria-label="Search" />
							<button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button>
						</form>
					</div>
				</nav>
			</div>
		</header>

		<!-- 内容 -->
		<div class="main">
			<div class="container">
				<!-- 选项 -->
				<div class="position-relative">
					<ul class="nav nav-tabs">
						<li class="nav-item">
							<a class="nav-link active" href="profile.html">个人信息</a>
						</li>
						<li class="nav-item">
							<a class="nav-link" href="my-post.html">我的帖子</a>
						</li>
						<li class="nav-item">
							<a class="nav-link" href="my-reply.html">我的回复</a>
						</li>
					</ul>
				</div>
				<!-- 个人信息 -->
				<div class="media mt-5">
					<img th:src="${user.headerUrl}" class="align-self-start mr-4 rounded-circle" alt="用户头像" style="width:50px;">
					<div class="media-body">
						<h5 class="mt-0 text-warning">
							<span th:utext="${user.username}">nowcoder</span>
							<button type="button" class="btn btn-info btn-sm float-right mr-5 follow-btn">关注TA</button>
						</h5>
						<div class="text-muted mt-3">
							<span>注册于 <i class="text-muted" th:text="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}">2015-06-12 15:20:12</i></span>
						</div>
						<div class="text-muted mt-3 mb-5">
							<span>关注了 <a class="text-primary" href="followee.html">5</a></span>
							<span class="ml-4">关注者 <a class="text-primary" href="follower.html">123</a></span>
							<span class="ml-4">获得了 <i class="text-danger" th:text="${likeCount}">87</i> 个赞</span>
						</div>
					</div>
				</div>
			</div>
		</div>

		<!-- 尾部 -->
		<footer class="bg-dark">
			<div class="container">
				<div class="row">
					<!-- 二维码 -->
					<div class="col-4 qrcode">
						<img src="https://uploadfiles.nowcoder.com/app/app_download.png" class="img-thumbnail" style="width:136px;" />
					</div>
					<!-- 公司信息 -->
					<div class="col-8 detail-info">
						<div class="row">
							<div class="col">
								<ul class="nav">
									<li class="nav-item">
										<a class="nav-link text-light" href="#">关于我们</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">加入我们</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">意见反馈</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">企业服务</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">联系我们</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">免责声明</a>
									</li>
									<li class="nav-item">
										<a class="nav-link text-light" href="#">友情链接</a>
									</li>
								</ul>
							</div>
						</div>
						<div class="row">
							<div class="col">
								<ul class="nav btn-group-vertical company-info">
									<li class="nav-item text-white-50">
										公司地址:北京市朝阳区大屯路东金泉时代3-2708北京牛客科技有限公司
									</li>
									<li class="nav-item text-white-50">
										联系方式:010-60728802(电话)&nbsp;&nbsp;&nbsp;&nbsp;admin@nowcoder.com
									</li>
									<li class="nav-item text-white-50">
										牛客科技©2018 All rights reserved
									</li>
									<li class="nav-item text-white-50">
										京ICP备14055008号-4 &nbsp;&nbsp;&nbsp;&nbsp;
										<img src="http://static.nowcoder.com/company/images/res/ghs.png" style="width:18px;" />
										京公网安备 11010502036488号
									</li>
								</ul>
							</div>
						</div>
					</div>
				</div>
			</div>
		</footer>
	</div>

	<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script>
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script>
	<script th:src="@{/js/global.js}"></script>
	<script th:src="@{/js/profile.js}"></script>
</body>
</html>

在这里插入图片描述

将之前的测试数据删除,重新构造点赞数据测试即可
在这里插入图片描述


注意:Redis存的是Key Value的键值对,对其用户key,设置一个value,可以存储该用户被点赞的数据量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/53088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ------其他知识点(幂等性、优先级队列、惰性队列)(九)

RabbitMQ------其他知识点&#xff08;&#xff09;&#xff08;九&#xff09; 幂等性 用户对于统一操作发起的一次请求或者多次请求的结果是一致的&#xff0c;不会因为多次点击而产生副作用。同一次还款&#xff0c;通过多次点击不会生成多条还款记录&#xff0c;一个人的…

crm客户管理系统为企业带来的价值

简道云CRM场景套件对中小企业来说&#xff0c;crm客户管理系统最核心的作用&#xff0c;一是客户信息(联系信息和洽谈过程&#xff09;的存留&#xff0c;不会因为业务人员的离职造成流失&#xff0c;这点对老板很重要。二是可帮助业务人员&#xff08;客户获取、主管指导等&am…

Win32API操作文件

在Windows编程中CreateFile函数是用得非常多的&#xff0c;不仅可以打开文件&#xff0c;还可以打开管道、邮槽、通信资源、磁盘设备&#xff08;早期Windows)&#xff0c;控制台、目录。该函数返回一个句柄&#xff0c;该句柄可用于根据文件或设备以及指定的标志和属性访问文件…

SpringSecurity(二十)---OAuth2:实现资源服务器(上)资源服务器搭建以及直接调用授权服务器模式

一、 前言 本章将讨论如何使用Spring Security实现一个资源服务器&#xff0c;资源服务器是管理用户资源的组件。另外&#xff0c;学习本章有个前提&#xff0c;需要先把前面搭建授权服务器的相关文章先给阅读&#xff0c;否则可能后面出现的授权服务器相关代码不知道个所以然…

【Redis】缓存击穿的产生情况解决方案

1. 缓存击穿产生 也叫做 热点 Key 问题&#xff0c;高并发访问并且缓存重建业务较复杂的 key 突然失效了&#xff0c;无数的请求想要重建缓存&#xff0c;大量的访问会在瞬间给数据库带来巨大冲击。 2. 解决方案 2.1 方案一&#xff1a;互斥锁 查询缓存不存在时&#xff0c;…

【OpenFOAM】-olaFlow-算例1- baseWaveFlume

算例路径&#xff1a; olaFlow\tutorials\baseWaveFlume 算例描述&#xff1a; 一个基础的二维波浪水槽 算例快照&#xff1a; 图1 波浪模拟结果图2 算例网格文件结构&#xff1a; ├── 0.org │ ├── U │ ├── alpha.water │ ├── alpha.water.org │ └─…

关于Redis的远程连接 Connection: Disconnect on error 问题

bug描述&#xff1a; Connection: Disconnect on error: Connection error: Connection timed outConnection: 192.168.245.128 > connection failed 问题复现&#xff1a; redis版本&#xff1a; redis-6.2.6 Linux版本&#xff1a;CenterOS 7 在linux上已经完成了red…

第五章. 可视化数据分析分析图表—常用图表的绘制1—折线图,柱形图

第五章. 可视化数据分析分析图 5.3 常用图表的绘制1—折线图,柱形图 本节主要介绍常用图表的绘制&#xff0c;主要包括折线图&#xff0c;柱形图。 1.折线图&#xff08;matplotlib.pyplot.plot&#xff09; 折线图可以显示随时间而变化的连续数据&#xff0c;适用于显示在相…

Hadoop原理与技术——hdfs命令行基本操作

一、实验目的 熟悉hdfs命令行基本操作 二、实验环境 Windows 10 VMware Workstation Pro虚拟机 Hadoop环境 Jdk1.8 三、实验内容 1&#xff1a;hdfs常见命令&#xff1a; &#xff08;1&#xff09;查看帮助&#xff1a;hdfs dfs -help &#xff08;2&#xff09;查看当前目录…

OpenCV图像处理——目标追踪

总目录 图像处理总目录←点击这里 二十四、目标追踪 24.1、多目标&#xff08;手动检测&#xff09;追踪 24.1.1、原理 目标检测&#xff1a;运行之后按下s&#xff0c;通过鼠标对某个目标进行检测&#xff0c;然后点击空格或者回车 目标追踪&#xff1a;opencv的八种追踪…

【JavaEE】JavaScript(基础语法)1

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录前言一、JavaScript初识&#xff08;简单了解就行&#xff0c;没时间跳过&#xff09;二、【JS的代码相关】【注释】【输入输出】三、语法1. 变量2. 【基本数据类型】THINK前言 一个人最大的痛苦就是对自己无能的愤…

信贷风控NCL净损失率的指标实现与应用

在金融信贷业务的风险控制过程中&#xff0c;有一项财务指标发挥着比较重要的信息参考价值&#xff0c;可以有效衡量某个月份放款金额在形成呆账后的资金损失情况&#xff0c;其中呆账指的是信贷逾期180天以上&#xff0c;这个指标便是NCL&#xff08;Net Credit Loss&#xff…

大家都在用的福昕阅读器 foxit 你还不知道吗? 祛除水印PDF转换全功能解锁…

趣味拓展 什么字大家看了都说没用&#xff1f; (答案在文末) 引言 福昕阅读器是一款高级PDF编辑器&#xff0c;查看目录、去除水印、编辑文本、转换格式等都是可以用到的~ 小编第一次使用的时候是用来查看pdf文档目录的&#xff0c;当时未使用破解版&#xff0c;后来循序渐进…

基于PHP+MySQL中小学生科学实验展示网站的设计与实现

中小学生科学实验展示网站能够通过互联网得到广泛的、全面的宣传,让尽可能多的人积极的参加到科学实验行列中来,不仅为需要的人提供了服务,而且锻炼了自己,同时能够让中小学生对科学实验的兴趣有很大的提高 PHP中小学生科学实验展示网站是一个科普类型的网站,系统通过PHp&#…

[附源码]Python计算机毕业设计SSM客户信息管理(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

模拟电子技术(四)放大电路的频率响应

&#xff08;四&#xff09;放大电路的频率响应电路理论基础知识复习频率响应基本概念两个无源频率响应的单元电路波特图&#xff08;幅频、相频&#xff09;高、低同电路对比晶体管的高频等效模型单管放大电路的频率响应研究信号频率的变化对放大电路性能的影响也就是电路对输…

Linux零基础入门(二)Linux基础命令

Linux零基础入门&#xff08;二&#xff09;Linux基础命令前言Linux基础命令一 Linux的目录结构1 Linux路径的描述方式二 Linux命令入门1 Linux命令基础格式2 ls命令3 HOME目录和工作目录4 ls命令的参数ls 命令的 -a选项ls命令的 -l选项ls命令选项的组合使用ls选项和参数的组合…

基于人工势场法的二维平面内无人机的路径规划的matlab仿真,并通过对势场法改进避免了无人机陷入极值的问题

目录 1.算法描述 2.matlab算法仿真效果 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 人工势场法原理是&#xff1a;首先构建一个人工虚拟势场&#xff0c;该势场由两部分组成&#xff0c;一部分是目标点对移动机器人产生的引力场&#xff0c;方向由机器人指向目标点&#xf…

C语言——malloc开辟矩阵

目录 用动态内存开辟矩阵 矩阵初始化 用动态内存开辟矩阵 动态内存更多的知识在这篇博客&#xff0c;本文将介绍用malloc开辟矩阵。 malloc是C语言中用来动态开辟内存的&#xff0c;通过malloc函数可以向计算机申请一串连续的内存空间。 因为malloc开辟的内存在堆上&#…

数据链路层-封装成帧

封装成帧 数据链路层给上层交付的协议数据单元添加上帧头和帧尾使之成为帧帧头和帧尾包含有重要的控制信息帧头和帧尾的作用之一就是帧定界 透明传输 数据链路层对上层的交付的传输数据没有任何的限制&#xff0c;就好像数据链路层不存在一样面向字节的物理链路使用字节填充(字…