您的位置:首页 > 编程语言 > Java开发

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

2017-08-21 21:10 441 查看

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. 总结

  博客系统的标签功能是一种典型的数据库多对多情况,通过建立中间关系表将文章和标签关联起来,进而实现特定文章的标签列表查询和特定标签的文章列表查询。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: