Advertisement

Spring boot 搭建个人博客系统(五)——标签和标签云

阅读量:

Spring boot 搭建个人博客系统(五)——标签和标签云

一直想用Spring boot 搭建一个属于自己的博客系统,刚好前段时间学习了叶神的牛客项目课受益匪浅,乘热打铁也主要是学习,好让自己熟悉这类项目开发的基本流程。系统采用Spring boot+MyBatis+MySQL的框架进行项目开发。

项目源码:Jblog
个人主页:tuzhenyu’s page
原文地址:Spring boot 搭建个人博客系统(五)——标签和标签云

0. 思路

标签作为文章中的分类标记,会显示出该文章是关于哪一方面的文章,当我们点击该标签的时候,会出现该博客中所有属于该标签的文章。一篇文章可以对应很多标签,同时一个标签也可以对应很多篇文章,博客系统的标签功能是一种典型的多对多的情况。
解决多对多的标签问题,一般有两种方案。一种是将标签直接以逗号隔开组成一个字符串存储在article表的字段里,这种方案在文章插入和显示时比较简单,可以直接从标签字段里插入或读取,但是在归档同一标签的文章时复杂度较高,需要遍历全部文章记录将标签字段进行分割,看看该记录是否含有此标签,也可以直接使用like语法查询。另一种是将标签存在tag表中,同时创建article_tag关系表用来存储文章和标签的对应关系。在文章插入的同时插入文章标签关系记录,在文章显示的时候通过查询关系表获取article_id或者tag_id来实现标签功能。

1. 数据模型

文章的标签功能需要操作数据库中的tag表和article_tag表,使用MyBatis作为系统的ORM框架用来简化数据操作。

  • 添加数据库表实体类
复制代码
    public class Tag {
    private int id;
    private String name;
    private int count;
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getCount() {
        return count;
    }
    
    public void setCount(int count) {
        this.count = count;
    }
    
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
复制代码
    public class ArticleTag {
    private int id;
    private int articleId;
    private int tagId;
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public int getArticleId() {
        return articleId;
    }
    
    public void setArticleId(int articleId) {
        this.articleId = articleId;
    }
    
    public int getTagId() {
        return tagId;
    }
    
    public void setTagId(int tagId) {
        this.tagId = tagId;
    }
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
  • 添加数据库操作DAO类
复制代码
    @Mapper
    public interface ArticleDao {
    String TABLE_NAEM = " article ";
    String INSERT_FIELDS = " title, describes, content, created_Date, comment_Count, category ";
    String SELECT_FIELDS = " id, " + INSERT_FIELDS;
    
    @Insert({"insert into",TABLE_NAEM,"(",INSERT_FIELDS,") values (#{title},#{describes},#{content}" +
            ",#{createdDate},#{commentCount},#{category})"})
    int insertArticle(Article article);
    
    @Select({"select",SELECT_FIELDS,"from",TABLE_NAEM,"where id=#{id}"})
    Article selectById(int id);
    
    @Select({"select",SELECT_FIELDS,"from",TABLE_NAEM,"order by id desc limit #{offset},#{limit}"})
    List<Article> selectLatestArticles(@Param("offset") int offset, @Param("limit") int limit);
    
    @Select({"select",SELECT_FIELDS,"from",TABLE_NAEM,"where category=#{category} order by id desc limit #{offset},#{limit}"})
    List<Article> selecttArticlesByCategory(@Param("category") String category,@Param("offset") int offset, @Param("limit") int limit);
    
    @Select({"select count(id) from",TABLE_NAEM,"where category=#{category}"})
    int getArticleCountByCategory(@Param("category") String category);
    
    @Select({"select count(id) from",TABLE_NAEM})
    int getArticleCount();
    
    @Update({"update",TABLE_NAEM,"set comment_count = #{commentCount} where id = #{questionId}"})
    void updateCommentCount(@Param("questionId") int questionId,@Param("commentCount") int commentCount);
    
    @Delete({"delete from",TABLE_NAEM,"where id=#{id}"})
    void deleteById(int id);
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
复制代码
    @Mapper
    public interface ArticleTagDao {
    String TABLE_NAEM = " article_tag ";
    String INSERT_FIELDS = " article_id, tag_id ";
    String SELECT_FIELDS = " id, " + INSERT_FIELDS;
    
    String TAG_FIELDS = " id, name, count ";
    String ARTICLE_FIELDS = " id, title, describes, content, created_Date, comment_Count , category ";
    
    @Insert({"insert into",TABLE_NAEM,"(",INSERT_FIELDS,") values (#{articleId},#{tagId})"})
    int insertArticleTag(ArticleTag articleTag);
    
    @Select({"select",TAG_FIELDS,"from tag where id in (select tag_id from article_tag where article_id=#{articleId})"})
    List<Tag> selectByArticleId(int articleId);
    
    @Select({"select",ARTICLE_FIELDS,"from article where id in (select article_id from article_tag where tag_id=#{tagId}) limit #{offset},#{limit}"})
    List<Article> selectByTagId(@Param("tagId") int tagId,@Param("offset") int offset, @Param("limit") int limit);
    
    @Select({"select count(id) from article where id in (select article_id from article_tag where tag_id=#{tagId})"})
    int selectArticleCountByTagId(@Param("tagId") int tagId);
    
    @Delete({"delete from",TABLE_NAEM,"where id=#{id}"})
    void deleteById(int id);
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    

2. 标签功能

博客系统采用文章标签关系表的方式实现博客的标签功能,功能的实现主要包括标签的插入,特定文章所有标签的查询和特定标签所有文章的查询。

(1) 标签的插入:在文章发布的时候,将输入的标签信息插入数据库。如果数据库中已存在欲插入的标签则直接返回标签id,同时在文章标签关系表中插入一条关系记录;如果数据库中未存在欲插入的标签则插入该标签并返回标签id,同时在文章标签关系表中插入一条关系记录;

复制代码
    @RequestMapping("/articleAdd")
    public String addArticle(@RequestParam("title")String title,@RequestParam("category")String category,
                             @RequestParam("tag")String tag,@RequestParam("describe")String describe,
                             @RequestParam("content")String content){
    Article article = new Article();
    article.setTitle(title);
    article.setDescribes(describe);
    article.setCreatedDate(new Date());
    article.setCommentCount(0);
    article.setContent(JblogUtil.tranfer(content));
    article.setCategory(category);
    int articleId = articleService.addArticle(article);
    
    String[] tags = tag.split(",");
    for (String t : tags){
        Tag tag1 = tagService.selectByName(t);
        if (tag1==null){
            Tag tag2 = new Tag();
            tag2.setName(t);
            tag2.setCount(1);
            int tagId = tagService.addTag(tag2);
    
            ArticleTag articleTag = new ArticleTag();
            articleTag.setTagId(tagId);
            articleTag.setArticleId(articleId);
            tagService.addArticleTag(articleTag);
        }else {
            tagService.updateCount(tag1.getId(),tag1.getCount()+1);
    
            ArticleTag articleTag = new ArticleTag();
            articleTag.setTagId(tag1.getId());
            articleTag.setArticleId(articleId);
            tagService.addArticleTag(articleTag);
        }
    }
    
    return "redirect:/";
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    

(2) 特定文章所有标签的查询:文章显示时查询此文章所有标签,先通过本文章标签关系表article_tag查询出所有与该文章关联的标签id,再在标签tag表中根据标签id查询出所有关联标签。

复制代码
     @RequestMapping("/article/{articleId}")
    public String singleArticle(Model model, @PathVariable("articleId")int articleId){
     Article article = articleService.getArticleById(articleId);
     List<Tag> tags = tagService.getTagByArticleId(article.getId());
     model.addAttribute("article",article);
     model.addAttribute("tags",tags);
     return "article";
    }
    
      
      
      
      
      
      
      
      
    

通过子查询获取特定文章的所有标签

复制代码
    @Select({"select",TAG_FIELDS,"from tag where id in (select tag_id from article_tag where article_id=#{articleId})"})
    List<Tag> selectByArticleId(int articleId);
    
    
      
      
      
      
    

(3) 特定标签所有文章的查询:根据标签对文章分类显示时,通过标签查询所有关联文章。先通过本文章标签关系表article_tag查询出所有与该标签关联的文章id,再在文章article表中根据文章id查询出所有关联文章。

复制代码
     @RequestMapping(value = "/tag/{tagId}",method = RequestMethod.GET)
    public String tag(Model model, @PathVariable("tagId")int tagId, @RequestParam("pageId")int pageId){
        List<Article> articles = articleService.getArticlesByTag(tagId,(pageId-1)*4,4);
        List<ViewObject> vos = new ArrayList<>();
        for (Article article:articles){
            ViewObject vo = new ViewObject();
            List<Tag> tags = tagService.getTagByArticleId(article.getId());
            String clickCount = jedisService.get(RedisKeyUntil.getClickCountKey("/article/"+article.getId()));
            if (clickCount==null)
                clickCount = "0";
            vo.set("clickCount",clickCount);
            vo.set("article",article);
            vo.set("tags",tags);
            vos.add(vo);
    }
    model.addAttribute("vos",vos);
    return "tag";
    }
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    

通过子查询获取特定文章的所有标签

复制代码
     @Select({"select",ARTICLE_FIELDS,"from article where id in (select article_id from article_tag where tag_id=#{tagId}) limit #{offset},#{limit}"})
    List<Article> selectByTagId(@Param("tagId") int tagId,@Param("offset") int offset, @Param("limit") int limit);
    
      
      
    

3. 标签云功能

标签云的实现主要是通过一个JS插件jquery-tagclould.js实现的。

复制代码
    <div class="side tags">
     <div class="header"><i class="fa fa-tags" aria-hidden="true"></i><span>Tags</span></div>
      <div id="tagCloud">
    #foreach($tag in $tags)
    <a href="/tag/$!{tag.id}?pageId=1" rel="$!{tag.count}">$!{tag.name}</a>
    #end
      </div>
    </div>
    
      
      
      
      
      
      
      
      
    
复制代码
    $('#tag').tokenfield();
    $('#tagCloud a').tagcloud();
    $.fn.tagcloud.defaults = {
    size: {start: 10, end: 18, unit: 'pt'},
    color: {start: '#aaa', end: '#555'}
    };
    
      
      
      
      
      
      
    

4. 总结

博客系统的标签功能是一种典型的数据库多对多情况,通过建立中间关系表将文章和标签关联起来,进而实现特定文章的标签列表查询和特定标签的文章列表查询。

全部评论 (0)

还没有任何评论哟~