⭐ 作者简介:码上言
⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程
项目部署视频
https://www.bilibili.com/video/BV1sg4y1A7Kv/?vd_source=dc7bf298d3c608d281c16239b3f5167b
文章目录
- 1、ArticleServiceImpl.java
- 2、ArticleTagServiceImpl.java
- 3、ArticleTagService.java
- 4、ArticleTagMapper.java
- 5、ArticleTagMapper.xml
前言
小伙伴们原谅我更新的有点慢了,过年事情比较多,前面的一章我们已经把文章的基本功能实现了,但是文章还牵扯到很多的功能,我们的关联表还没有维护,所以还有很多的东西需要去写。我们先把这个写好,如果有时间后边再使用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)); } } }
我把邮箱发送功能封装成了类,我们在那边使用到直接调用这个方法即可,传三个参数即可。MailAccount
和MailUtil
是Hutool
的类,我们引入包直接使用即可。
可以参考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}是占位符,进行补充内容。然后创建对象并设置值,在这里的邮箱是接收邮件的邮箱,最后调用发送邮箱的方法即可。
到目前为止,我们的添加文章到此写完了,下面还有文章修改也要修改标签关联基本上和添加一样。