Spring Boot + vue-element 开发个人博客项目实战教程(三十一、项目完善)

270 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

前言

这一篇将是我们项目开发的最后一篇文章了,到这里该和大家说再见了,这个项目从开始写到现在刚好一年了,有时间就写写,中间断了好几个月的时间,看到好多人说对他们很有用,我写的也就变成了有意义的事情,希望大家都不忘初心,牢记使命,认真的学习技术和好好地生活。

正如士兵突击中的许三多说的,好好活,就是做有意义的事,做有意义的事情,就是好好活着。

1、项目完善

1.1、文章创建完后在编辑标签没有展示

这是上一篇的bug,我在测试文章添加后,然后再点击编辑后,发现标签的值并没有,我查看了接口返回的数据为空,发现是后端添加文章存入缓存的问题,这里修改一下,只要加一行代码即可,大家可以提前想一下。

先分析一下我们调用的方法findById。

 @Override
    public ArticleVO findById(Integer articleId) {
        Article article = articleMap.get(articleId);

只看这一句即可,文章的数据来自map中,然而再添加文章的时候,map只存的是页面传来的数据,并没有将标签的数据给map,所以查出来的话肯定没有标签数据。

可以在文章添加的实现类中直接加上一下这行代码,在我们添加文章之后,在调用init重新加载一下缓存里的数据

this.init();

完整代码:

@Override
    public void insertOrUpdateArticle(ArticleInsertBO bo) {
        //分类添加
        Category category = saveCategory(bo);
        Article article = BeanUtil.copyProperties(bo, Article.class);
        if (category != null) {
            article.setCategoryId(category.getCategoryId());
        }
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        User user = userService.getUserByUserName(username);
        article.setUserId(user.getId());
        article.setAuthor(user.getUserName());
        article.setViews(0L);
        article.setTotalWords(WordCountUtil.wordCount(bo.getContent()));
        if (bo.getId() != null) {
            articleMapper.updateArticle(article);
        } else {
            articleMapper.createArticle(article);
        }
        articleMap.put(article.getId(), article);
        //添加文章标签
        saveTags(bo, article.getId());
        this.init();
        //添加文章发送邮箱提醒
        try {
            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);
        } catch (Exception e) {
            log.error("邮件发送失败{}", e.getMessage());
        }

    }

1.2、文章字数统计实现

我们在文章的数据表中预留了一个文章的字数,一开始的时候我直接赋值的是0,现在我们要把字数统计给加上,所以需要写一个字数统计的工具类。

package com.blog.personalblog.util;

/**
 * @author: SuperMan
 * @create: 2022-10-14
 **/
public class WordCountUtil {

    /**
     * 统计字数, 空格不统计
     * @param string
     * @return
     */
    public static long wordCount(String string) {
        if (string == null) {
            return 0;
        }
        long letterCount = 0L;
        long numCount = 0L;
        long otherCount = 0L;

        String str = string.trim();
        char[] chr = str.toCharArray();
        for(int i = 0; i < chr.length;i++){
            if(Character.isLetter(chr[i])){
                letterCount++;
            } else if(Character.isDigit(chr[i])){
                numCount ++;
            } else{
                otherCount ++;
            }
        }
        return letterCount + numCount + otherCount;
    }
}

还是在添加的方法中来统计文章字数。将原来的article.setTotalWords(0L) 改成以下代码:

 article.setTotalWords(WordCountUtil.wordCount(bo.getContent()));

查看页面效果:

1.3、发布文章新建分类修改

我在测试的时候,发布文章没有选择从数据库查出来的分类,而是自己创建的一个分类,点击发布会报错。

首先定位到代码错误的信息。

   private Category saveCategory(ArticleInsertBO bo) {
        if (StrUtil.isEmpty(bo.getCategoryName())) {
            return null;
        }
        Category category = categoryService.getCategoryByName(bo.getCategoryName());
        if (category == null && !ArticleArtStatusEnum.DRAFT.getStatus().equals(bo.getArtStatus())) {
            category.setCategoryName(bo.getCategoryName());
            categoryService.saveCategory(category);
        }
        return category;
    }

Category category = categoryService.getCategoryByName(bo.getCategoryName());

这一句我们拿前端传过来的分类名去查找,然后没有找到,我们又将前端的值赋给了它,就报错了。

我们拿到的category是一个null,而null对象在堆中会被java的垃圾回收机制回收。所以这里赋值直接报错了,所以我们再重新new一个分类对象即可。

 private Category saveCategory(ArticleInsertBO bo) {
        if (StrUtil.isEmpty(bo.getCategoryName())) {
            return null;
        }
        Category category = categoryService.getCategoryByName(bo.getCategoryName());
        Category newCategory = new Category();
        if (category == null && !ArticleArtStatusEnum.DRAFT.getStatus().equals(bo.getArtStatus())) {
            newCategory.setCategoryName(bo.getCategoryName());
            categoryService.saveCategory(newCategory);
            return newCategory;
        }
        return category;
}

1.4、邮件发送配置修改

这里我把邮箱的配置进行了修改,原来配置的邮箱信息是在代码里配置的,维护不太方便,我把它提到了配置文件中了。以后修改邮箱信息直接修改配置文件,就不需要找代码了。打开application.yml

send:
  mail:
    host: # 邮件服务器的SMTP地址
    port: # 邮件服务器的SMTP端口
    from: # 发件人
    pass: # 密码

然后修改代码,打开SendMailConfig.java,将配置信息引入进来。

    @Value("${send.mail.host}")
    private String host;

    @Value("${send.mail.port}")
    private Integer port;

    @Value("${send.mail.from}")
    private String from;

    @Value("${send.mail.pass}")
    private String pass;

public void sendMail(MailInfo mailInfo) {
        try {
            MailAccount account = new MailAccount();
            //邮件服务器的SMTP地址
            account.setHost(host);
            //邮件服务器的SMTP端口
            account.setPort(port);
            //发件人
            account.setFrom(from);
            //密码
            account.setPass(pass);
            //使用SSL安全连接
            account.setSslEnable(false);
            MailUtil.send(account, mailInfo.getReceiveMail(),
                    mailInfo.getTitle(), mailInfo.getContent(), false);
            log.info("邮件发送成功!");
        } catch (Exception e) {
            log.error("邮件发送失败" + JSONUtil.toJsonStr(mailInfo));
        }

    }

添加完之后,再去测试下。

1.5、登录页改造升级

我们现在的登录页面非常的原始,不太好看,俗话说人靠衣服马靠鞍,我们也将登录的入口进行改造,后端的逻辑不用动,我们只改前端代码即可。

<style rel="stylesheet/scss" lang="scss">
$bg:#889aa4;
$light_gray:#eaeaea;

/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: 85%;
    input {
      background: transparent;
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      color: black;
      height: 47px;
      &:-webkit-autofill {
        -webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
        -webkit-text-fill-color: black !important;
      }
    }
  }
  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}

</style>

<style rel="stylesheet/scss" lang="scss" scoped>
$bg:#889aa4;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
  position: fixed;
  height: 100%;
  width: 100%;
  background:url("../../assets/bj.jpg");
  position:fixed;
  background-size:100% 100%;
  // background-image: "../../assets/bg.jpg";
  .login-form {
    position: absolute;
    left: 0;
    right: 0;
    width: 520px;
    max-width: 100%;
    padding: 35px 35px 15px 35px;
    margin: 120px auto;
  }
  .tips {
    font-size: 14px;
    color: #fff;
    margin-bottom: 10px;
    span {
      &:first-of-type {
        margin-right: 16px;
      }
    }
  }
  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
  }
  .title {
    font-size: 28px;
    font-weight: 400;
    margin: 0px auto 40px auto;
    text-align: center;
    font-weight: bold;
  }
  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    cursor: pointer;
    user-select: none;
  }
  
}
</style>

这里只修改了一些样式和添加了一个背景图片。也算是有点样子了。