在mblog中实现了给文章添加tag的功能
具体效果如下:
-
首先在用户发表文章的界面,增加了增添标签的选项:
-
顶部上方添加了标签栏目:
-
点击进入可以获得当前所有标签:
-
点击标签可获得当前所有已发表文章:
对于这一业务功能的实现思路以及关键步骤如下:
- 需要在数据库中增添tag表,同时,由于发表的文章和标签是多对多的关系,因此需要建立一个post和tag的关系表。
同时建立相应的实体类,利用jpa的持久化功能对应相应的数据表:
- 通过jpa实现dao层接口
实现了两个Repository
其中,TagRepository实现了基本的查询接口,通过标签名获取标签类,以及如果文章被删除,那么则修改当前标签下的发表文章数量。
PostTagRepository实现了通过id获取postTag列表,其中涉及到多表的连接查询,以及删除后的更新操作。
- 实现service层的具体业务逻辑
TagService中:
利用jpa中的page和pageable类实现查询结果的分页。
将所有tag分页查询并返回一个page泛型类。
展示每个tag下的文章列表的简要标题信息。
更新当前tag下的发布信息,这是由于文章会有所变化。
当文章删除时,更改数据表中相关的映射关系。
在完成TagService后,在原有的PostService中需要添加部分代码:
这是由于在发布文章之后,需要再次更新标签中的数据。
- 编写Controller:
/**
- 标签控制器
*/
@Controller
public class TagController extends BaseController {
@Autowired
private TagService tagService;
/**
* 展示标签列表的页面
* @param model
* @return
*/
@RequestMapping("/tags")
public String index(ModelMap model) {
/**
* 包装分类对象,设置排序规律,最新更新的文章放在对应tag中的最前面
*/
Pageable pageable = wrapPageable(Sort.by(Sort.Direction.DESC, "updated"));
/**
* 获得分页对象
*/
Page<TagVO> page = tagService.pagingQueryTags(pageable);
model.put("results", page);
/**
* 展示页面
*/
return view(Views.TAG_INDEX);
}
/**
* 点击对应tag后进入的文章列表页面
* @param name
* @param model
* @return
*/
@RequestMapping("/tag/{name}")
public String tag(@PathVariable String name, ModelMap model) {
/**
* 设置优先级,该优先级取决于文章的权重,与文章的阅读量,评论量有关
*/
Pageable pageable = wrapPageable(Sort.by(Sort.Direction.DESC, "weight"));
Page<PostTagVO> page = tagService.pagingQueryPosts(pageable, name);
model.put("results", page);
model.put("name", name);
return view(Views.TAG_VIEW);
}
}
其中,非常有用的是利用了原作者编写的BaseCotroller,因为在该Controller中,作者定义了分页查询类的排序方式是如何去包装的,可以根据自定义的优先级去定义最终查询的页面的显示列表的排序情况。
因此,就可以实现标签列表的显示优先级,以及对应各个列表中文章显示的优先级。
5. 编写前端页面与Controller交互:
Index.ftl展示了标签模块下的所有标签列表:
<@layout.put block="contents">
<div class="row">
<div class="col-xs-12 col-md-9 side-left">
<div class="panel panel-default">
<div class="panel-body streams-tags">
<#list results.content as row>
<#assign post = row.post />
<div class="col-sm-6 row-item">
<h2 class="title">
<a href="${base}/tag/${row.name}/"><i class="fa fa-quote-left"></i> ${row.name}</a>
<span class="label label-default">${row.posts}</span>
</h2>
<#if post??>
<div class="media">
<div class="media-left">
<@utils.showAva post.author "media-object"/>
</div>
<div class="media-body">
<h4 class="media-heading">
<a href="${base}/post/${post.id}">${post.title?html}</a>
</h4>
</div>
</div>
</#if>
</div>
</#list>
<#if results.content?size == 0>
<li class="ajax-load-con content">
<div class="content-box posts-aside">
<div class="posts-default-content">该目录下还没有内容!</div>
</div>
</li>
</#if>
</div>
</div>
<!-- Pager -->
<div class="text-center">
<@utils.pager request.requestURI!"", results, 5/>
</div>
</div>
View.ftl展示了当点击进入标签后,展示的已经发布的文章列表:
<div class="row streams">
<div class="col-xs-12 col-md-9 side-left">
<div class="panel panel-default">
<div class="panel-heading">
<ul class="list-inline topic-filter">
<li class="popover-with-html">
标签: ${name} 共 ${results.totalElements} 个结果.
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="panel-body remove-padding-horizontal">
<ul class="list-group row topic-list">
<#list results.content as row>
<#assign post = row.post />
<li class="list-group-item ">
<a class="reply_count_area hidden-xs pull-right" href="#">
<div class="count_set">
<span class="count_of_votes" title="阅读数">${post.views}</span>
<span class="count_seperator">/</span>
<span class="count_of_replies" title="回复数">${post.comments}</span>
<span class="count_seperator">/</span>
<span class="count_of_visits" title="点赞数">${post.favors}</span>
<span class="count_seperator">|</span>
<abbr class="timeago">${timeAgo(post.created)}</abbr>
</div>
</a>
<div class="avatar pull-left">
<@utils.showAva post.author "media-object img-thumbnail avatar avatar-middle"/>
</div>
<div class="infos">
<div class="media-heading">
<#--<span class="hidden-xs label label-warning">${row.channel.name}</span>-->
<a href="${base}/post/${post.id}">${post.title}</a>
</div>
</div>
</li>
</#list>
<#if results.content?size == 0>
<li class="list-group-item ">
<div class="infos">
<div class="media-heading">该目录下还没有内容!</div>
</div>
</li>
</#if>
</ul>
</div>
<div class="panel-footer text-right remove-padding-horizontal pager-footer">
<@utils.pager request.requestURI, results, 5/>
</div>
</div>
</div>
<div class="col-xs-12 col-md-3 side-right">
<#include "/default/inc/right.ftl" />
</div>
在editing.ftl中添加增加标签的模块: