OpenJWeb 快速开发平台 - 内容管理系统 (CMS)
栏目标签库的设计与实现
2010-1-19
王保政
(QQ:29803446)
一、 标签库的设计
为了尽可能减少在 JSP 页面中直接编写代码, OpenJWeb 中新增了栏目显示的标签库,此标签库用来控制在页面中显示的信息栏目的样式、内容,并可以根据权限控制,只有授权的用户才可以看到对应的栏目。
下面是设计的栏目显示的标签库的属性:
<cms:category categoryCode="P0101" rowCount="10" pointColor="#ff0000" titleLen="20" serviceBean="IDBSupportService3" style="Style1" authId="AUTH_CATE1" title=" 测试 !!!!"/>
在 JSP 页面中可使用
<%@taglib prefix="cms" uri="http://www.openjweb.com/cms/tags" %>
来引用 openjweb 的 cms 系统的标签库。
具体属性介绍:
属性名 |
值 |
说明 |
categoryCode |
P0101 |
此栏目编码对应栏目表 ( cms_category ) 的 cate_code 字段,确定栏目编码可以找到此栏目相关的信息条目 |
rowCount |
10 |
在一个栏目中显示的信息行数 |
pointColor |
#ff0000 |
栏目中信息列表开头的小圆点的颜色 |
titleLen |
20 |
栏目中信息标题显示多长的字符串,过长则被截短 |
serviceBean |
IDBSupportService3 |
对应的 Spring 中配置的数据连接组件 |
Style |
Style1 |
对应栏目样式表中的样式编码,此样式编码对应一段栏目的 HTML 代码,这样更改栏目样式的时候,不需要在页面中修改。具体见说明 1. |
authId |
权限码 |
如果为空串, authId= “”则不需要权限,否则当前用户必须拥有给定的权限码才可以显示栏目,权限码的分配是采用 Spring Security 机制,在平台中可用权限管理来定义。 |
Titile |
测试 |
这是栏目的标题 |
说明 1 :
栏目样式配置,对应的功能为门户网站 - 栏目样式定义,对应的数据库表 portal_category_html ,此表中定义了栏目编码 Style1( 对应 style_code 字段 ) ,此编码对应的栏目的 html 代码:
</div></div><div class="vscape"></div>
<div class="md1"><font color="#FFFFFF"><b>
${categoryTitle}</b></font>
</div>
<div class="md2">
<div class="txt fh" >${infoContent}
</div>
</div>
其中 ${categoryTitle} 是栏目标题, ${infoContent} 是隶属此栏目的第一页的信息列表。
这样我们在修改栏目样式的时候,不需要在 jsp 页面中进行修改了,可直接在栏目样式定义功能中调整就可以了,而且我们还可以设置多个样式,在标签库中可引用其他的样式码。
对比没有使用标签库的 JSP 页面,首先要在页面前面 import 一堆 java 类,然后在页面中到处使用 <%%> 来分隔 java 代码和 html 代码,下面是没使用标签库的 jsp 部分代码:
<%@ page import="java.util.*"%>
<%@ page import="org.openjweb.core.util.*"%>
<%@ page import="org.openjweb.core.service.*"%>
<%@ page import="org.openjweb.core.entity.*"%>
…
<div class="vscape"></div>
<div class="md1"><font color="#FFFFFF"><b>
其他栏目 </b></font>
</div>
<div class="md2">
<div class="txt fh" >
<%
List infoList2 = CMSUtil.getCateInfoList("P0101",10,"desc",20 );
if(infoList2!=null)
{
for(int i=0;i<infoList2.size();i++)
{
CmsInfo infEnt = (CmsInfo)infoList2.get(i);
out.println("<font color=/"#FF0000/">¡¤</font> <a href=/""+infEnt.getInfUrl()+"/" target=/"_blank/">"+infEnt.getInfTitle()+"</a><br /> ");
}
}
%>
可以看出,上面的代码比较长,而使用标签后,只需要通过这种方式就可以动态生成信息栏目:
<cms:category categoryCode="P0101" rowCount="10" pointColor="#ff0000" titleLen="20" serviceBean="IDBSupportService3" style="Style1" authId="AUTH_CATE1" title=" 测试 !!!!"/>
二、 标签库 tld 文件
Openjweb 的标签库放在 WEB-INF/tld/ openjweb.tld ,此文件的具体内容:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>openjweb</short-name>
<uri>http://www.openjweb.com/cms/tags</uri>
<description>
OpenJWeb Cms Tag Library
$Id: openjweb.tld 3173 2010-01-19 08:14:28Z baozhengwang $
</description>
<tag>
<name>category</name>
<tag-class>org.openjweb.core.portal.taglibs.CmsTag</tag-class>
<description>
OpenJWeb Cms category tablib.
</description>
<attribute>
<name>categoryCode</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
category code
</description>
</attribute>
<attribute>
<name>rowCount</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
rowCount
</description>
</attribute>
<attribute>
<name>pointColor</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
point color
</description>
</attribute>
<attribute>
<name>titleLen</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
title len
</description>
</attribute>
<attribute>
<name>serviceBean</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
DB ServiceBean
</description>
</attribute>
<attribute>
<name>authId</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
authId
</description>
</attribute>
<attribute>
<name>style</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
style
</description>
</attribute>
<attribute>
<name>title</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>
category title
</description>
</attribute>
</tag>
</taglib>
此标签属性在上文已经介绍。
三、 在 web.xml 中引用标签库
在 web.xml 中的 taglib 区域添加:
<taglib>
<taglib-uri>http://www.openjweb.com/cms/tags</taglib-uri>
<taglib-location>
/WEB-INF/tld/openjweb.tld
</taglib-location>
</taglib>
四、 标签库实现类 org.openjweb.core.portal.taglibs.CmsTag
代码简要说明:
此 Tag 类读取页面标签中设置的属性,构造 html 代码输出到页面中,并且可以按用户权限来进行显示,此 Tag 类灵活结合了 SpringSecurity 的权限框架,不需要在 JSP 页面中手工编写跟栏目授权相关的代码。 Openjweb 中可从 v_user_auth 视图中读取当前用户拥有哪些权限 ID 。
package org.openjweb.core.portal.taglibs;
import java.io.IOException;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.log4j.Logger;
import org.openjweb.core.entity.CmsInfo;
import org.openjweb.core.entity.CommUser;
import org.openjweb.core.service.IDBSupportService;
import org.openjweb.core.service.ServiceLocator;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.web.util.ExpressionEvaluationUtils;
public class CmsTag extends TagSupport
{
private static final Logger logger = Logger. getLogger (CmsTag. class );
private String categoryCode = "" ; // 栏目编码
private int rowCount = 0; // 显示的信息条目数量 , 可直接从页面获得
private String pointColor = "#FF0000" ; // 信息标题前面的小圆点颜色
private int titleLen = 20; // 截取的字符串的长度
private String serviceBean = "IDBSupportService3" ;
private String authId = "" ; // 栏目对应的 authId
private String style = "" ; // 栏目的样式
private String title = "" ; // 栏目的标题
public void setTitle(String value)
{
this . title = value;
}
public String getTitle()
{
return this . title ;
}
public void setStyle(String value)
{
this . style = value;
}
public String getStyle()
{
return this . style ;
}
public void setAuthId(String value)
{
this . authId = value;
}
public String getAuthId()
{
return this . authId ;
}
public void setServiceBean(String value)
{
this . serviceBean = value;
}
public String getServiceBean()
{
return this . serviceBean ;
}
public void setTitleLen( int len)
{
this . titleLen = len;
}
public int getTitleLen()
{
return this . titleLen ;
}
public void setPointColor(String value)
{
this . pointColor = value;
}
public String getPointColor()
{
return this . pointColor ;
}
public void setCategoryCode(String value)
{
this . categoryCode = value;
}
public String getCategoryCode()
{
return this . categoryCode ;
}
public void setRowCount( int value)
{
this . rowCount = value;
}
public int getRowCount()
{
return this . rowCount ;
}
public int doStartTag() throws JspException
{
// 似乎可直接从页面获得
final String code = ExpressionEvaluationUtils. evaluateString ( "cateGoryCode" , categoryCode , pageContext );
final String dbService = ExpressionEvaluationUtils. evaluateString ( "serviceBean" , serviceBean , pageContext );
final String pointColor1 = ExpressionEvaluationUtils. evaluateString ( "pointColor" , pointColor , pageContext );
IDBSupportService service = (IDBSupportService)ServiceLocator. getBean (dbService);
// 尝试获取用户信息
String loginId= "" ; // 当前登录用户
try
{
SecurityContextImpl securityContext=(SecurityContextImpl) pageContext .getSession().getAttribute( "SPRING_SECURITY_CONTEXT" );
if (securityContext!= null )
{
CommUser currUser = (CommUser)securityContext.getAuthentication().getPrincipal();
logger .info( " 当前用户为 :" ); // 当登录后,会取得用户名称,可以据此来控制权限
logger .info(currUser.getUsername());
loginId = currUser.getLoginId(); // 当前登录用户
}
}
catch (Exception ex)
{
logger .error( " 获取用户上下文信息失败 " );
}
if ( this .getAuthId()== null || this .getAuthId().trim().length()==0)
{
// 如果没有设置 authId, 则说明为不限制栏目访问权限
logger .info( " 未设置权限,可以显示栏目 " );
}
else
{
// 如果有 authId, 则查看
if (loginId== null ||loginId.trim().length()==0)
{
// 说明未登录,应该不允许查看栏目
logger .info( " 当前登录帐号为空,所以不显示内容 " );
return Tag. SKIP_BODY ;
}
else
{
// 查找权限
String sql = "select count(*) from v_user_auth where login_id='" +loginId+ "' and comm_code='" + this .getAuthId()+ "' " ;
logger .info( " 标签中的查询语句 :" );
logger .info(sql);
try
{
int authCount = service.getJdbcTemplate().queryForInt(sql);
if (authCount ==0)
{
logger .info( " 此栏目没有获得授权 ....." );
return Tag. SKIP_BODY ; // 没有获得授权
}
else
{
logger .info( " 此栏目获得授权 ...." );
}
}
catch (Exception ex)
{
logger .error(ex.toString());
return Tag. SKIP_BODY ; // 如果出现异常,不允许访问栏目
}
}
}
try
{
// 获取栏目的样式
if ( this .getStyle()== null || this .getStyle().trim().length()==0)
{
logger .info( " 未设置样式,退出 !" );
return Tag. SKIP_BODY ;
}
else
{
String sStyle = this .getStyle();
Object obj = service.getJdbcTemplate().queryForObject( "select style_html from portal_category_html where style_code='" + this .getStyle()+ "'" ,String. class );
if (obj== null )
{
logger .info( " 未设置栏目样式,退出 !" );
return Tag. SKIP_BODY ;
}
else
{
String htmlExpr = obj.toString();
htmlExpr = htmlExpr.replace( "${categoryTitle}" , this .getTitle());
String infoContents = "" ;
List list = service.findPage( "org.openjweb.core.entity.CmsInfo" , " where cateTreeCode in (select treeCode from CmsCategory where cateCode='" +code+ "') order by createDt " + "desc" ,1,20);
if (list!= null &&list.size()>0)
{
for ( int i=0;i<list.size();i++)
{
CmsInfo infEnt = (CmsInfo)list.get(i);
infoContents += "<font color=/"" +pointColor1+ "/">¡¤</font> <a href=/"" +infEnt.getInfUrl()+ "/" target=/"_blank/">" +infEnt.getInfTitle()+ "</a><br /> /r" ;
}
}
htmlExpr = htmlExpr.replace( "${infoContent}" , infoContents);
pageContext .getOut().print(htmlExpr);
}
}
}
catch (Exception ex)
{
logger .error( "cms tab error:" +ex.toString());
}
return Tag. EVAL_BODY_INCLUDE ;
}
}
五、 总结
使用标签库开发 JSP 页面并不难,这样可以使得 JSP 页面更加规范,而且给定一个标准的标签库规则,美工人员在制作静态页面后,可以不需要开发人员就能将静态页面转换为 JSP 动态页面。