两天完成的一个轻量内容发布

定位

最近项目中需要实现一个轻量的内容发布。市面上常见的内容管理系统大多面面俱到,反而不适合作为一个内嵌的组件,整合到系统中作为一个子模块。

因此决定在现有系统框架下,自行实现一个轻量的内容管理。

工作完成之后,真正附加的开发成果只包括:

  • 一张数据库表:Article文章表
  • 一个json文件:定义树状的网站栏目,允许指定栏目的模版,如果不指定则采用默认模版
  • 两个jsp模版(测试用):用于验证在栏目中指定模版
  • 三个java类: CMSController用于将发布生成的url 映射为模版+数据;SecNode.java用于加载json节点到后端;CMSService.java封装具体的实现逻辑。

基本原理

本文只讨论文章详细页的内容发布,不涉及网站栏目首页的发布。



 
文章发布的三要素如上图所示:

  • 栏目——也称网站频道,可以视为一个树状的网站内容逐层分类。一个栏目下包含很多文章,通常一个栏目下的文章采用相同的模版发布,以保持相同的展示形式和风格。
  • 文章——包括:题名、内容、作者等元数据的结构化内容。文章可以发布到一个或者多个栏目下。一篇文章绑定一个模版之后会形成一个唯一的URL。如果一篇文章绑定了多个模版,应当会形成多个URL。
  • 模版——负责内容的展示形式,绑定文章(本例中为数据库表Article中的一条记录),render出最终的页面效果。

栏目

栏目信息非常适合用json树描述,用json的好处是维护方便,而且可以直接提供给后台界面用于发布栏目的多选。

栏目json文件见附件,后台管理中的呈现效果如下:

 用户选择发布的栏目之后,直接以简单的格式分隔存到一个文本字段即完成了文章发布,用户体验是不是够简单?

当然如果业务要求对发布内容进行审查,默认的状态可以是预览,后期也可通过置顶设置调整文章在频道首页的位置。

同时json定义也供后台java逻辑解析,以获得指定栏目对应的模版。

发布结果

文章指定的“发布到” 哪些栏目后,同时决定了:

  • 该内容在哪些栏目下出现?——栏目首页模版很容易根据该字段检索出属于本栏目的文章列表
  • 文章的展示形式——json中包含了栏目的模版指定(json节点的tpl属性),如果不指定则沿用父节点模版,如果无父节点则采用默认模版。
  • 文章的URL——文章的URL只由文章id和模版名两者确定,栏目不直接参与URL的确定。这样设计的一个好处是:假如一篇文章发布到多个栏目,但是却采用了相同的模版,那么这些发布最终都对应一个URL,即只生成一份静态页面。

发布结果的URL有两种形式:

  • 指定模版发布对应的URL:/article/{id}_{tpl}
  • 不指定模版发布对应的URL:/article/{id}

其中:id为数据的主键值,tpl为模版名。

采用SpringMVC的映射注解可以轻松将上述URL匹配到负责绑定模版和数据的处理逻辑:

	@RequestMapping(value = PATH_ARTICLE + "{id_tpl}", method = RequestMethod.GET)
	public String showDetailByTpl(@PathVariable("id_tpl") String id_tpl, Model model) {
		try {
			String[] prs = id_tpl.split("_");
			long id = Long.parseLong(prs[0]);
			Article obj = cmsService.getArticle(id);
			// TODO 检查status 状态, 只允许管理员预览
			model.addAttribute("obj", obj);
			String tpl;
			if (prs.length == 1) {
				tpl = TPL_DEFAULT;
			} else {
				tpl = prs[1];
			}
			// 根据频道绑定多个文章模版
			return "tpl" + PATH_ARTICLE + tpl;
		} catch (Exception e) {
			e.printStackTrace();
			return "error/404";
		}
	}

  

模版

模版采用JSP EL或JSTL,只负责将传入的model在页面中进行展示,不含其他逻辑。

此处也曾犹豫是否引入模版组件,最终SpringSide作者的见解影响了我,模版引擎怎么说相对jsp来说也是小众,

JSP完全胜任模版引擎任务,如果不考虑前端工程师的偏好,没必要再引入其他模版引擎,增加程序员的麻烦和系统复杂度。

写了两个最简单的jsp模版用于测试,两者基本一致

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<html>
<head>
	<title>${obj.title}</title>
</head>

<body>
模版1
<h1>${obj.title}</h1>
<p>${obj.content}</p>
</body>
</html>

预览

这块的工作就算稍微麻烦点的了,需要在java中解析json文件,获得指定栏目的文章模版。

基本思路如下:

  1. 定义与json节点对应的java类SecNode
  2. 利用ObjectMapper读取json文件并解析为SecNode[]
  3. 遍历SecNode[],建立栏目全路径名称对应的模版文件名,
  4. 例如:用户中心#办理流程-> 1.jsp ; 政策法规->default.jsp
  5. 前台Ajax请求主键值1的文章,发布对应的URL
  6. 后台根据主键值从数据库提取Article对象,得到其发布栏目为:政策法规;用户中心#办理流程  两个栏目
  7. 根据栏目获得对应的模版,如果栏目在json节点通过tpl定义了模版,则采用指定模版,否则沿用父节点模版。
  8. 根据模版和文章id 按URL定义规则拼接出URL数组,返回前端
  9. 前端拿到URL数组之后,采用tab窗口打开对应的两个页面预览。

同一篇文章发布到两个栏目下的预览效果图如下:

 (其中:”用户中心#办理流程“ 栏目在json中指定了模版名 1.jsp,而”政策法规“栏目未指定模版,采用了默认模版)

 

 

扩展

本文的实现算是一个最简版本的内容发布,但用于解决一个只是以资讯内容为辅的小型网站,也够用了。

更完整的内容管理还需要考虑以下问题:

  1. 内容的版本维护——需要在文章表中引入版本信息以及关联
  2. 内容的多语种支持——在文章表中引入多语种信息以及关联,可参考drupal的表结构设计
  3. 内容发布的审核——文章状态+审核日志
  4. 内容的静态化——可以采用Web Server的反向缓存,或者在后台应用中自行将生成的html流写入Web Server管理的文件目录。

猜你喜欢

转载自chen4w.iteye.com/blog/2283686
今日推荐