hk2000c技术专栏

技术源于哲学,哲学来源于生活 关心生活,关注健康,关心他人

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 1 文章 :: 28 评论 :: 0 Trackbacks

#

Liferay 二次开发太困难,花了N*N个小时,除了搭建了一套可以调试部署的环境之外,部署了几个示例实例之外,几乎毫无建树。
liferay代码可读性是我见过最差的,乍看觉得可能是反编译的代码。昏过去,我要骂娘了。什么编码规范!呕了!!!
网上support 的效率非常低,几乎没人帮忙,遇到问题简直就是灾难。继续下去的信心简直快要破灭了。

Jetspeed 2 就比较好了 , 源代码,文档,二次开发比较容易。
而且国内弄得人也多,可以相互交流支持,不像liferay 一条小道走不到底的感觉。

不过Liferay 还是比较好的一个项目,速度比jetspeed2 不知道快多少,而且拥有很多很实用的portlet .
但愿 Jetspeed2 会做得更好。毕竟开源需要众人去做,才会有生命力。

posted @ 2006-08-08 23:05 hk2000c 阅读(3097) | 评论 (6)编辑 收藏

准备每个知识点的几个例子,梳理一下自己的知识树结构,避免时间长了,技术生疏

暂时需要整理的知识点例子有

tag

jms

oscache

hiberante

spring

SWF spring web flow

struts tiles

axis webservice

准备阅读相关的JSR标准
编写一个Axis的例子


pdf liberay

nutch search

SSO


posted @ 2006-08-08 15:25 hk2000c 阅读(315) | 评论 (0)编辑 收藏

Portlet 形态

Portlet 的形态直白的说,就是 portlet 功能的表现形式。通常, portlet 根据他们自己功能的不同,执行不同的任务以及生成不同的内容。 Portlet 形态直接预示着他们担任什么样的功能并且将会显示什么样的内容。当 portlet 被调用的时候, portlet 容器会为其提供的一个的当前 portal 形态。 Portlet 可以很方便的在处理一个 action 请求的时候改变它的形态。

       Portal 规范定义了 3 portlet 形态。他们分别是 VIEW EDIT 以及 HELP PortletMode 类定义了这些形态的常量。

       Portal 形态还用于对用户的权限功能控制,比方说一个未认证用户只能察看 portlet VIEW 以及 HELP 形态,而认证用户则能访问 portlet EDIT 形态。

 

8.1 Portlet VIEW 形态

       Portlet VIEW 形态的主要功能是通过生成标记语言来显示 portlet 的当前状态。比方说,一个 portlet VIEW 形态可能包含一到两个页面,用户可以浏览或者做某些操作。它也可能仅仅是一张静态页面而不做任何事情。

       开发者可以简单的通过重载 GenericPortlet doView() 方法来获得这项功能

       Portlet 必须支持 VIEW 形态

 

8.2 EDIT 形态

       EDIT 形态下面, portlet 应该提供相关的内容以及逻辑给用户,以便能够让用户可以自定义 portlet 行为。一个 EDIT 形态的 portlet 应该有 1 到多个窗口,这样用户就能从这些窗口进入他们自己自定义的数据了。

       通常, EDIT 形态的 portlet 会设置或者更新 Portlet 参数。参考 portlet 参数一节获得更多的细节。

开发者可以简单的通过重载 GenericPortlet doEdit() 方法来获得这项功能

Portlet 不必支持 EDIT 形态

8.3 HELP 形态

       help 形态下面, portlet 应该提供 portlet 本身的相关帮助信息。一个 portlet 的帮助信息可以是介绍 portlet 的完整帮助或者是内容相关的帮助文本。

开发者可以简单的通过重载 GenericPortlet doHelp() 方法来获得这项功能

Portlet 不必支持 HELP 形态

8.4 portlet 自定义形态

       Portlal 的提供者可以自定义 portlet 形态用来提供自己指定的功能

       要使用自定义 Portlet 形态,首先需要在部署描述器中添加 custom-portlet-mode 元素 ,其次需要在运行期找到该形态的 portal 实现。如果在运行期间找不到该自定义形态的 portal 实现,这个 portlet 就不应该被调用

       打个比方, portlet 应用需要支持 clipsboard 以及 config 形态的 portlet ,那么部署描述器里面可能这么写:

 

<portlet-app>

...

<custom-portlet-mode>

<description>Creates content for Cut and Paste</description>

<name>clipboard</name>

</custom-portlet-mode>

<custom-portlet-mode>

<description>Provides administration functions</description>

<name>config</name>

</custom-portlet-mode>

...

</portlet-app>

 

在《扩展 Portlet 形态》附录中列出了建议的 portlet 形态的命名参考以及他们的使用参考。如果 portlet 在部署描述器中定义了一个自定义的形态,并且 portal 容器实现了这种形态的话,那么 Portal 容器可以立即自动地映射这种支持形态。

 

 

8.5 GenericPorlet 渲染方法的处理

       GenericPorlet 通过 render 方法来分发用户的请求给 doView , doEdit , doHelp 方法。这个指定形态分发的动作在 doDispatch 里面都会指明。如果 portal 容器提供者需要支持一种新的形态,那么必须重载 doDispatch 方法。

 

8.6     定义 portlet 形态

 

Portlet 通过在它的部署描述器内配置 portlet 形态来获得它能使用的 portal 容器支持的形态。每个 Portlet 都必须支持 VIEW 形态,而且 VIEW 形态无需特别指定。

下面的例子显示了一个配置 Portlet 形态的样本:

...

<supports>

<mime-type>text/html</mime-type>

<portlet-mode>edit</portlet-mode>

<portlet-mode>help</portlet-mode>

...

</supports>

<supports>

<mime-type>text/vnd.wap.wml</mime-type>

<portlet-mode>help</portlet-mode>

...

</supports>

...

 

以上的配置说明了,该 portlet html 标记语言下支持 edit ,help 形态,当然还支持默认的 view 形态。在 wml 语言环境下,支持 help 以及 view 形态。

 

 

 ===


以上是翻译节选,以后会陆续刊出其它章节
欢迎转载共同交流

 

posted @ 2006-07-12 11:01 hk2000c 阅读(1701) | 评论 (0)编辑 收藏

装载JBoss 应用的时候出现经典log错误 org.apache.commons.logging.LogConfigurationException: Class org.apache. commons.logging.impl.Log4JCategoryLog does not implement Log

检查应用路径 %App_path%/WEB-INF/lib ,把下面 log4j.jar以及 commons-logging.jar 均删除,问题解决

原理解释文章在以下位置

http://www.qos.ch/logging/thinkAgain.jsp

以前也遇到类似问题

如果是tomcat 5.x 版本,需要这样处理

删除tomcat/webapps/%apps%/WEB-INF/lib/下面的
commons-logging-api-1.0.4.jar 包
然后换成

log4j.jar以及 commons-logging.jar

posted @ 2006-04-28 23:21 hk2000c 阅读(266) | 评论 (0)编辑 收藏

     摘要: Java Authentication Authorization Service(JAAS,Java验证和授权API)提供了灵活和可伸缩的机制来保证客户端或服务器端的Java程序。Java早期的安全框架强调的是通过验证代码的来源和作者,保护用户避免受到下载下来的代码的攻击。JAAS强调的是通过验证谁在运行代码以及他/她的权限来保护系统面受用户的攻击。它让你能够将一些标准的安全机制,例如Solar...  阅读全文
posted @ 2006-03-23 08:07 hk2000c 阅读(6179) | 评论 (0)编辑 收藏

     摘要: 有一部分xml解析器使用者认为 JDOM 很慢,至少比起Dom4j来说效率不快。其实JDOM和DOM4J一样,同属优秀的开源XML解析器, 完全不必这样担心。 现在就实际拿一些实际使用的例子,作为简单的测试用例,对JDOM以及DOM4J最基本的文档解析功能来说明这个问题。 JDOM测试用例如下:      public Document getDoc(String filename) throws...  阅读全文
posted @ 2005-03-21 05:00 hk2000c 阅读(853) | 评论 (0)编辑 收藏

     摘要: Ant 介绍以及基本使用指南 Ant 是著名 Java 开源组织 Apache 的一个项目,是一个基于 java 的 build 工具。它可以使你通过 ant 脚本语言,自动你...  阅读全文
posted @ 2004-12-03 19:21 hk2000c 阅读(244) | 评论 (0)编辑 收藏

克服J2SE 1.3 ~ 1.4不兼容问题
--从反射API和ANT获得帮助



概要
    如果你要实现JavaAPI中的一个,那么可能是件比较痛苦的事情。你经常会需要实现许多交叉依赖的接口。对新特性的需求促成了升级现有的JavaAPI,这就造成了提供这些API的供应商对他们的相关实现不断的升级以维持相关功能。随着这些API的升级更改越来越频繁,API代码的不兼容使你不得不分别维护新旧版本的代码库。这直接到导致了你维护成本和难度的增加。本文演示了解决此问题的技术,揭示了如何仅使用一个代码库编译不同JavaAPI版本的代码。



    现在非常多的API被加入到到Java的标准库中,比如JDBC。这样做的好处是,Java可选包在部署时不必被绑定到相关的部署应用中去。这些API由专门的专业开发小组实现,在实际的使用当中这些API变得越来越受欢迎,使用的深度及广度也在不断的增加。但是有时候对一些API升级会变得使一些类及方法不可用。开发小组宁愿让这些API包成为可选组件而不是作为Java标准支持库的形式来发布。但是一旦加入标准库中的API包,就像是和用户签定了终生契约,想再成为可选包是不可能的。所以作为用户的你,可能会突然发现你一下子自己的代码库变成了不兼容的2个代码库,一个是使用新API的代码库,另一个是使用旧API的代码库。你可能会以为情况不像你想象的那样糟糕。我这里举一个简单的例子。J2SE1.4中由于对JDBC中的一些API的升级使的java.sql.Connection 不能同时被1.3 及 1.4 版本编译通过。你可能会遇到我这样的困境:我可能需要实现java.sql.Connection这个接口,但是我的代码需要同时通过1.3 及1.4 得编译。但是我不想同时维护2个版本的代码库。所以我开始寻找更好的解决方法。
    如果你依赖于javac来编译你的应用的话,那么很不幸,Java著名的一次编写,到处运行(WORA)并不包括WOCA(一次编写,到处编译^_^;)。
不过别太沮丧,编码的反射技巧以及编译的Ant技巧是你能够安然过关。我能够仅仅使用一组Java文件以及Ant工具,就能使一个版本同时编译
在1.3 和1.4 版本下面。别急,在我结识解决办法之前,让我先详细的解释一下问题的描述。

可怜人的连接池(PS:Poor man's connection pool ,很有意思的一句话)
    两年前,我的公司需要一个连接池,但是又不肯出钱买一个。当时并没有什么免费的东东可以使用,所以我们自己写了一个连接池。为了能更好的跟踪在整个应用中连接的情况,我们写了一个com.icentris.sql.ConnectionWrapper类,它实现了java.sql.Connection 接口以及其他的一些包装类(实现了另外的一些的java.sql 接口)。这些包装类仅仅是跟踪我们应用中的数据库使用,以及通过方法调用真正的
数据库资源。
    当J2SE1.4来的时候,我们自然而然的想到升级我们提供给客户的应用,使这些应用的性能得到很多提升。当然,我们也需要保留1.3版本,因为有些客户根本不需要升级到1.4。我们气恼的发现,如果我们不修改,我们的ConnectionWrapper 以及其他JDBC封装类根本通不过J2SE1.4的编译。
    为了文章的简明,我通过使用ConnectionWrapper 这个类来演示我对所有其他不能够通过J2SE1.4的类所使用的技术。如果我按照新的API标准,那么我不得不添加几个方法到ConnectionWrapper中去,接下来2个大问题摆在了面前:
1.因为我的包装类需要经历方法调用,我将不得不调用在J2SE1.3 sql类中并不存在的方法。
2.因为一些新的方法涉及到一些新出现的类,我将不得不在编译中面对那些在J2SE1.3中并不存在的类。

反射提供了援助
一些代码可以很方便的解释第一个问题。但是我的ConnectionWrapper 封装了java.sql.Connection , 所有的我的例子
依赖于在构造方法中的变量 realConnection :

private java.sql.Connection realConnection = null;
 
  public ConnectionWrapper(java.sql.Connection connection) {
    realConnection = connection;
  }

    为了看清楚我怎么做到解决版本不兼容问题,让我们仔细看一下setHoldability(int)(这个在J2SE1.4被声明的新方法)
public void setHoldability(int holdability) throws SQLException {
    realConnection.setHoldability( holdability );
  }

    很不幸,这个方法在J2SE1.3中显然通不过编译,这就陷入了2难的尴尬境地。为了解决这一情况,我假定setHoldability() 将只会在J2SE1.4
下面被调用,所以我使用了反射机制来调用该方法。

public void setHoldability(int holdability) throws SQLException {
    Class[] argTypes = new Class[] { Integer.TYPE };
    Object[] args = new Object[] {new Integer(holdability)};
    callJava14Method("setHoldability", realConnection, argTypes, args);
  }

  public static Object callJava14Method(String methodName, Object instance,
  Class[] argTypes, Object[] args)
    throws SQLException
  {
    try {
      Method method = instance.getClass().getMethod(methodName, argTypes);
      return method.invoke(instance, args );
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
      throw new SQLException("Error Invoking method (" + methodName + "): "
      + e);
    } catch (IllegalAccessException e) {
      e.printStackTrace();
      throw new SQLException("Error Invoking method (" + methodName + "): "
      + e);
    } catch (InvocationTargetException e) {
      e.printStackTrace();
      throw new SQLException("Error Invoking method (" + methodName + "): "
      + e);
    }
  }

    现在我有了setHoldability() 方法,因此能顺利通过J2SE1.4的编译。原理是我并不直接调用J2SE1.3中间java.sql.Connection并不存在的方法,
而是转为通过让setHoldability调用callJava14Method这个通用方法来调用,然后在一个SQLException 里封装所有的异常。这样就达到我预期的效果。
现在所有的在J2SE1.4中新方法都工作的很好,在J2SE1.3的老版本下也能顺利编译而且工作正常。现在我来着手解决第二个问题。
就是如何在应用中能够找到一个方法能够使用J2SE1.3中并不存在的新的类。

Ant 是答案
在J2SE1.4中,java.sql.Connection 依赖于一个新的类java.sql.Savepoint。因为这个类在java.sql 包中,所以你不可能把它加入到J2SE1.3中去。Java不允许任何的第三方扩展包加入它的核心包(java.* 以及 javax.* )中去。 因此挑战来了,在J2SE1.4下调用这个新的java.sql.Savepoint 类,但同时需要代码能够在J2SE1.3下面得到编译以及能够运行。很简单,不是吗?所有回答"Yes"的人都会得到一个榛仁巧克力饼(PS:哈哈,我回答了,可是没有:P)。至少现在我找到了答案,使问题变得很简单了。
  首先我插入了下面一条有条件的import语句
// Comment_next_line_to_compile_with_Java_1.3
  import java.sql.Savepoint;

    然后我找到了一个能够在J2SE1.3下面注释掉import的方法。非常简单,使用如下Ant 语句就可以了:
<replace>
    <replacetoken>Comment_next_line_for_Java_1.3&#010;</replacetoken>
    <replacevalue>Comment_next_line_for_Java_1.3&#010;//</replacevalue>
  </replace>

    这个Ant 的 replace 标签 有好几个标签选项,在以后我给出的全部例子里有很多。在这里面最重要的是使用<replacevalue>来替换<replacetoken> 。&#010;在XML里面的意思是换行。在J2SE1.4下,没什么会发生, 但是在J2SE1.3下面一个import声明被注释掉了。
// Comment_next_line_to_compile_with_Java_1.3
  //import java.sql.Savepoint;

    但是我在代码中Savepoint仍在使用public Savepoint setSavepoint(String name) throws SQLException { . . .}。不过我只在J2SE1.4使用这些方法类,在J2SE1.3中只要能编译就可以了。我发现只要我有一个我自己的Savepoint 类在我的包中,我的代码就能够通过编译,而且不用任何的import包。但是我又要同时在这条import 语句不被注释的同时我自己的Savepoint类被忽略掉。因此我造了一个空的com.icentris.sql.Savepoint类,这个可能(除了JavaDoc)是最短的有效类:
package com.icentris.sql;

  /** Dummy class to allow ConnectionWrapper to implement java.sql.Connection
   * and still compile under J2SE 1.3 and J2SE 1.4. When compiled
   * under J2SE 1.3, this class compiles as a placeholder instead of the
   * missing java.sql.Savepoint (not in J2SE 1.3).  When compiled
   * under J2SE 1.4, this class is ignored and ConnectionWrapper uses the
   * java.sql.Savepoint that is new in J2SE 1.4.
   */
  public class Savepoint {}

    在J2SE1.4下我能够正确的import java.sql.Savepoint类,而在J2SE1.3下面Ant注释了这条import语句。因此这个Savepoint就被替换成了我这个包里面写的一个空的Savepoint类。所以我现在就能加入任何引用到Savepoint类的方法,同样的在这些新方法中使用刚才所说的反射方法。
// Comment_next_line_to_compile_with_Java_1.3
  import java.sql.Savepoint;

  . . .
    public Savepoint setSavepoint() throws SQLException {
      Class[] argTypes = new Class[0];
      Object[] args = new Object[0];
      return (Savepoint) callJava14Method("setSavepoint", realConnection,
      argTypes, args);
    }

    public Savepoint setSavepoint(String name) throws SQLException {
      Class[] argTypes = new Class[] { String.class };
      Object[] args = new Object[] { name };
      return (Savepoint) callJava14Method("setSavepoint", realConnection,
      argTypes, args);
    }

    public void rollback(Savepoint savepoint) throws SQLException {
      Class[] argTypes = new Class[] { Savepoint.class };
      Object[] args = new Object[] { savepoint };
      callJava14Method("rollback", realConnection, argTypes, args);
    }

    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
      Class[] argTypes = new Class[] { Savepoint.class };
      Object[] args = new Object[] { savepoint };
      callJava14Method("releaseSavepoint", realConnection, argTypes, args);
    }

    现在我所要做的就是能够使Ant 识别 J2SE1.3版,然后能够使这条import 语句被注释掉。
<target name="compile">
    <antcall target="undoJava13Tweaks" />
    <antcall target="doJava13Tweaks" />
    <javac srcdir="src" destdir="WEB-INF/classes" debug="on">
      <classpath>
        <fileset dir="WEB-INF/lib">
          <include name="*.jar"/>
        </fileset>
      </classpath>
    </javac>
    <antcall target="undoJava13Tweaks" />
  </target>

  <target description="Find out if we're being compiled on Java 1.3"
  name="isJava13">
    <echo message="java.specification.version=[${java.specification.version}]"/>
    <condition property="isJava13">
      <equals arg1="${java.specification.version}" arg2="1.3" />
    </condition>
  </target>

  <target description="There are a couple tweaks I have to do to compile under Java 1.3"
    name="doJava13Tweaks" depends="isJava13" if="isJava13">
    <echo message="This is Java 1.3, doing Tweaks!" />
    <replace dir="src/com/icentris/" summary="true">
      <include name="sql/ConnectionWrapper.java" />
      <replacetoken>Comment_next_line_for_Java_1.3&#010;</replacetoken>
      <replacevalue>Comment_next_line_for_Java_1.3&#010;//</replacevalue>
    </replace>
  </target>

  <target description="Let's undo Java 1.3 tweaks" name="undoJava13Tweaks">
    <replace dir="src/com/icentris/" summary="true">
      <include name="sql/ConnectionWrapper.java" />
      <replacetoken>Comment_next_line_for_Java_1.3&#010;//</replacetoken>
      <replacevalue>Comment_next_line_for_Java_1.3&#010;</replacevalue>
    </replace>
  </target>

    注意编译目标在调用doJava13Tweaks的前后都调用了undoJava13Tweaks。如果万一javac编译失败的话,我们可以恢复以前的编译版本。

你没有必要同时维护2个应用实现
    对于Java来说,新的API升级所带来的新的方法以及新的类/接口并不是新鲜事。一般而言,加入的新方法以及新的类的同时,会考虑到向上兼容的问题来照顾老API用户。但是当升级的API属于Java核心包内时,就会很麻烦。因为Java不允许对这些核心包的任何的外在更改或者是增加。通常这会引起针对不同版本API而维护不同版本代码树的需要。但是,就像上面的例子所演示的那样,你只要维护一棵代码树就能够在不同的版本的API下,编译运行。这个反射的API允许你调用并不存在的方法,而Ant能通过识别不同的Java编译版本而对相应的import包进行调整。虽然上面的所举的例子仅仅是一个简单的演示,但是在实际工作当中,利用这些简单的技术,解决了许多J2SE1.4和J2SE1.3的版本问题。我相信通过这些技术,你可以在频繁的Java版本升级中不必为同时维护两棵代码库而烦恼。

 


关于作者:
Sam Mefford是iCentris的首席架构设计师。对于系统的兼容性重视程度,Sam Mefford是放在第一位的。他带领的团队致力于使用一个代码库
向众多的客户公司提供应用发布方案。这些部署方案使用的应用服务器有Tomcat,Weblogic, Resin, Orion以及 Websphere;在数据库方面有
Oracle,PostgreSQL, MySQL,以及 Informix;以及多个Java运行期环境。

译者: SpikeWang (CSDN ID:hk2000c)

东华大学计算机系毕业,现在同济大学攻读软件工程硕士学位。致力于J2EE方面的企业级应用开发以及研究工作。


About Copyright:
原文章版权属于作者 Sam Mefford
译文版权属于译者及原文作者共同所有,欢迎转载,但要注上译者及原文作者。


参考资源:
The API for java.sql.Connection (J2SE 1.3):
http://java.sun.com/j2se/1.3/docs/api/java/sql/Connection.html

The API for java.sql.Connection (J2SE 1.4):
http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Connection.html

The JDBC API:
http://java.sun.com/products/jdbc/

Java Core Reflection参考概要:
http://java.sun.com/j2se/1.3/docs/guide/reflection/spec/java-reflectionTOC.doc.html

the Reflection API指南:
http://java.sun.com/docs/books/tutorial/reflect/

The Javadoc (java.lang.reflect):
http://java.sun.com/j2se/1.3/docs/api/java/lang/reflect/package-summary.html

 

 

 

 


posted @ 2003-10-03 22:27 hk2000c 阅读(155) | 评论 (0)编辑 收藏

JDOM 介绍及使用指南

一、JDOM 简介
JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。
JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。
在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。
JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter开发出来,以弥补DOM及SAX在实际应用当中的不足之处。
这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来用起来总觉得不太方便。
DOM的缺点主要是来自于由于Dom是一个接口定义语言(IDL),它的任务是在不同语言实现中的一个最低的通用标准,并不是为JAVA特别设计的。JDOM的最新版本为JDOM Beta 9。最近JDOM被收录到JSR-102内,这标志着JDOM成为了JAVA平台组成的一部分。


二、JDOM 包概览
JDOM是由以下几个包组成的
org.JDOM
org.JDOM.input
org.JDOM.output
org.JDOM.adapters
org.JDOM.transform

三、JDOM 类说明

org.JDOM
这个包里的类是你解析xml文件后所要用到的所有数据类型。
Attribute
CDATA
Coment
DocType
Document
Element
EntityRef
Namespace
ProscessingInstruction
Text

org.JDOM.transform
在涉及xslt格式转换时应使用下面的2个类
JDOMSource
JDOMResult

org.JDOM.input
输入类,一般用于文档的创建工作
SAXBuilder
DOMBuilder
ResultSetBuilder

org.JDOM.output
输出类,用于文档转换输出
XMLOutputter
SAXOutputter
DomOutputter
JTreeOutputter

使用前注意事项:
1.JDOM对于JAXP 以及 TRax 的支持
JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具类,默认情况下是JAXP的parser。
制定特别的parser可用如下形式
SAXBuilder parser
  = new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");
 Document doc = parser.build("http://www.cafeconleche.org/");
 // work with the document...
JDOM也支持TRaX:XSLT可通过JDOMSource以及JDOMResult类来转换(参见以后章节)
2.注意在JDOM里文档(Document)类由org.JDOM.Document 来表示。这要与org.w3c.dom中的Document区别开,这2种格式如何转换在后面会说明。
以下如无特指均指JDOM里的Document。


四、JDOM主要使用方法
1.Ducument类
(1)Document的操作方法:
Element root = new Element("GREETING");
Document doc = new Document(root);
root.setText("Hello JDOM!");
或者简单的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));

这点和DOM不同。Dom则需要更为复杂的代码,如下:
DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
DocumentBuilder builder =factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root =doc.createElement("root");
Text text = doc.createText("This is the root");
root.appendChild(text);
doc.appendChild(root);


注意事项:JDOM不允许同一个节点同时被2个或多个文档相关联,要在第2个文档中使用原来老文档中的节点的话。首先需要使用detach()把这个节点分开来。

(2)从文件、流、系统ID、URL得到Document对象:
DOMBuilder builder = new DOMBuilder();
Document doc = builder.build(new File("jdom_test.xml"));

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(url);
在新版本中DOMBuilder 已经Deprecated掉 DOMBuilder.builder(url),用SAX效率会比较快。

这里举一个小例子,为了简单起见,使用String对象直接作为xml数据源:

 public jdomTest() {
    String textXml = null;
    textXml = "<note>";
    textXml = textXml +
        "<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";
    textXml = textXml + "</note>";
    SAXBuilder builder = new SAXBuilder();
    Document doc = null;
    Reader in= new StringReader(textXml);
    try {
      doc = builder.build(in);
      Element root = doc.getRootElement();
      List ls = root.getChildren();//注意此处取出的是root节点下面的一层的Element集合
      for (Iterator iter = ls.iterator(); iter.hasNext(); ) {
        Element el = (Element) iter.next();
        if(el.getName().equals("to")){
         System.out.println(el.getText());
        }
      }
    }
    catch (IOException ex) {
      ex.printStackTrace();
    }
    catch (JDOMException ex) {
      ex.printStackTrace();
    }
  }

很简单把。


(3)DOM的document和JDOM的Document之间的相互转换使用方法,简单!
DOMBuilder builder = new DOMBuilder();
org.jdom.Document jdomDocument = builder.build(domDocument);
// work with the JDOM document…

DOMOutputter converter = new DOMOutputter();
org.w3c.dom.Document domDocument = converter.output(jdomDocument);
// work with the DOM document…

2.XML文档输出
XMLOutPutter类:
JDOM的输出非常灵活,支持很多种io格式以及风格的输出
Document doc = new Document(...);
XMLOutputter outp = new XMLOutputter();
// Raw output
outp.output(doc, fileOutputStream);
// Compressed output
outp.setTextTrim(true);
outp.output(doc, socket.getOutputStream());
// Pretty output
outp.setIndent(" ");
outp.setNewlines(true);
outp.output(doc, System.out);
......
详细请参阅最新的JDOM API手册


3.Element 类:
(1)浏览Element树
//获得根元素element
Element root = doc.getRootElement();
// 获得所有子元素的一个list
List allChildren = root.getChildren();
// 获得指定名称子元素的list
List namedChildren = root.getChildren("name");
//获得指定名称的第一个子元素
Element child = root.getChild("name");
(这里的List是java.util.List)

JDOM给了我们很多很灵活的使用方法来管理子元素
List allChildren = root.getChildren();
// 删除第四个子元素
allChildren.remove(3);
// 删除叫“jack”的子元素
allChildren.removeAll(root.getChildren("jack"));

root.removeChildren("jack"); // 便捷写法
// 加入
allChildren.add(new Element("jane"));

root.addContent(new Element("jane")); // 便捷写法
allChildren.add(0, new Element("first"));


(2)移动Elements:
在JDOM里很简单
Element movable = new Element("movable");
parent1.addContent(movable); // place
parent1.removeContent(movable); // remove
parent2.addContent(movable); // add

在Dom里
Element movable = doc1.createElement("movable");
parent1.appendChild(movable); // place
parent1.removeChild(movable); // remove
parent2.appendChild(movable); // 出错!

补充:
纠错性
JDOM的Element构造函数(以及它的其他函数)会检查element是否合法。
而它的add/remove方法会检查树结构,检查内容如下:
1.在任何树中是否有回环节点
2.是否只有一个根节点
3.是否有一致的命名空间(Namespaces)

 

(3)Element的text内容读取
<description>
A cool demo
</description>

// The text is directly available
// Returns "\n A cool demo\n"
String desc = element.getText();

// There's a convenient shortcut
// Returns "A cool demo"
String desc = element.getTextTrim();

(4)Elment内容修改
element.setText("A new description");
3.可正确解释特殊字符
element.setText("<xml> content");
4.CDATA的数据写入、读出
element.addContent(new CDATA("<xml> content"));
String noDifference = element.getText();

混合内容
element可能包含很多种内容,比如说

<table>
<!-- Some comment -->
Some text
<tr>Some child element</tr>
</table>

取table的子元素tr
String text = table.getTextTrim();
Element tr = table.getChild("tr");

也可使用另外一个比较简单的方法
List mixedCo = table.getContent();
Iterator itr = mixedCo.iterator();
while (itr.hasNext()) {
Object o = i.next();
if (o instanceof Comment) {
...
}
// 这里可以写成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的类型
}
// 现在移除Comment,注意这里游标应为1。这是由于回车键也被解析成Text类的缘故,所以Comment项应为1。
mixedCo.remove(1);

 

4.Attribute类
<table width="100%" border="0"> </table>
//获得attribute
String width = table.getAttributeValue("width");
int border = table.getAttribute("width").getIntValue();
//设置attribute
table.setAttribute("vspace", "0");
// 删除一个或全部attribute
table.removeAttribute("vspace");
table.getAttributes().clear();

 

5.处理指令(Processing Instructions)操作
一个Pls的例子
<?br?>
<?cocoon-process type="xslt"?>
          |        |
          |        |
        目标     数据

处理目标名称(Target)
String target = pi.getTarget();
获得所有数据(data),在目标(target)以后的所有数据都会被返回。
String data = pi.getData();
获得指定属性的数据
String type = pi.getValue("type");
获得所有属性的名称
List ls = pi.getNames();

6.命名空间操作
<xhtml:html
 xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:title>Home Page</xhtml:title>
</xhtml:html>

Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");
List kids = html.getChildren("title", xhtml);
Element kid = html.getChild("title", xhtml);
kid.addContent(new Element("table", xhtml));

7.XSLT格式转换
使用以下函数可对XSLT转换
最后如果你需要使用w3c的Document则需要转换一下。
public static Document transform(String stylesheet,Document in)
                                        throws JDOMException {
     try {
       Transformer transformer = TransformerFactory.newInstance()
                             .newTransformer(new StreamSource(stylesheet));
       JDOMResult out = new JDOMResult();
       transformer.transform(new JDOMSource(in), out);
       return out.getDeocument();
     }
     catch (TransformerException e) {
       throw new JDOMException("XSLT Trandformation failed", e);
     }
   }

参考书目:

1.JDOM官方网站: http://www.jdom.org

2.<<Processing XML with Java>> Elliotte Rusty Harold 2002

3.JDOM API Documentation

4.<<JDOM Makes XML Easy>>Jason Hunter Co-Creator JDOM Project

5.WSDP Tutorial

 

 

 

 

posted @ 2003-09-27 07:19 hk2000c 阅读(239) | 评论 (0)编辑 收藏

仅列出标题
共11页: First 上一页 3 4 5 6 7 8 9 10 11