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

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

⭐ 作者简介:码上言



⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程



⭐专栏内容:零基础学Java个人博客系统

项目部署视频

https://www.bilibili.com/video/BV1sg4y1A7Kv/?vd_source=dc7bf298d3c608d281c16239b3f5167b

文章目录

前言

小伙伴们原谅我更新的有点慢了,过年事情比较多,前面的一章我们已经把文章的基本功能实现了,但是文章还牵扯到很多的功能,我们的关联表还没有维护,所以还有很多的东西需要去写。我们先把这个写好,如果有时间后边再使用Mybatis-pius更新第二期,先把这个一期搞完再说吧。

一、标签和文章关联表开发

1、关联表实体类

这个很简单,我们就三个字段,新增加一个ArticleTag.java

package com.blog.personalblog.entity;
import lombok.Data;
/**
 * @author: SuperMan
 * @create: 2022-01-14
 */
@Data
@Builder
public class ArticleTag {
    /**
     * id主键
     */
    private Integer id;
    /**
     * 文章id
     */
    private Integer articleId;
    /**
     * 标签id
     */
    private Integer tagId;
}

这个地方用到了一个注解@Builder,这个注解主要使用创建者模式又叫建造者模式。简单来说,就是一步步创建一个对象,它对用户屏蔽了里面构建的细节,但却可以精细地控制对象的构造过程。


@Builder声明实体,表示可以进行Builder方式初始化,@Value注解,表示只公开getter,对所有属性的setter都封闭,即private修饰,所以它不能和@Builder现起用

2、文章增加

接下来我们修改上一篇写的文章增加的方法,我们把文章标签关联加上,在我们添加文章的时候,文章和标签的关联表也要进行添加。

首先在文章的实体类中添加一个属性。

  /**
     * 文章标签添加或更新时使用
     */
    private List<Integer> tagIdList;

接下来我们添加文章的标签

    //添加文章标签
        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);
        }

可能会有些童学没看懂这个操作,我来解释一下这个流程。

首先判断添加的文章是否有标签,然后我们将前端传过来的标签关联的id进行遍历,这里没有使用for循环,而是使用了Java8的.stream().map().collect()用法,这样减少的了代码的行数,看起来比较高大上,精简代码。

steam():把一个源数据,可以是集合,数组,I/O channel, 产生器generator 等,转化成流。

map():用于映射每个元素到对应的结果

Collectors(): 类实现了很多归约操作,例如将流转换成集合和聚合元素。
在以往的版本中,我们要新建一个空的List,然后遍历,再add到List中非常的麻烦,现在一行代码就实现了这个功能,所以在学习中,不能只使用一种方法要多用集中方法去实现。


我们拿到遍历的List<ArticleTag>,然后批量去插入关联表,这是我们创建一个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);
}

有了接口就要有接口的实现类,我们再创建一个实现类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());
        }
    }
}

这个也没有什么可以讲的,和我们之前的批量插入差不多。

接下来对数据库操作,我们需要创建一个关联表的Mapper接口,对数据库进行操作。

新建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);
}

然后再新建一个xml来写sql语句,相信大家这一套流程基本上熟悉了。

新建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>
</mapper>

这里的批量插写的sql语句和之前的有点不太一样,使用了trim标签。


mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。

使用也非常的简单,就是省略了之前的and关键字等。其余的都差不多,也使用了foreach循环。

好啦,到此添加的功能基本上完善了。

3、邮箱发送

我在写的过程中又突然想到了邮箱的功能,反正做项目的目的就是学习,索性我就把邮箱的功能也加入到了文章添加中,我们在添加文章成功后,会发一条成功创建一条文章到你的邮箱上,接收的邮箱是你的创建用户的时候的邮箱,发送的邮箱我们在后台写死,不能对它操作。如果你想挑战的话也可以把发送邮箱写活,配置不同的发送邮箱,可以自己尝试。我这里就不写了,有问题可以问我。


其实很简单,我把邮箱的发送核心都简单化了,只要两个类即可,接下来我们就来完成这个功能。

在我们的config包中新建一个mail包,然后创建一个MailInfo.java实体类和SendMailConfig.java类。


MailInfo.java类主要是用来存放接收的邮箱、标题和邮件内容。具体如下代码:

注意这里也使用了@Builder

package com.blog.personalblog.config.mail;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
 * 邮件接收配置信息
 *
 * @author: SuperMan
 * @create: 2022-01-24
 **/
@Builder
@Data
public class MailInfo {
    /**
     * 接收的邮箱
     */
    private String receiveMail;
    /**
     * 邮件标题
     */
    private String title;
    /**
     * 邮件内容
     */
    private String content;
}

接下来我们要实现邮件发送的方法,这里我们使用了Hutool的邮件发送。

参考官方文档:

https://www.hutool.cn/docs/#/extra/%E9%82%AE%E4%BB%B6%E5%B7%A5%E5%85%B7-MailUtil

3.1、引用

Hutool对所有第三方都是可选依赖,因此在使用MailUtil时需要自行引入第三方依赖。

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

3.2、邮件服务器配置

注意 邮件服务器必须支持并打开SMTP协议


这里我们使用qq邮箱作为发送邮箱,我们需要开通一下我们qq邮箱配置,我们先移步到qq邮箱,使用电脑登录qq邮箱,然后在顶部找到设置->账户

见腾讯的帮助说明:https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256

然后往下找,找到标题为:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务然后开启这两个,会提示你发送你一条短信,发送完成后,会有一个授权码,把那个授权码保存下来,那个就是我们发送的密码。

接下里我们去写邮件发送配置SendMailConfig.java

package com.blog.personalblog.config.mail;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.log4j.Log4j2;
/**
 * 邮件发送
 * @author: SuperMan
 * @create: 2022-01-24
 **/
@Log4j2
public class SendMailConfig {
    /**
     * 邮件发送实现方法
     * @param mailInfo
     */
    public static void sendMail(MailInfo mailInfo) {
        try {
            MailAccount account = new MailAccount();
            //邮件服务器的SMTP地址
            account.setHost("smtp.qq.com");
            //邮件服务器的SMTP端口
            account.setPort(587);
            //发件人邮箱,改成你自己的
            account.setFrom("13323232332@qq.com");
            //密码,刚开通的授权码
            account.setPass("WYUSTGBIISYSCAIC");
            //使用SSL安全连接
            account.setSslEnable(false);
            MailUtil.send(account, mailInfo.getReceiveMail(),
                    mailInfo.getTitle(), mailInfo.getContent(), false);
            log.info("邮件发送成功!");
        } catch (Exception e) {
            log.error("邮件发送失败" + JSONUtil.toJsonStr(mailInfo));
        }
    }
}

我把邮箱发送功能封装成了类,我们在那边使用到直接调用这个方法即可,传三个参数即可。MailAccountMailUtilHutool的类,我们引入包直接使用即可。

可以参考Hutool给的例子:邮件服务器的SMTP地址

host = smtp.yeah.net

邮件服务器的SMTP端口

port = 465

发件人(必须正确,否则发送失败)

from = hutool@yeah.net

用户名(注意:如果使用foxmail邮箱,此处user为qq号)

user = hutool

密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)

pass = q1w2e3

使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。

starttlsEnable = true

使用SSL安全连接

sslEnable = true

指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字

socketFactoryClass = javax.net.ssl.SSLSocketFactory

如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true

socketFactoryFallback = true

指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口456

socketFactoryPort = 465

SMTP超时时长,单位毫秒,缺省值不超时

timeout = 0

Socket连接超时值,单位毫秒,缺省值不超时

connectionTimeout = 0


配置完成后,我们在添加文章成功后进行发送,还是添加文章的实现方法中调用发送邮箱的方法。

4、添加根据用户id查找用户

这里我们使用的是用户信息中的邮箱,我们需要获取到是哪个用户发布的文章,根据用户id去查找用户对象。我们打开UserService.java,添加一个根据用户id查找对象的接口。

    /**
     * 根据用户id查找用户
     * @param userId
     * @return
     */
    User findByUserId(Integer userId);

然后在实现类中实现这个接口

    @Override
    public User findByUserId(Integer userId) {
        User user = userMapper.getUserById(userId);
        return user;
    }

再对数据库进行操作,在UserMapper.java中增加一个dao接口

    /**
     * 根据用户id查找
     * @param userId
     * @return
     */
    User getUserById(Integer userId);

然后在xml中添加sql语句

<select id="getUserById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
     select * from person_user where id = #{userId, jdbcType=INTEGER}
</select>

完成之后,我们回到ArticleServiceImpl.java实现类中,在添加文章的方法中添加邮箱发送。

 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);

说明:首先根据用户id去查找该用户的信息,然后创建邮件内容,{0}、{1}是占位符,进行补充内容。然后创建对象并设置值,在这里的邮箱是接收邮件的邮箱,最后调用发送邮箱的方法即可。

到目前为止,我们的添加文章到此写完了,下面还有文章修改也要修改标签关联基本上和添加一样。

目录
相关文章
|
1月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
352 3
|
10天前
|
前端开发 安全 Java
基于springboot+vue开发的会议预约管理系统
一个完整的会议预约管理系统,包含前端用户界面、管理后台和后端API服务。 ### 后端 - **框架**: Spring Boot 2.7.18 - **数据库**: MySQL 5.6+ - **ORM**: MyBatis Plus 3.5.3.1 - **安全**: Spring Security + JWT - **Java版本**: Java 11 ### 前端 - **框架**: Vue 3.3.4 - **UI组件**: Element Plus 2.3.8 - **构建工具**: Vite 4.4.5 - **状态管理**: Pinia 2.1.6 - **HTTP客户端
91 4
基于springboot+vue开发的会议预约管理系统
|
10天前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
162 4
|
1月前
|
前端开发 JavaScript Java
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
本系统基于SpringBoot与Vue3开发,实现校园食堂评价功能。前台支持用户注册登录、食堂浏览、菜品查看及评价发布;后台提供食堂、菜品与评价管理模块,支持权限控制与数据维护。技术栈涵盖SpringBoot、MyBatisPlus、Vue3、ElementUI等,适配响应式布局,提供完整源码与数据库脚本,可直接运行部署。
81 0
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
|
2月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
311 13
|
3月前
|
监控 数据可视化 JavaScript
springboot + vue的MES系统生产计划管理源码
MES系统(制造执行系统)的生产计划管理功能是其核心模块之一,涵盖生产计划制定与优化、调度排程、进度监控反馈、资源管理调配及可视化报告五大方面。系统基于SpringBoot + Vue-Element-Plus-Admin技术栈开发,支持多端应用(App、小程序、H5、后台)。通过实时数据采集与分析,MES助力企业优化生产流程,适用于现代化智能制造场景。
156 1
|
3月前
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
478 2
|
4月前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
|
3月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
386 0