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

来源:互联网 发布:js获取flash对象 编辑:程序博客网 时间:2024/06/07 05:11

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类
@Mapperpublic 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);}
@Mapperpublic 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. 总结

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

原创粉丝点击