springboot+vue+mybatis-plus写一个文章点赞功能

以下是使用 Spring Boot + Vue + Mybatis - Plus 实现文章点赞功能的步骤:

后端实现(Spring Boot + Mybatis - Plus)

  1. 数据库设计
    创建article表和article_like表。article表存储文章信息,article_like表用于记录点赞信息,结构如下:

article表:

字段名类型说明
idbigint文章 ID(主键)
titlevarchar文章标题
contenttext文章内容
like_countint点赞数(初始值为 0)

article_like表:

字段名类型说明
idbigint点赞记录 ID(主键)
article_idbigint文章 ID(外键,关联article表的id
user_idbigint用户 ID(假设你有用户系统)

 2.创建实体类

  • Article
import com.baomidou.mybatisplus.annotation.IdentityStrategy;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("article")
public class Article {
    @TableId(type = IdentityStrategy.AUTO)
    private Long id;
    private String title;
    private String content;
    private Integer likeCount = 0;
}

 ArticleLike

import com.baomidou.mybatisplus.annotation.IdentityStrategy;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("article_like")
public class ArticleLike {
    @TableId(type = IdentityStrategy.AUTO)
    private Long id;
    private Long articleId;
    private Long user_id;
}
  1. 创建 Mapper 接口
    • ArticleMapper接口:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Article;

@Repository
public interface ArticleMapper extends BaseMapper<Article> {
}

 

  • ArticleLikeMapper接口:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import com.example.demo.model.ArticleLike;

@Repository
public interface ArticleLikeMapper extends BaseMapper<ArticleLike> {
}

 创建 Service 层

  • ArticleService接口:
import com.example.demo.model.Article;
import com.baomidou.mybatisplus.extension.service.IService;

public interface ArticleService extends IService<Article> {
    void incrementLikeCount(Long articleId);
}
  • ArticleServiceImpl类:
import com.example.demo.mapper.ArticleMapper;
import com.example.demo.model.Article;
import com.example.demo.service.ArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    @Override
    @Transactional
    public void incrementLikeCount(Long articleId) {
        Article article = getById(articleId);
        if (article!= null) {
            article.setLikeCount(article.getLikeCount() + 1);
            updateById(article);
        }
    }
}

 ArticleLikeService接口:

import com.example.demo.model.ArticleLike;
import com.baomidou.mybatisplus.extension.service.IService;

public interface ArticleLikeService extends IService<ArticleLike> {
    boolean isLikedByUser(Long articleId, Long userId);
    void likeArticle(Long articleId, Long userId);
}

 ArticleLikeServiceImpl

import com.example.demo.mapper.ArticleLikeMapper;
import com.example.demo.model.ArticleLike;
import com.example.demo.service.ArticleLikeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
public class ArticleLikeServiceImpl extends ServiceImpl<ArticleLikeMapper, ArticleLike> implements ArticleLikeService {
    @Override
    public boolean isLikedByUser(Long articleId, Long userId) {
        return lambdaQuery()
              .eq(ArticleLike::getArticleId, articleId)
              .eq(ArticleLike::getUser_id, userId)
              .count() > 0;
    }

    @Override
    @Transactional
    public void likeArticle(Long articleId, Long userId) {
        if (!isLikedByUser(articleId, userId)) {
            ArticleLike articleLike = new ArticleLike();
            articleLike.setArticleId(articleId);
            articleLike.setUser_id(userId);
            save(articleLike);
        }
    }
}
  1. 创建 Controller 类
import com.example.demo.service.ArticleLikeService;
import com.example.demo.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/article")
public class ArticleController {
    @Autowired
    private ArticleService articleService;
    @Autowired
    private ArticleLikeService articleLikeService;

    // 点赞文章接口
    @PostMapping("/{articleId}/like")
    public void likeArticle(@PathVariable Long articleId, @RequestHeader("user-id") Long userId) {
        articleLikeService.likeArticle(articleId, userId);
        articleService.incrementLikeCount(articleId);
    }

    // 查询文章是否被用户点赞接口
    @GetMapping("/{articleId}/isLiked")
    public boolean isLiked(@PathVariable Long articleId, @RequestHeader("user-id") Long userId) {
        return articleLikeService.isLikedByUser(articleId, userId);
    }
}

前端实现(Vue)

  1. 创建点赞组件(LikeButton.vue

 

<template>
  <button @click="toggleLike">{{ liked? '取消点赞' : '点赞' }}</button>
</template>

<script>
export default {
  props: {
    articleId: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      liked: false
    };
  },
  methods: {
    async toggleLike() {
      const userId = this.$store.getters.userId; // 假设从Vuex存储中获取用户ID
      if (this.liked) {
        // 取消点赞请求
        await this.$axios.delete(`/article/${this.articleId}/like`, {
          headers: { 'user - id': userId }
        });
      } else {
        // 点赞请求
        await this.$axios.post(`/article/${this.articleId}/like`, null, {
          headers: { 'user - id': userId }
        });
      }
      this.liked =!this.liked;
    },
    async checkLiked() {
      const userId = this.$store.getters.userId;
      const response = await this.$axios.get(`/article/${this.articleId}/isLiked`, {
        headers: { 'user - id': userId }
      });
      this.liked = response.data;
    }
  },
  mounted() {
    this.checkLiked();
  }
};
</script>
  1. 在文章展示页面使用点赞组件

 

<template>
  <div>
    <h2>{{ article.title }}</h2>
    <p>{{ article.content }}</p>
    <LikeButton :articleId="article.id" />
  </div>
</template>

<script>
import LikeButton from '@/components/LikeButton.vue';
export default {
  components: {
    LikeButton
  },
  data() {
    return {
      article: {}
    };
  },
  // 假设通过接口获取文章数据并赋值给article
  mounted() {
    // 获取文章数据的逻辑
  }
};
</script>

 上述代码中的@RequestHeader("user - id")假设你在请求头中传递用户 ID,实际应用中可能需要根据你的认证和授权机制进行调整。

在实际应用中,你可能需要考虑更多的功能,如取消点赞时减少点赞数、性能优化等。

概要介绍:本门课程属于“Java分布式中间件大汇聚实战”系列课程,主要介绍了企业级项目中真实的应用场景的实现及主流的Java核心技术栈(Redis、RabbitMQ、Spring AOP、Redisson、ZooKeeper…)的实战等等。除此之外,还介绍了如何基于Redis设计并实战一款系统(、取消、排行榜、用户中心、文章用户列…)可以说技术干货甚多,不仅可以巩固企业级应用系统的开发实战能力,相信在面试、跳槽涨薪方面也能带来相应的帮助!课程内容:传说中的金三银四、面试跳槽涨薪季已经来临,Debug特地为大家准备了一系列跟面试、跳槽、巩固核心技术栈相关的课程,本门课程属于第一季,其中的内容包括企业级项目中真实的应用场景实战、面试相关的技术分享、主流的Java技术栈(Undertow、Redis、RabbitMQ、Spring AOP、Redisson、ZooKeeper…)实战等等。除此之外,我们还基于Redis设计并实战了一款系统,可以说技术干货甚多。在课程的最后,Debug给大家整理了一份最新的面向BAT大厂招聘 ~ 2020年程序猿最新的Java面试题(附带目录和答案),希望对各位小伙伴的成长有所帮助!值得一提的是,本季课程实战的应用场景包括“日志记录”、“邮件发送”、“通告消息通知”、“短信验证码失效验证”、“会员到期自动提醒/到期前N天自动提醒”以及“系统”的设计与实战,其大纲如下所示:其中,涉及到的技术栈包括Spring Boot2.0、Mybatis、Undertow、Redis、RabbitMQ、Redisson、Spring AOP、 Java8…下面罗列出本门课程重介绍的价格应用案例以及业务场景的实现流程图!(1)基于Spring的消息驱动模型实现日志的异步记录:(2)基于消息中间件RabbitMQ的消息队列实现日志的异步记录:(3)基于缓存中间件Redis的订阅发布机制实现商户公告消息通知:(4)基于Redis的Key失效与定时任务实现实现短信验证码的过期失效验证:其他核心、典型的应用案例和业务场景的实战可以详细参考“课程目录”!除此之外,我们还基于缓存中间件Redis设计并实战实现了系统中的功能模块,下面罗列出其中涉及到的相关功能模块的实战流程图:其课程收益如下所示:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值