小Hub领读:
项目eblog的第5篇讲解文章,今天我们来填充一下项目首页的数据,我们会用到自定义Freemaker标签等技术,来看看如何使用标签来填充内容吧。
项目名称:eblog
项目 Git 仓库:https://github.com/MarkerHub/eblog(给个 star 支持哈)
前几篇项目讲解文章:
1、Github 上最值得学习的 Springboot 开源博客项目!
自定义freemarker标签
首先要来弄的是置顶的数据。为了让大家能对freemarker有更多的了解,我们定义一个freemarker标签,然后使用标签去展示我们的数据。
想要自定义freemarker标签需要实现这个接口并且重写excute方法:
public interface TemplateDirectiveModel extends TemplateModel {
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException;
}
上面的参数如下:
env:系统环境变量,通常用它来输出相关内容,如Writer out = env.getOut()。
params:自定义标签传过来的对象,其key=自定义标签的参数名,value值是TemplateModel类型,而TemplateModel是一个接口类型,通常我们都使用TemplateScalarModel接口来替代它获取一个String 值,如TemplateScalarModel.getAsString();当然还有其它常用的替代接口,如TemplateNumberModel获取number,TemplateHashModel等。
loopVars 循环替代变量。
body 用于处理自定义标签中的内容,如<@myDirective>将要被处理的内容;当标签是<@myDirective />格式时,body=null。
但是直接这些参数来处理我们业务其实还有点麻烦,为了更好使用这个接口,我们需要再封装多一层,这里我引用了mblog项目的对这个接口的封装。
com.example.common.template
DirectiveHandler
TemplateDirective
TemplateModelUtils
上面的3个类我都是在mblog项目中复制过来的,就改了一下包路径
mblog原路径:
https://gitee.com/mtons/mblog/tree/master/src/main/java/com/mtons/mblog/modules/template
有了上面的封装之后,我们要定义个标签模板只需要继承TemplateDirective,重写getName()和excute(DirectiveHandler handler);可以看到excute方法中之后handler了,这个handler我们使用起来就很简便了。
下面我们来定义一个博客列表的标签com.example.templates.PostsTemplate
@Component
public class PostsTemplate extends TemplateDirective {
@Autowired
PostService postService;
@Override
public String getName() {
return "posts";
}
@Override
public void execute(DirectiveHandler handler) throws Exception {
Long categoryId = handler.getLong("categoryId", 0);
int pn = handler.getInteger("pn", 1);
int size = handler.getInteger("size", 10);
String order = handler.getString("order", "created");
Page page = new Page(pn, size);
IPage results = postService.paging(page, categoryId, order);
handler.put(RESULTS, results).render();
}
}
上面的代码可以知道,我们标签有几个参数:categoryId、pn、size、order。然后封装成了两个类:Page、QueryWrapper,都是mybatis-plus里面的封装类,用于分页和参数查询。
为了可以做缓存,这里我们没有直接传QueryWrapper过去,而是直接传参数过去,这样我们可以用参数作为缓存的key。
下面我们去具体看看postService.paging(Page page, Long categoryId, String order);方法。
@Override
@Cacheable(cacheNames = "cache_post", key = "'page_' + #page.current + '_' + #page.size " +
"+ '_query_' +#categoryId + '_' + #order")
public IPage paging(Page page, Long categoryId, String order) {
QueryWrapper wrapper = new QueryWrapper<Post>()
.eq(categoryId != 0, "category_id", categoryId)
.orderByDesc(order);
IPage<PostVo> pageData = postMapper.selectPosts(page, wrapper);
return pageData;
}
上面接口又调用了mapper的接口,并且使用了缓存注解@Cacheable表示缓存结果,key是page的pn、size、还有categoryId、order的参数。好了,上面我定义了一个模板标签,需要在页面中使用还需要把这个标签配置到freemarker中,因此我们定义一个FreemarkerConfig。
com.example.config.FreemarkerConfig
@Configuration
public class FreemarkerConfig {
@Autowired
private freemarker.template.Configuration configuration;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void setUp() {
configuration.setSharedVariable("posts", applicationContext.getBean(PostsTemplate.class));
}
}
页面使用标签
好了,freemarker标签就是这样生成了,下面我们在页面中使用。我们定义的标签名称是posts,结果是results。所以置顶模块,我们这样写:
templates/index.ftl
得到的结果如下:
首页侧边栏-本周热议(续)
在上一次作业中,我们完成了本周热议的数据接口:
但是还没在页面中展示我们的数据,一般按照逻辑,我们应该页面中写个ajax,然后调用这接口展示数据,现在我们学会了自定义freemarker,我觉得定义一个标签更方便点,因此,这里我们修改一下接口,把接口改成模板标签。
ok,我们安装刚才的流程,梳理一下:
首先定义一个模板HotsTemplate,继承TemplateDirective
重写getName和execute方法
然后在FreemarkerConfig中配置注入标签
页面中使用标签
/**
* 本周热议
*/
@Component
public class HotsTemplate extends TemplateDirective {
@Autowired
RedisUtil redisUtil;
@Override
public String getName() {
return "hots";
}
@Override
public void execute(DirectiveHandler handler) throws Exception {
Set<ZSetOperations.TypedTuple> lastWeekRank = redisUtil.getZSetRank("last_week_rank", 0, 6);
List<Map<String, Object>> hotPosts = new ArrayList<>();
for (ZSetOperations.TypedTuple typedTuple : lastWeekRank) {
Map<String, Object> map = new HashMap<>();
map.put("comment_count", typedTuple.getScore());
map.put("id", redisUtil.hget("rank_post_" + typedTuple.getValue(), "post:id"));
map.put("title", redisUtil.hget("rank_post_" + typedTuple.getValue(), "post:title"));
hotPosts.add(map);
}
handler.put(RESULTS, hotPosts).render();
}
}
上面execute的内容是把之前的本周热议的接口搬过来的。然后是freemarkerConfig.setUp
configuration.setSharedVariable("hots", applicationContext.getBean(HotsTemplate.class));
有了这行代码,页面中就可以使用了。
templates/inc/right.ftl
<dl class="fly-panel fly-list-one">
<dt class="fly-panel-title">本周热议</dt>
<@hots>
<#list results as post>
<dd>
<a href="jie/detail.html">${post.title}</a>
<span><i class="iconfont icon-pinglun1"></i> ${post.comment_count}</span>
</dd>
</#list>
</@hots>
</dl>
好了,这一次的作业的内容了。我们要学会快速自定义freemarker标签。freemarker模板引擎还是比较主流的页面引擎。
(完)
MarkerHub文章索引:
https://github.com/MarkerHub/JavaIndex
【项目相关文章】
1、Github上最值得学习的Springboot开源博客项目!
给eblog一个star,感谢支持哈