Spring Boot + vue-element 开发个人博客项目实战教程(十五、文章功能实现(下))2

简介: Spring Boot + vue-element 开发个人博客项目实战教程(十五、文章功能实现(下))2

5、文章修改

这里需要注意的是在修改文章的时候可能会修改标签,这里我不管标签有没有修改都先把标签删除掉,然后再添加。

ArticleTagService.java类中再添加一个接口,根据文章id删除关联表的标签数据。

/**
     * 根据文章id删除关联表的标签数据
     *
     * @param articleId
     */
    void deleteTag(Integer articleId);

实现类ArticleTagServiceImpl.java

  @Override
    public void deleteTag(Integer articleId) {
        articleTagMapper.deleteByArticleId(articleId);
    }

数据操作接口ArticleTagMapper.java

    /**
     * 根据文章id删除关联表的数据
     * @param articleId
     */
   void deleteByArticleId(@Param("articleId") Integer articleId);

xml文件的数据操作

 <delete id="deleteByArticleId" parameterType="java.lang.Integer">
      DELETE FROM person_article_tag WHERE article_id = #{articleId}
 </delete>

文章修改的代码:

修改文章基本上和添加的一样,就多了个删除的操作。

    @Override
    public void updateArticle(Article article) {
        articleMapper.updateArticle(article);
        articleMap.put(article.getId(), article);
        //更新文章先把原来的标签删除掉
        articleTagService.deleteTag(article.getId());
        //添加文章标签
        if (article.getTagIdList() != null) {
            List<ArticleTag> articleTagList = article.getTagIdList().stream().map(tagId -> ArticleTag.builder()
                    .tagId(tagId)
                    .articleId(article.getId())
                    .build()).collect(Collectors.toList());
            articleTagService.insertBatch(articleTagList);
        }
    }

6、删除文章

删除文章的时候也要将关联的标签删除掉

  @Override
    public void deleteArticle(Integer articleId) {
        articleMapper.deleteArticle(articleId);
        articleMap.remove(articleId);
        //关联标签删除掉
        articleTagService.deleteTag(articleId);
    }

好啦,还剩一个文章列表的方法

文章列表查询的时候关联的标签也要查出来,所以我们还要根据文章id去查找关联表中的标签

ArticleTagService.java中添加一个查找的接口

/**
     * 根据文章id查找出所有的关联标签数据
     *
     * @param articleId
     * @return
     */
    List<ArticleTag> findArticleTagById(Integer articleId);

实现类:

  @Override
    public List<ArticleTag> findArticleTagById(Integer articleId) {
        List<ArticleTag> articleTagList = articleTagMapper.getArticleTagById(articleId);
        return articleTagList;
    }

数据库接口:

/**
     * 根据文章id查找出所有的关联标签数据
     * @param articleId
     * @return
     */
   List<ArticleTag> getArticleTagById(@Param("articleId") Integer articleId);

xml文件:

  <select id="getArticleTagById" resultMap="BaseResultMap">
        SELECT * FROM person_article_tag WHERE article_id = #{articleId}
    </select>

准备工作完成,接下里修改文章列表,将查找的文章进行遍历,再将标签整合到返回的对象中。

  @Override
    public List<Article> getArticlePage(ArticleBO articleBO) {
        int pageNum = articleBO.getPageNum();
        int pageSize = articleBO.getPageSize();
        PageHelper.startPage(pageNum,pageSize);
        List<Article> articleList = articleMapper.getArticlePage(articleBO);
        List<Tag> tagList = new ArrayList<>();
        if (articleList != null) {
            for (Article article : articleList) {
                List<ArticleTag> articleTags = articleTagService.findArticleTagById(article.getId());
                if (articleTags != null) {
                    for (ArticleTag articleTag : articleTags) {
                        Tag tag = tagService.findTagById(articleTag.getTagId());
                        tagList.add(tag);
                    }
                }
                article.setTagList(tagList);
            }
        }
        return articleList;
    }

好啦,到目前为止,文章的开发整体结束,接下来的一篇写操作日志,还差个登录,基本上我们的博客系统就比较完善了,还有数据的统计,一步步的来,自己也可以先写写。

二、完整代码

这里我粘贴一下完整的代码(只贴修改的类)。供大家参考

1、ArticleServiceImpl.java

package com.blog.personalblog.service.Impl;
import com.blog.personalblog.bo.ArticleBO;
import com.blog.personalblog.config.mail.MailInfo;
import com.blog.personalblog.config.mail.SendMailConfig;
import com.blog.personalblog.entity.Article;
import com.blog.personalblog.entity.ArticleTag;
import com.blog.personalblog.entity.Tag;
import com.blog.personalblog.entity.User;
import com.blog.personalblog.mapper.ArticleMapper;
import com.blog.personalblog.service.ArticleService;
import com.blog.personalblog.service.ArticleTagService;
import com.blog.personalblog.service.TagService;
import com.blog.personalblog.service.UserService;
import com.github.pagehelper.PageHelper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @author: SuperMan
 * @create: 2021-12-01
 */
@Log4j2
@Service
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    ArticleMapper articleMapper;
    @Resource
    ArticleTagService articleTagService;
    @Resource
    UserService userService;
    @Resource
    TagService tagService;
    /**
     * key:文章id
     * value: 文章
     */
    Map<Integer, Article> articleMap = new LinkedHashMap<>();
    @Override
    @PostConstruct
    public void init() {
        List<Article> articleList = articleMapper.findAll();
        try {
            for(Article article : articleList) {
                articleMap.put(article.getId(), article);
            }
            log.info("文章缓存数据加载完成");
        } catch (Exception e) {
            log.error("文章缓存数据加载失败!", e.getMessage());
        }
    }
    @Override
    public List<Article> getArticlePage(ArticleBO articleBO) {
        int pageNum = articleBO.getPageNum();
        int pageSize = articleBO.getPageSize();
        PageHelper.startPage(pageNum,pageSize);
        List<Article> articleList = articleMapper.getArticlePage(articleBO);
        List<Tag> tagList = new ArrayList<>();
        if (articleList != null) {
            for (Article article : articleList) {
                List<ArticleTag> articleTags = articleTagService.findArticleTagById(article.getId());
                if (articleTags != null) {
                    for (ArticleTag articleTag : articleTags) {
                        Tag tag = tagService.findTagById(articleTag.getTagId());
                        tagList.add(tag);
                    }
                }
                article.setTagList(tagList);
            }
        }
        return articleList;
    }
    @Override
    public void saveArticle(Article article) {
        articleMapper.createArticle(article);
        articleMap.put(article.getId(), article);
        //添加文章标签
        if (article.getTagIdList() != null) {
            List<ArticleTag> articleTagList = article.getTagIdList().stream().map(tagId -> ArticleTag.builder()
                    .tagId(tagId)
                    .articleId(article.getId())
                    .build()).collect(Collectors.toList());
            articleTagService.insertBatch(articleTagList);
        }
        User user = userService.findByUserId(article.getUserId());
        //添加文章发送邮箱提醒
        String content = "【{0}】您好:\n" +
                "您已成功发布了标题为: {1} 的文章 \n" +
                "请注意查收!\n";
        MailInfo build = MailInfo.builder()
                .receiveMail(user.getEmail())
                .content(MessageFormat.format(content, user.getUserName(), article.getTitle()))
                .title("文章发布")
                .build();
        SendMailConfig.sendMail(build);
    }
    @Override
    public void updateArticle(Article article) {
        articleMapper.updateArticle(article);
        articleMap.put(article.getId(), article);
        //更新文章先把原来的标签删除掉
        articleTagService.deleteTag(article.getId());
        //添加文章标签
        if (article.getTagIdList() != null) {
            List<ArticleTag> articleTagList = article.getTagIdList().stream().map(tagId -> ArticleTag.builder()
                    .tagId(tagId)
                    .articleId(article.getId())
                    .build()).collect(Collectors.toList());
            articleTagService.insertBatch(articleTagList);
        }
    }
    @Override
    public void deleteArticle(Integer articleId) {
        articleMapper.deleteArticle(articleId);
        articleMap.remove(articleId);
        //关联标签删除掉
        articleTagService.deleteTag(articleId);
    }
    @Override
    public Article findById(Integer articleId) {
        Article article = articleMap.get(articleId);
        if (article == null) {
            Article art = articleMapper.getById(articleId);
            return art;
        }
        return article;
    }
}

2、ArticleTagServiceImpl.java

package com.blog.personalblog.service.Impl;
import com.blog.personalblog.entity.ArticleTag;
import com.blog.personalblog.mapper.ArticleTagMapper;
import com.blog.personalblog.service.ArticleTagService;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
 * @author: SuperMan
 * @create: 2022-01-24
 **/
@Log4j2
@Service
public class ArticleTagServiceImpl implements ArticleTagService {
    @Resource
    ArticleTagMapper articleTagMapper;
    @Override
    public void insertBatch(List<ArticleTag> articleTagList) {
        try {
            articleTagMapper.insertBatch(articleTagList);
        } catch (Exception e) {
            log.error("批量添加文章标签失败!" + e.getMessage());
        }
    }
    @Override
    public void deleteTag(Integer articleId) {
        articleTagMapper.deleteByArticleId(articleId);
    }
    @Override
    public List<ArticleTag> findArticleTagById(Integer articleId) {
        List<ArticleTag> articleTagList = articleTagMapper.getArticleTagById(articleId);
        return articleTagList;
    }
}

3、ArticleTagService.java

package com.blog.personalblog.service;
import com.blog.personalblog.entity.ArticleTag;
import java.util.List;
/**
 * @author: SuperMan
 * @create: 2022-01-24
 **/
public interface ArticleTagService {
    /**
     * 批量插入文章标签数据
     *
     * @param articleTagList
     */
    void insertBatch(List<ArticleTag> articleTagList);
    /**
     * 根据文章id删除关联表的标签数据
     *
     * @param articleId
     */
    void deleteTag(Integer articleId);
    /**
     * 根据文章id查找出所有的关联标签数据
     *
     * @param articleId
     * @return
     */
    List<ArticleTag> findArticleTagById(Integer articleId);
}

4、ArticleTagMapper.java

package com.blog.personalblog.mapper;
import com.blog.personalblog.entity.ArticleTag;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
 * @author: SuperMan
 * @create: 2022-01-24
 **/
@Repository
public interface ArticleTagMapper {
    /**
     * 批量插入
     * @param articleTagList
     */
   int insertBatch(@Param("articleTagList") List<ArticleTag> articleTagList);
    /**
     * 根据文章id删除关联表的数据
     * @param articleId
     */
   void deleteByArticleId(@Param("articleId") Integer articleId);
    /**
     * 根据文章id查找出所有的关联标签数据
     * @param articleId
     * @return
     */
   List<ArticleTag> getArticleTagById(@Param("articleId") Integer articleId);
}

5、ArticleTagMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.blog.personalblog.mapper.ArticleTagMapper">
    <resultMap id="BaseResultMap" type="com.blog.personalblog.entity.ArticleTag">
        <result column="id" jdbcType="INTEGER" property="id"/>
        <result column="article_id" jdbcType="INTEGER" property="articleId"/>
        <result column="tag_id" jdbcType="INTEGER" property="tagId"/>
    </resultMap>
    <insert id="insertBatch">
        INSERT INTO person_article_tag
        <trim prefix="(" suffix=")" suffixOverrides=",">
            article_id, tag_id
        </trim>
        VALUES
        <foreach collection="articleTagList" item="item" separator=",">
            <trim prefix="(" suffix=")" suffixOverrides=",">
                #{item.articleId}, #{item.tagId}
            </trim>
        </foreach>
    </insert>
    <delete id="deleteByArticleId" parameterType="java.lang.Integer">
        DELETE FROM person_article_tag WHERE article_id = #{articleId}
    </delete>
    <select id="getArticleTagById" resultMap="BaseResultMap">
        SELECT * FROM person_article_tag WHERE article_id = #{articleId}
    </select>
</mapper>

三、测试

添加文章测试

这里你要确定标签表里要有添加的标签id。

{
    "author": "码上言1",
    "title": "我的第一篇博客上线啦!",
    "userId": 1,
    "categoryId": 2,
    "content": "这是博客的内容",
    "views": 0,
    "totalWords": 0,
    "commentableId": 1,
    "artStatus": 0,
    "description": "这是备注",
    "imageUrl": "www.baidu.com",
    "tagIdList":[ 1,2]
}

修改和删除大家自己测试一下

目录
相关文章
|
2天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
12 2
|
3天前
|
NoSQL 前端开发 Java
使用 Spring Boot + Neo4j 实现知识图谱功能开发
在数据驱动的时代,知识图谱作为一种强大的信息组织方式,正逐渐在各个领域展现出其独特的价值。本文将围绕使用Spring Boot结合Neo4j图数据库来实现知识图谱功能开发的技术细节进行分享,帮助读者理解并掌握这一技术栈在实际项目中的应用。
38 4
|
6天前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
53 6
|
6天前
|
IDE Java 开发工具
还在为繁琐的配置头疼吗?一文教你如何用 Spring Boot 快速启动,让开发效率飙升,从此告别加班——打造你的首个轻量级应用!
【9月更文挑战第2天】Spring Boot 是一款基于 Spring 框架的简化开发工具包,采用“约定优于配置”的原则,帮助开发者快速创建独立的生产级应用程序。本文将指导您完成首个 Spring Boot 项目的搭建过程,包括环境配置、项目初始化、添加依赖、编写控制器及运行应用。首先需确保 JDK 版本不低于 8,并安装支持 Spring Boot 的现代 IDE,如 IntelliJ IDEA 或 Eclipse。
28 5
|
7天前
|
Java Spring 人工智能
AI 时代浪潮下,Spring 框架异步编程点亮高效开发之路,你还在等什么?
【8月更文挑战第31天】在快节奏的软件开发中,Spring框架通过@Async注解和异步执行器提供了强大的异步编程工具,提升应用性能与用户体验。异步编程如同魔法,使任务在后台执行而不阻塞主线程,保持界面流畅。只需添加@Async注解即可实现方法的异步执行,或通过配置异步执行器来管理线程池,提高系统吞吐量和资源利用率。尽管存在线程安全等问题,但异步编程能显著增强应用的响应性和效率。
19 0
|
18天前
|
SQL 前端开发 NoSQL
SpringBoot+Vue 实现图片验证码功能需求
这篇文章介绍了如何在SpringBoot+Vue项目中实现图片验证码功能,包括后端生成与校验验证码的方法以及前端展示验证码的实现步骤。
SpringBoot+Vue 实现图片验证码功能需求
|
17天前
|
JavaScript
SpringBoot+Vue+ElementUI 实现视频播放 轮播图效果
这篇文章介绍了如何在SpringBoot+Vue+ElementUI项目中使用vue-awesome-swiper插件实现视频播放轮播图效果,包括安装插件、引入项目和使用案例的步骤。
SpringBoot+Vue+ElementUI 实现视频播放 轮播图效果
|
17天前
|
JavaScript 前端开发 Java
SpringBoot + Vue 前端后分离项目精进版本
这篇文章详细介绍了一个基于SpringBoot + Vue的前后端分离项目的搭建过程,包括前端Vue项目的初始化、依赖安装、页面创建和路由配置,以及后端SpringBoot项目的依赖添加、配置文件修改、代码实现和跨域问题的解决,最后展示了项目运行效果。
SpringBoot + Vue 前端后分离项目精进版本
|
17天前
|
缓存 前端开发 JavaScript
前后端分离 SpringBoot+Vue商城买卖系统通杀版本。大家可以参考学习一下
这篇文章介绍了一个使用SpringBoot+Vue开发的前后端分离商城系统,包括技术架构、开发环境、实现的功能以及项目截图,并展示了普通用户和商家端的功能界面。
前后端分离 SpringBoot+Vue商城买卖系统通杀版本。大家可以参考学习一下
|
17天前
|
JavaScript Java 关系型数据库
美妆商城系统 SpringBoot + Vue 【毕业设计 资料 + 源码】
这篇文章介绍了一个使用SpringBoot + Vue + Mybatis + Mysql技术栈开发的美妆商城系统,包括系统功能划分、部分页面截图和前后端源码示例,并提供了GitHub上的源码链接。
美妆商城系统 SpringBoot + Vue 【毕业设计 资料 + 源码】
下一篇
DDNS