BEA Weblogic Portal内容管理的几点开发经验 1.BEA Weblogic Portal 8.1内容管理概述 BEA Weblogic Platform 8.1将所有在门户中显示的内容包括文本、HTML、图形以及多媒体文件等都统一存储在内容库中,称为BEA虚拟内容库(BEA VCR)。所有的内容组织成层次结构,虚拟内容库(VCR)是内容管理系统的顶层节点,接下来是内容库,这些内容库可以是多个BEA内容库、第三方内容库以及用户自定义的内容库。再下面就是层次节点(相当于文件夹)和内容节点(相当于文件)。如下图:
图1 BEA虚拟内容库的层次结构图 BEA内容库在数据库中由CM_开头的5个表组成,其E/R图如下:
图2 BEA内容存储数据库的E/R图 CM_NODE表存储的是各个节点(包括层次节点和内容节点)的信息及其在整个内容库中的位置。CM_OBJECT_CLASS表示的是各个节点的模式,也就是不同内容类型的定义。各种类型的内容又是由一系列属性来表示的,CM_PROPERTIY_DEFINITION 存储的就是所有内容类型的各种属性的定义。CM_PROPERTY存储的是每一个具体节点所有属性的值。 BEA Repository是与某个特定的服务器域(Server Domain)相对应的,在配置domain时,BEA Weblogic的服务器域模板就会自动在数据库中生成内容库的各种数据表。通过Workshop开发Portal应用时会自动生成Portal管理程序,通过该管理程序可以直接完成内容类型定义,内容节点的创建、修改以及删除等基本的内容创建和管理功能。而且作为Portal管理的一部分,还可以对内容管理进行委托管理。可以说应用起来,是很方便的,但在企业级Portal的开发中,这些基本的内容管理功能是不够的。BEA还在com.bea.conten.*中提供了一系列API,这些API不仅是BEA实现内容管理的核心,也是用户二次开发的基础。但遗憾的是BEA在这方面的文档相当少,同时Platform 8.1发布时间又不长,因此本文作者在开发国家电子政务试点示范项目绵阳市电子政务门户系统的过程中,通过摸索和实践,积累了几点开发经验,现整理出来,希望能对BEA Platform 8.1开发的同好有所帮助。 2.通过Java类或JSP直接进行内容管理 在我们的项目中,内容管理是用户使用较频繁的一部分。虽然Workshop为Portal应用自动生成的Portal管理程序中已具有内容管理模块,但是我们发现它却不能很好地满足最终用户的需求,他们需要更加直观和操作便捷、功能简练而又能最大限度地满足日常内容管理要求的Portal内容管理界面。于是,我们按照用户的实际情况对BEA的内容管理进行二次开发,现摘出其主要的开发过程与大家探讨。 在程序中操作Repository概括起来有以下几个步骤:首先,构造一个RepositoryManager类的实例;接下来,通过分别调用getObjectClassOps()方法和getNodeOps() 方法得到该实例的ObjectClassOps接口和NodeOps接口;然后即可使用接口中相应的方法实现对ObjectClass (类型)或Node(节点)的操作了。 BEA Repository中的目录和内容条目都是以节点的形式来组织的,若是目录管理就调用操作目录节点的方法,若是内容条目管理就调用操作内容节点的方法。下面列举部分程序代码: //得到ObjectClassOps接口和NodeOps接口 Try { RepositoryManager rMgr = RepositoryManagerFactory.connect ( ); ObjectClassOps ocOps = rMgr.getObjectClassOps(); NodeOps nOps = rMgr.getNodeOps ( ); } catch (Exception e) { …… } //以’BEA Repository’为根目录,创建自己的子目录 ID RootID = new ID ( "BEA Repository", "" ); String DirNodeName = “dir1”; Node DirNode = nOps.getNode ( "/BEA Repository/ " + DirNodeName ); if (DirNode == null ){ Try { DirNode = nOps.createHierarchyNode ( RootID, DirNodeName); } catch (Exception e) { …… } } //先取得要添加内容所属Type的ObjectClassID //假设该Type的名称为”type1” String typeName = " type1"; ObjectClass[] objectClasses = null; String CurObjectClassID = null; try{ objectClasses = ocOps.getObjectClasses(); } catch(Exception e){ …… } int i; for (i=0; i<objectClasses.length; i++){ if(objectClasses[ i ].getName().equals( typeName )) break; } if(i < objectClasses.length){ CurObjectClassID = objectClasses[ i ].getId().toString(); } else{ //该类型不存在,另做处理并退出,return } //在目录下添加内容条目 /* *假设 type1共有2个Property, 分别是: * -----------------“title”(String) * -----------------“content”(String) */ String ContentNodeName = “内容条目1”; ID DirNodeID = DirNode.getId ( ); //取得父节点的ID Property [ ] prp = new Property[2]; Value TitileValue = new Value ( “标题” ); Value ContentValue = new Value ( “内容” ); prp [0] = new Property ( “title”, TitleValue ); prp [1] = new Property ( “content”, ContentValue ) try{ nOps.createContentNode (DirNodeID, ContentNodeName, CurObjectClassID, prp ); } carch(Exception e){ …… } //删除内容条目 Node ContentNode = nOps.getNode ( "/BEA Repository/ " + ContentNodeName) if (ContentNode != null ) { try { ID ContentNodeID = ContentNode.getId ( ); nOps.deleteNode (ContentNodeID ); } catch (Exception e) { …… } } //删除目录 DirNode = nOps.getNode ( "/BEA Repository/ " + DirNodeName) if (DirNode!= null ) { try { ID DirNodeID = DirNode.getId ( ); nOps.deleteNode (DirNodeID ); } catch (Exception e) { …… } } 3.对较大文本内容的发布 在Bea Repository中,一般的文字内容都被存为String类型,不过String类型是有长度限制的,所以不能存储较长的内容。当然,我们可以把较长的内容先编辑成文件,再以Binary类型存入BEA Repository中进行发布。但是,如果用BEA提供的ShowBinaryServlet来显示这种Binary类型的数据,只能是在一个新打开的页面中显示,而不能在自定义页面中进行显示,这就造成了不能按自己的需要定制内容显示的界面。为解决这个问题,我们在在认真研究ShowBinarySeverlet的基础上,开发了自己的Java代码以读取这种Binary内容并在JSP中予以显示。 //"bContent"为存放文本文件的字段 Property property=node.getProperty("bContent"); // 将要用到Property的getPropertyBytes()方法,它必须以transaction的方式来执行 UserTransaction tx; Context initCtx = new InitialContext(); tx = (UserTransaction)initCtx.lookup("java:comp/UserTransaction"); //通过getPropertyBytes()方法把二进制数据变成流文件 tx.begin(); RepositoryManager repositoryManager = RepositoryManagerFactory.connect(); NodeOps nodeOps = repositoryManager.getNodeOps(); InputStream is = null; is = nodeOps.getPropertyBytes(node.getId(), property.getId()); tx.commit(); //把输入流中的数据读入缓冲区 InputStreamReader isr = new InputStreamReader(is); StringBuffer buffer = new StringBuffer(); Reader in = new BufferedReader(isr); int ch; while ((ch = in.read()) > -1) { buffer.append((char)ch); } in.close(); is.close(); //把缓冲区的内容转换为字符串,为了支持中文还需作编码方式的转换 String str = buffer.toString(); String newStr = new String(str.getBytes(),"gb2312"); 4.对中文乱码问题的处理 在开发BEA Portal 8.1内容管理的过程中,我们经常遇到在程序中不能正确对中文进行处理的情况。发生乱码时,中文字符就变成了一个个问号或怪字符(例如图3中的情况),确实比较令人着急。当然,这并不是BEA Portal的问题,因为java中出现中文乱码问题一般都是由于对程序中的编码/解码方式(如:UNICODE编码和其它本地的编码)使用不当所造成,而这些问题本身都是可以通过合理途径加以解决的。
图3 页面中出现了中文乱码 要解决这些问题,首先要搞清楚的是一些常见的字符集编码方式。ISO8859系列是8位的西文字符集(如:ISO8859-1, ISO8859-2等),0~0x7F仍与ASCII字符集保持兼容,大于0x7F的是各种拉丁字符或欧洲字符的扩展;GB2312是简体中文编码方式,BIG5是繁体中文的编码方式,它们表示西文字符时用单字节,表示中文用两个字节,而GBK可以看成是GB2312的扩展;Java中为了便于国际化,它的字符数据都是16位无符号型数据??UNICODE集;而在以英文为主要信息的互联网时代,UNICODE对任何字符都采用双字节表示的方式极其浪费空间,所以在此基础上出现了UTF-8,在UTF-8中,属于US-ASCII中的字符,仍用一个字节表示,且和US-ASCII兼容,其他的字符,则用1(大于0x7F部分)到3个字节。Windows (简体中文版)一般采用GBK字符集,而BEA Weblogic Portal 8.1默认采用UTF-8字符集。 编码(Encode)和解码(Decode)是两个相反的动作。编码是把字符按照某种映射标准(字符集),转换成字节,这时我们把执行编码动作时所采用的标准叫编码(encoding)。而解码则是将字节序列按照某种字符标准(解码,decoding),转换成字符串。如果解码的标准和编码标准不兼容,得出的字符串就是乱码。 当出现java的中文乱码问题时,需要根据具体情况来分析解决。在开发Portal内容管理程序中我们遇到了以下几种出现中文乱码的情况:页面内的中文字符、提交到数据库中的内容、在页面中显示的从数据库中读出的内容和页面之间通过URL传递的中文参数。通过实践和总结,有下面一种比较通用的简单解决方案,即在任何地方都使用GB2312字符集进行编码和解码,可以解决绝大多数中文乱码问题。 1. 在startweblogic.cmd 文件中添加如下代码(使程序编译时按gb2312编码): %JAVA_OPTIONS% -Dfile.encoding=gb2312; 2. 修改weblogic.xml文件(使页面向服务器发送的内容按gb2312编码): …… <jsp-param> <param-name>encoding</param-name> <param-value>gb2312</param-value> </jsp-param> ……
3. 修改web.xml文件(使页面之间通过URL方式传递的中文参数以gb2312进行编码): …… <context-param> <param-name>weblogic.httpd.inputCharset./*</param-name> <param-value>gb2312</param-value> </context-param> ……
4. 修改 .portal文件(使portal运行时采用gb2312字符集): <portal:directive.page contentType="text/html;charset=gb2312"/>
5. 每个jsp的文件头里面都写上如下的语句(使每个页面都采用gb2312字符集): <%@ page language="java" contentType="text/html;charset=gb2312"%>
6. 如果仍然出现乱码,可再对该乱码字符串使用如下方法进行一次编码方式的转换: NewString = new String( OldString.getBytes(), "gb2312" );
| <script type="text/javascript"> <!-- google_ad_client = "pub-8054039502712326"; google_ad_width = 160; google_ad_height = 600; google_ad_format = "160x600_as"; google_ad_channel =""; google_color_border = "336699"; google_color_bg = "FFFFFF"; google_color_link = "000000"; google_color_url = "006699"; google_color_text = "000000"; //--> </script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> |
本文网址: http://www.java-cn.com/technology/technology_detail.jsp?id=3559