JavaTM安全体系结构(JDK1.2)

JavaTM安全体系结构(JDK1.2)


本文概述了JDK1.2所实现的主要安全特性的生成动机,介绍了新的类和它们的用法,讨论了这一新的体系结构对现存代码的影响,给出了将来编写安全敏感代码的想法。

内容目录

  1. 引言

    初始沙箱模型

  2. 新的保护机制----基本概念概述

  3. 许可和安全性策略

    3.1许可类

     3.1.1 java.security.Permission
     3.1.2 java.security.PermissionCollection
     3.1.3 java.security.Permissions
     3.1.4 java.security.UnresolvedPermission
     3.1.5 java.io.FilePermission
     3.1.6 java.net.SocketPermission
     3.1.7 java.security.BasicPermission
     3.1.8 java.util.PropertyPermission
     3.1.9 java.lang.RuntimePermission
     3.1.10 java.awt.AWTPermission
     3.1.11 java.net.NetPermission
     3.1.12 java.lang.reflect.ReflectPermission
     3.1.13 java.io.SerializablePermission
     3.1.14 java.security.SecurityPermission
     3.1.15 java.security.AllPermission
     3.1.16 许可含义讨论
     3.1.17 如何创建新的许可类

    3.2 java.security.CodeSource

    3.3 java.security.Policy

     3.3.1 策略文件格式
     3.3.2 策略文件的所有权扩展
     3.3.3 分配许可
     3.3.4 缺省系统和用户策略文件
     3.3.5 用户化策略评估

    3.4 java.security.GeneralSecurityException

  4. 访问控制机制和算法

    4.1 java.security.ProtectionDomain

    4.2 java.security.AccessController

     4.2.1检查许可的算法
     4.2.2特权处理

    4.3访问控制上下文的继承

  5. 安全类装载

    5.1类装载器类层次

    5.2原始类装载器

    5.3类解析算法

  6. 安全性管理

    6.1 管理小应用程序和应用程序

    6.2 SecurityManager与AccessController

    6.3 辅助工具

     6.3.1 键码和证书管理工具
     6.3.2 策略工具
     6.3.3 JAR签字和校验工具

  7. GuardedObject和SignedObject

    7.1 java.security.GuardedObject和java.security.Guard

    7.2 java.security.SignedObject

  8. 未来方向讨论

    8.1 用户、认证和信任
    8.2 资源消费管理
    8.3 许可的随机分组
    8.4 对象级保护
    8.5 创建保护域的子域
    8.6 运行带有签字内容的小应用程序


  9. 结束语
<淘宝热门商品:

小小豆叮

诊断 Java 代码:Broken Dispatch 错误模式

参数上溯造型解决了错误的方法调用

Eric E. Allen (eallen@cyc.com)
Java 软件开发人员带头人,Cycorp, Inc.
2001 年 5 月

在象 Java 语言这样的面向对象的语言中,方法是可重载和可覆盖的,即便在中等复杂程度的程序中,方法调度也会给代码管理带来困难。在本周的诊断 Java 代码中,Eric Allen 讨论了由这些困难导致的错误模式,概述了由于参数不匹配导致的错误方法调用的征兆,同时给出了应对这个问题的一些办法。

整体和部分
还记得这条谚语吗,“整体大于部分之和”?如果把一个个独立的事件组合成一个相互作用的整体,产生的结果会比单个个体的作用之和要大得多。

程序也是一样的道理。随着一个个新方法被添加到程序中,整个程序可能的控制流程迅速增加。对于大型程序而言,很快局面就会无法控制了。就象是一个荒谬而又不可思议的戏法,有时您得到的最终结果并不是您所期望的方向 — 这同您在重载方法或者覆盖方法时遇到的情况有些类似。

快速跟踪代码
清单 1. 实现不可变列表
我们讨论的起点

清单 2. 为链表定义强制参数
编写构造函数以强制类 LinkedList 的所有实例都是 String 列表。

清单 3. 新构造函数用唯一的 String 表达式列表作为参数。
介绍错误的行为

清单 4. 在方法调用中上溯造型参数
重写有关的 LinkedList 构造函数是一种简单的解决方案。

Broken Dispatch 错误模式
面向对象语言的最强大的特性之一就是继承多态性。这一特性允许我们根据参数类型重载和覆盖方法。但是,象其它功能强大的工具一样,这个特性也会引入新的危险。

虽然 Java 程序员们很快就能学会管理一次调用中将调用哪个方法的规则,但在大型程序中却很容易出现这种情况:在一个类中重载了一个方法,结果却是以前在另一个类中可以运行的代码被中断了。这样的错误正符合我所说的 Broken Dispatch 模式。

该模式可以描述如下:

  • 传递给某个重载方法,比如 foo 的参数,却被传给了另一个方法,比如 goo,它支持更广泛的参数类型。
  • goo 然后通过这些参数调用 foo
  • 但是由于 goo 内的这些参数的静态类型更为广泛,因此,可能会调用方法 foo 的错误版本。

象这样的错误很难诊断,因为可能只是添加了新的方法(而不是修改现有的方法)就引入了错误。而且,在发现问题之前,程序可能会继续执行相当长的一段时间。

症状
为了说明这种模式的本质,让我们来看看下面这段示例代码,它是为实现我前面的文章“空标志错误模式”中的不可变列表而编写的。

清单 1. 实现不可变列表


interface List {
  public Object getFirst();
  public List getRest();
}

class Empty implements List {
  public Object getFirst() { throw new NoSuchElementException(); }
  public List getRest() { throw new NoSuchElementException(); }
  public boolean equals(Object that) { 
    return this.getClass() == that.getClass(); 
  }
}

class Cons implements List {
  
  Object first;
  List rest;
  
  Cons(Object _first) {
    this.first = _first;
    this.rest = new Empty();
  }
  Cons(Object _first, List _rest) {
    this.first = _first;
    this.rest = _rest;
  }
  public Object getFirst() { return this.first; }
  public List getRest() { return this.rest; }
  ...
}

在那篇文章中,我们把链表实现作为这些不可变列表的容器。

假设我们在一个独立的包中实现链表,我们知道这个包中类 LinkedList 的所有实例都将是 String 列表。我们可以象下面这样编写构造函数来强制定义该不变量:

清单 2. 为链表定义强制参数


public class LinkedList {

  private List value;

  /**
   * Constructs an empty LinkedList.
   */
  public LinkedList() { this.value = new Empty(); }

  /**
   * Constructs a LinkedList containing only the given element.
   */
  public LinkedList(String _first) { this.value = new Cons(_first); }

  /**
   * Constructs a LinkedList consisting of the given Object followed by
   * all the elements in the given LinkedList.
   */
  public LinkedList(String _first, LinkedList _rest) {
   this.value = new Cons(_first, _rest.value);
  }

  public Object getFirst() { return this.value.getFirst();  }

  public LinkedList getRest() { 
    return new LinkedList(this.value.getRest()); 
  }

  public void push(String s) { this.value = new Cons(s, this.value); }

  public String pop() {
    String result = (String)this.value.getFirst();
    this.value = this.value.getRest();
    return result;
  }

  public boolean isEmpty() { return this.value instanceof Empty; }

  public String toString() {...}
  ...
}

假设我们写了这些代码,并且所有的测试案例都可以正常运行。(或者,更现实些,假设它起初并不能正常运行,可经过几个调试周期后,我们使它变得能够正常运行了。)

也许几个月后,您开发了类 Cons 的一个新构造函数,它使用列表的 String 表达作为其唯一的参数。这种构造函数非常有用 — 它允许我们用下面这样的表达式构造新的列表:

清单 3. 新构造函数仅使用列表的 String 表示法作为参数



  new Cons("(this is a list)")
  new Cons("(so is this)")

这样,我们写了这个构造函数而且它的所有测试案例也正常运行了。太棒了!但是,接着,我们发现,太不可思议了,类 LinkedList 的方法测试中有一些突然中断了。发生了什么事?

起因
问题在于类 LinkedList 的构造函数,它只有一个 String 作为参数。

这个构造函数以前曾调用底层的类 Cons 的构造函数。但是,既然我们用一个更加明确的方法 — 该方法只有一个 String 作为参数 — 重载了这个构造函数,那么被调用的就是这个更加特殊的方法了。

除非传递给 LinkedList 构造函数的 String 是一个有效的 Cons 表示法,否则试图对其进行语法分析时就会导致程序崩溃。更糟糕的是,如果 String 正好是一个有效的 Cons 表示法,程序就会使用这些毁坏的数据继续执行。如果那样的话,我们就在数据中引入了一个破坏者数据。关于破坏者数据的讨论,请参阅最后一部分,“破坏者数据错误模式”。

Broken Dispatch 错误,与所有的错误模式一样,在“布满测试”的代码(借用自极端编程术语)中最容易诊断,在这种环境中连最微不足道的方法也有相应的单元测试。在这样的环境里,最为一般的症状是为您从未碰过的代码编写的测试案例突然中断运行。

如果这种情况发生,有可能是 Broken Dispatch 模式的一种情况。如果测试案例中断是在您重载另一个方法后立即发生的,那就几乎可以肯定。

如果这段代码没有经过布满测试,情况就变得更加困难了。错误症状可能表现为,比如,返回速度比预期快得多(并且结果错误)的方法调用。换句话说,您可能会发现本来应该发生的某些事件从未发生(因为正确的方法未曾被执行)。

要记住,尽管类似的症状也可能是其它错误模式的缘故。但是,如果遇到这种的症状,最好是开始写更多的单元测试,从发现错误的方法开始,回退测试程序执行的过程。

治疗和预防措施
关于这个错误模式的好消息是有一些简单的解决方案。最直接的一种方法是把方法调用中的参数上溯造型。在我们的示例中,这意味着重写相关的 LinkedList 构造函数,如下所示:

清单 4. 在方法调用中上溯造型参数



  public LinkedList(String _first) { 
    this.value = new Cons((Object)_first); 
  }

当然,这种办法只解决了调用 Cons 构造函数这个问题。还有其它地方的调用,我们也得上溯造型,这种技术对于 Cons 类的客户来说是很讨厌的。在这样的情形下,您就得权衡一下,应用这个方便的构造函数给您带来的好处以及它引入错误的潜在危险,二者孰重孰轻了。

接口的表达性和健壮性之间的平衡也存在这种困境。一种两全其美的方法是用一个 static 方法来替代这个 ConsString 构造函数,该 static 方法只有一个 String 作为参数并返回一个新的 Cons 对象。

总结
以下是对上面这个错误模式的总结:

  • 模式: Broken Dispatch
  • 症状:在重载了另一个方法之后,测试您从未碰过的代码的测试案例突然发生中断。
  • 起因: 重载使得未碰过的方法调用了一个方法,而该方法不是您希望调用的那个方法。
  • 治疗和预防措施:插入显式上溯造型。或者,重新考虑您提供给不同的类的方法集。

记住,当您重载或者覆盖一个方法时,参数结构是确保按意图调用方法的一个关键部分。

下个月,我们将暂停错误模式的讨论转而处理其它一些重要的课题。诊断 Java 代码的下一部分将考查尾递归方法如何影响 Java 程序的性能。请不要担心,我们很快就会回到错误模式上来。

参考资料

  • 参加本文的讨论论坛。
  • 务必把 Java 语言规范加为书签,该书提供不错的关于方法调用规则的讨论。
  • 经典的 Java VM 里有一个错误,导致方法覆盖不能正确的调度除它们的父类以外的包里定义的某些子类。请参阅 Sun Web 站点的讨论以获取详细信息。
  • Bill Venners 的 Under the Hood(JavaWorld,1997 年 6 月)讲述了 JVM 中方法调用的字节码实现。
  • 下载 JUnit 并使您的代码“布满测试”。
  • 要得到更多的关于极端编程方法的信息,请阅读“XP 精华”(developerWorks,2001 年 3 月),它提供了关于这种非常受欢迎而且灵活的进程的优秀文摘。
  • 阅读 Eric 的诊断 Java 代码的完整系列。

关于作者
Eric Allen 毕业于 Cornell 大学,曾获得计算机科学和数学的学士学位。他目前是 Cycorp 公司的 Java 软件开发人员带头人,还是 Rice 大学的编程语言小组的兼职硕士生。他的研究涉及 Java 的正规语义模型和 Java 语言的扩展,都是在源代码和字节码的级别上的。目前,他正在为 NextGen 编程语言实现一种从源代码到字节码的编译器,这也是 Java 语言的泛型运行时类型的一种扩展。请通过 eallen@cyc.com 与 Eric 联系。
<淘宝热门商品:

小小豆叮

SMS:关于 Web 服务应用的个案研究

“即时满意”编程成果

Cameron Laird (Cameron@Lairds.com)
副总裁, Phaseit, Inc.
2001 年 8 月

Web 服务正在开始应用于生产。这一关于短消息服务应用程序的个案研究分析了与电信服务 中的 Web 服务开发相关的问题。
Cameron 是独立咨询公司 Phaseit, Inc. 的全职开发人员。他经常撰写关于 Web 服务以及 其它技术主题的文章。可以通过 Cameron@Lairds.com 与他 联系。

Web 服务已“投入生产”。尽管许多商业新闻坚持将 Web 服务作为一种未来的技术进行报道, 然而它已经开始为各种组织机构解决问题了。该个案研究简要描述了一个成功的公开的运用推广在为其编 码的程序员眼中是什么样的。

Web 服务方案便于管理吗?这是一个困扰着许多运用推广计划的关键的不确定因素。developerWorks Web 服务专区的读者们早已认识到 Web 服务是一项可靠的技术,它会在不久的将来变得极为重要。然而 方案计划和实行的结果又是什么呢?Web 服务工作与前几代的客户机-服务器式或基于主机的编程有何不 同呢?Lucin 的公共短消息服务(Short Message Service,SMS)为这些问题提供了线索。

服务运用的种类
首先,让我们来考虑一下 Web 服务的产业环境。如今大多数这样的方案都能归入以下四个类别之一:

  1. 内容管理、协作与联合。这方面的公认的领军者是 Dave Winer 的 Userland、O'Reilly and Associates 的 Meerkat 业务,以及 Jon Udell 为 Linux Magazine 以及 Byte.com 所作的开发和所写的文 章。
  2. 内部服务合并。与 1995 和 1996 年所爆发的“intranet”有所不同,不少 Web 服务的开发是避开公众 视线,在防火墙后展开的。战略上依靠技术多样性的组织机构正将其内部接口作为服务来合并。
  3. CORBA 和 DCOM 的替代品。用 CORBA(更确切地说是 IIOP)或 DCOM 来执行方案或许还是可行的,人们 在去年还采用这种方法。 然而今年,决策者们开始选用 Web 服务作为这些具有竞争力的分布式计算协议的技术替代品了。
  4. 那些以 CORBA 和 DCOM 无法比拟的方式充分利用 Web 服务的公共特性及互操作性的“以程序员为中心” 的方案。

该个案研究可归入这些类别中的最后一个:Web 服务为该应用程序带来了 CORBA 和 DCOM 无法与之匹 敌的重要优势。DCOM 本质上将用户限制为那些运行在 Windows 桌面的用户。而另一方面,CORBA 对于网 关所要求的简单处理来说显得过于“笨重”了。不仅如此,现实中的 CORBA 方案素有受防火墙和互操作 性问题的牵绊之名,而这些问题 Web 服务都能轻松地加以解决。

开发小组:重要统计资料
Lucin PLC 是一 个总部设在英国威尔士的 Newport 的小型软件咨询公司。Mike Clark 是它的创始人和常务董事。它投身 于面向事务的客户机-服务器应用的专业研究已有十余年。2001 年 2 月,三个工程师开始着手于一个“ Web 服务到 SMS”网关的小型演示。几周后,在 3 月份,它就将此项服务向公众开放了。

在大多数欧洲和亚太国家或地区,那里的无线电话都普遍支持“短消息服务(Short Messaging Service)”或者“短消息发送(Short Message Sending)”,尽管这在美国很少见。在日本和其它地区 热火朝天的 SMS 允许电话用户使用手机撰写短小的文本消息,并将它们进行异步传输。它们可被 视为蜂窝式电话的即时消息传递。

相关的电话技术和计算协议捆绑在一起是很自然的,这样计算机就能产生并有可能接收这样的消息了 。 这便是 Lucin 在其“Web 服务到 SMS”网关中所取得的成就;它是未来几个月中几个收费网关中的第一 个:

  • Web 服务到寻呼机
  • Web 服务到传真
  • Web 服务到语音
  • Web 服务到电话应用程序编程接口(telephony application programming interface,TAPI)

在 Lucin 的计划中,再过一段很短的时间,或许就是 2001 年的最后一个季度,它就会具有拨打一个传 统电话,然后用合成的语音读出一条任意消息的能力了。

然而其出发点是 Web 服务与 SMS 的集成。 让我们更仔细地看看第一步。

一种 Web 服务的结构
SMS 网关是一个小 型的软件方案。 许多关于 Web 服务的媒体宣传都设想在大型供应链方案上集成企业应用。Clark 坚持认为,这忽略了一 个要点,那就是“即时满意服务”针对普通的、明确规定的方案,已经运用到了生产中。他有意选择了 SMS 作为模型。 正如 Clark 所指出的那样,“[SMS]就象有着极好使用效果的 Web 服务一样完美地符合这一[模型] ,”但也可能遇到偶尔的供应中断或停机。

当前的基础设备导致我们不得不容忍这些问题。毕竟网络还不是百分之一百的可靠或无所不在的。

一些 Web 服务厂商将“革新”连同其 Web 服务工具的智能性一同兜售。然而不论这个软件在实验室中运 行得如何出色,看上去很少有组织能拥有足够多的连接良好的客户来把那么多重量压在现有的网络上。不 论一个程序的纠错和事务算法有多聪明:除非基础网络连接能获得一笔价格和可靠性均相当可观的订单, 否则建立复杂的 Web 服务就没什么意义。Clark 总结道:“别指望您的用户会因响应时间的缩短而感到 高兴。目前这并非是我们所能掌握的;可能两年后情况会有所不同。”

当前网络基础设备的匮乏迫使 Clark 对 Lucin 作了适当的调整:“我们为一个三年的周期作了仔细 的预算,这意味着我们能在用户基数不大的情况下顺利地维持三年。因为我相信,还需要长时间的艰苦跋 涉,才能让人们认为长期使用 Web 服务对企业来说是足够可靠且值得信赖的。”

与此同时,那几种确实能满足用户的服务可能比您期望的更为简单。Web 服务开发人员将典型的高级 设计看作是从网络上引入数据或对象,对它们进行计算然后使用 Web 服务协议将结果传回网络。Lucin 出售大量符合这一模型的 Web 服务产品并有一些内部工具来支持这样的开发。

然而对于 SMS 网关,Lucin 最终决定采用一种甚至更为简单的方法。Clark 的解释是“……如果您知 道接口的话,便只需构建一个简单的字符串变量,并替换那些您向远程 Web 服务发送数据时会改变的值 。这就节省了不得不引用[SOAP 工具包或模块]所需的时间和开销。"

Lucin 用 Visual Basic 在位于一个 NT Server 4.0 上的产品级版本的 SMS 网关上进行这一简单的 字符串替换,以及其他相关的轻量计算。它所提供的性能对于每天处理的几百条消息(通常在 300 到 800 之间)来说已是绰绰有余了。

该网关的简单性扩展至到了其 身份验证部分:一个通过超文本传输协议(HyperText Transport Protocol,HTTP)以纯文本形式发送的 用户—密码组合。Clark 指出:“您并不希望在登录 Web 站点时使用 HTTPS[安全 HTTP],那又何必用 HTTPS 让用户传递用户名及密码以验证他们使用您的 Web 服务呢?”由于使用 HTTPS 的频率相当高, Clark 指出了其在运行时性能上的缺点,并作了总结:“我们可以在一定程度上使用 HTTPS 的能力,但 差不多应该只在收到用户请求时使用。”

“Web 服务的优点之一,”根据 Clark 的观点,“就是使用简单、牢固的部件所带来的灵活性。”网 关在后端与电信厂商所提供的计量的 SMS 接口相连接。Lucin 已经两度为这个后端改变了供应商,但却 没有中断任何针对客户的服务。网关的用户只需接收关于收到他们的请求的确认;而无需知道或关心后端 的情况。

身份验证,连同验证电话国家或地区代码和本地号码的接口一起,使该网关的 Web 服务描述语言( Web Services Description Language,WSDL)实例成为一个最广泛使用的公开可见的服务(请参阅参考 资料)。它定义了四种操作:SendTextMessageSendMessageValidPhoneNumberGetCountryCodes。其中第二种操作的部分定义如清单 1 所示。

清单 1:process.xml


       <message name="SendMessageRequest">
         <part name="PhoneNumber" type="xsd:string"/>
         <part name="Message" type="xsd:string"/>
	 <part name="SenderName" type="xsd:string"/>
	 <part name="SenderPassKey" type="xsd:string"/>
       </message>
  

Lucin 在该方案中大量地重复运用了其在 Visual Basic 及其同类技术方面的专长。Clark 透露:“ Web 服务只是 DCOM 组件的一个层。”

根据 Clark 的观点,该网关接下来的变化将是:“将它发展成为一种收费服务,”价格为每次 4.5 便士,并与电信供应商签约,合作开发上面提到过的寻呼机、传真以及其它网关。

可操作性结论
作为一个软件方案,SMS 网关是很小的:其设计、实现和部署只需要十几个工作周。由于竞争方面的原因 ,Clark 不愿提供编码的细节。而他公开提出的部分观点是,Web 服务提供了基于组件的软件开发的优势 。适合于 Web 服务的几套要求常常自然分解为即使是初级编程人员也能进行的简单设计。

其它的公共 Web 服务在工程范围内同样看起来很小。XMethods.net 有一个通往 PacBell SMS(在美 国西部)的网关。它有个更为简单的公共接口(请参阅参考资料),仅处理 一个 WSDL operationsendMessage。最为复杂的公共服务接口是 Lucin 的邮件列表管理器演示。它定义了二十六个不同的 operation,所处理的所有数据类型都 很简单,如 string

那么,Web 服务开发有什么特别之处呢?我们都还无法确定。尚未有过任何一家从事大规模的基于 Web 服务开发的公司过多透露他们的经验。在小范围内,这一技术“感觉”就像是其它轻量级的网络的开 发。人们能够阅读 XML,并且有这么多工具可供人们管理使用,这无论如何都是个优点。

Clark 认为:“开发 Web 服务的问题并非开发周期,而是力图创建一个人们愿意为之付钱的 Web 服 务。”随着 Web 自身开始了其第二个十年,基础技术已被理解得相当透彻,但是在为人们可读的 Web 站 点建立“商业模型”方面,仍有许多不能令人满意之处,还需要做大量实验。这也将成为外部 Web 服务 — 介绍中所提到的第四个类别 — 的最大挑战。

当 Web 服务的“组件市场”在 OCX 或 VBX 实践的方式的逐渐成熟起来的时候,它的开发工作也将发 生重大变化。 这一技术已经强调了对构件的使用,而它很可能还会随着越来越多的服务联机入网而不断加强。其中的一 个不同可能就是开放源代码的影响。虽然 OCX 和 VBX 拥有所有权定义,并且授权收费的组件总是统制着 那个领域,然而由于 Web 服务是完全基于公共标准的,因此该技术的许多工具包都是开放源代码的。

参考资料

  • Userland 主页:Dave Winer 的 Userland 是关于 Web 服务内容企业联合组织及相关事物的热衷者和各种实验的可靠场所。
  • “Meerkat, an Open Wire Service”,O'Reilly 的演示给了 Web 服务一个新面貌。
  • 请查阅 Linux Magazine。
  • 请访问 Byte.com。
  • GSM-SMS 概述
  • :SMS 的技术概述 。
  • 请在“Short Message Sending for Wireless”学习 developerWorks 教程。
  • 请查看 Lucin 的 SMS 消息传递 SOAP Web 服务。
  • 这里是 Lucin SMS 网关的 WSDL 实例。
  • 请阅读 Microsoft 白皮书,“IP Telephony with TAPI 3.0”。
  • Bowstreet 关于紧密结合、普遍存在的 Web 服务的雄心勃勃的设想可在白皮书:“Bowstreet - Beyond B2B”中可见一斑。
  • XMethods.net PacBell SMS 的 WSDL 实例。
  • Lucin 邮件列表管理器的 WSDL 实例。
  • 请阅读 Cameron Laird 个人关于 Web 服务的 记录。

<淘宝热门商品:

小小豆叮

支持Java的空调即将推出

  美国空调制造商Carrier公司日前同IBM公司达成一项协议,将在Carrier空调器中加入支持Java的微芯片,使用户能远程设置温度或开关他们的空调。该系统还能向维修技师的手机或PDA实时发送故障码和诊断警示。警示也可通过电子邮件或传真发出。任何可以用无线或有线方式访问Carrier的Myappliance.com网站的用户还能访问他们自己的空调器。空调器内的IBM芯片和软件将接入GSM无线网并接受IBM管理。IBM设计了这个利用嵌入式Java连接到Web服务器的系统,Web服务器允许任何移动设备或桌面设备访问网站。 <淘宝热门商品:

小小豆叮

选择Java 战略决策

王克宏, 许斌, 柳西玲
清华大学计算机系
2001 年 6 月

本文概述了在旧金山举行的2001年全世界Java开发者大会的盛况,各种Java产品的展示和对未来Java技术发展趋势的展望,以及作者参加会议的体会。

1. 概况:
初夏的旧金山,凉风飕搜,夜间寒气逼人,加上近几个月美国经济下滑,各个公司不断辞退员工的消息更增添了人们心理压抑与紧张的气氛,但 JavaOne 2001全世界开发者大会的召开, 却给旧金山带来一股热气和欢快的气氛, 天上整天由一架双翼飞机拖着巨型Java会议的广告条幅在盘旋,地上则是近百辆摩托车队,插着Java会议的广告条旗"呼啸而过、招摇过市",引得行人纷纷行"注目礼", 来自全世界各地的 21000多名Java开发者和爱好者参加了这次大会,有345个公司在展览会上展示各自的Java产品, 大会上共有1200余人发言(包括大会主题报告、技术专题报告、BOF专题讨论会),收到了1000余篇文章;大会的统计资料表明, 全球超过 85%的大型企业正在用Java 开发自己的信息系统, 业界公认: Java 已进入主流计算模式,在美国高等学校中已有80%以上的开设了Java 课程, 已经出版的 Java 书籍超过了2500种;SUN公司的软件产品开发部的总经理Sueltz说: "Java+XML是网络经济的驱动力"; 占全世界95%市场份额的智能卡制造公司都已被授权使用 Java 平台, 预计2001年市场的份额将达到34 亿美元,因此, 信息技术市场的发展正由 Java 来推动;由于对Java 人才市场需求的奇缺, 使得Java 的培训与考证热遍硅谷, 各大公司都在纷纷采取措施, 以争夺Java人才, 以争取在IT市场的主动权.!

华尔街的金融巨头曾经在今年的2月,专门在世界贸易中心召开了一个"2001 Wall Street on Java Technology"会议,会上众多金融巨头几乎一致性地作出了"把Java平台作为金融业开发者的战略选择",认为下一代企业信息化必将以J2EE 为基础框架,这个消息由会议特刊"JavaOne Today"披露出来,对IT 业界产生了不小的震动,因为华尔街老板的举动往往对经济、技术的发展带有导向性作用,成为全球经济发展的风向标,而技术界则往往把它动向看成这个风向标上的定向器,因此,Java 必将象有人在会上报告中比喻"Java的出现和使用象塑料的发明一样,渗透和影响着人类的生活"。

2. 会议特色
大会共有7个专题, 但最吸引人的、突出的话题是Intelligent Web Service (智能Web 服务)、移动计算(J2ME嵌入到手机中)、下一代的企业综合信息求解方案(J2EE)和JXTA(分布计算技术)。

  1. Web Service (Web服务),主要在于通过Web 进行交互式信息定制服务、B2B(B2C)的电子商务的交易活动;
  2. Mobile Computing(移动计算)是会场上普遍都在议论的话题,无论是大会报告还是 Pavilion(产品展示),都是吸引人的地方;
  3. J2EE居于会场四大平台之首,SUN公司已发出29 个J2EE 的使用许可证,其中包括IBM、Oracle、 Motorola、 BEA等,这些公司都在不遗余力地推广J2EE 的使用;
  4. 这次会议上涌现出众多的以Java 起家的新兴软件公司,其中尤为突出的是BEA公司,他们以WebLogic 为拳头产品,号称"世界头号电子商务平台",成为会场上一棵耀亮的明星,以至于可以与全球第二软件巨头Oracle 平起平坐,他的总裁 Bill T.Coleman III 和 Oracle 的总裁Lawreance J.Ellison竟在万人大会上打起了"擂台",做起了竞争演说,把会场气氛推向了又一个高潮,BEA公司在全世界的客户已有9400多个,几乎囊括了世界500强的企业,该公司的e-B 构件库已成为品牌产品,独占电子商务市场,现有员工接近2000人,而该公司仅仅是95年Java正式发布后由三个发起者成立的小公司;

3. Java的发展趋势

  1. IWS(Intelligent Web Service) 智能Web服务是未来IT产业的发展方向,是信息化社会的必由之路,会议中有人认为IWS将是下一代Internet革命的发展方向,包括个性化的信息定制服务(如股票信息查询、货币网上兑换处理等)、电子商务(货物定单、物流配送)等;
  2. 移动计算(移动电子商务,移动通讯设备的巨挚诺基亚(Nokia)的总裁Pekka J.Pietila在会上大出风头,频频亮出各色Java手机,他预言:2003年全世界将会推出 1亿只Java手机,使得"移动计算无处不在,到处都能进行电子商务活动";JavaCard 在无线市场上的潜力会越来越为人们所接收, 人们只要持有一张Java 卡, 在社会就能通行无阻.
  3. 以JXTA为架构的分布计算可能是Internet 发展的又一个新时代,这个架构的基本思路就是不再依靠原来的"以某一个Web为中心,进行点-点的通信控制机制",而是"在某一协议下直接进行Peer-To-Peer"的通讯模式,使得各色电子、电气设备都可以直接联接到Internet上,这可能对分布对象计算、资源的共享与优化配置、多模式交互通信等研究和应用领域都可能产生深远的影响;
  4. 企业的信息化处理, 尤其是基于Web技术的电子商务, B2B的模式是今后企业生存与发展的必 不可少的基础, Intel公司的总裁巴瑞特曾经说过:"不上网的企业必死无疑 !"(最近他在一次 IT业界大会上又重申了这一观点),会上以BEA为首的一些软件公司纷纷以J2EE为基础平台,构造能适合各种企业所需要的电子商务Solution,而其实现的基本途径就是"构造构件库"的思路,尤其是BEA 靠大量销售、出租Components的办法,在全世界电子商务市场上具有举足轻重的地位,受到与会者的高度重视;
  5. Java+XML的结合, 尤其是将 EJB+XML用于电子商务(B2B)的模式,认为这是B2B的驱动力, 因为不管什么类型的电子商务, 企业之间的业务往来都是不同数据结构之间的信息交换, 即异构信息结构的转换和处理, 而这正是XML所能解决的问题, 各行各业都在纷纷上马电子商务, 尤其是 B2B(企业的综合信息系统) 的模式, 受到相当多的大型企业的重视, 如通用电气公司(GE),正在积极地构件B2B的框架, 用 Java 技术就是他们的首选平台;
  6. 嵌入式Java技术,通过嵌入各种类型的传感器和Java技术,即无处不在的计算模式,如 Java卡,所谓"社会一卡通",人们走在社会的任何角落,凭着这张卡就进行商务活动, 定飞机票,查询资料, 发电子邮件,看天气预报等等; 展览会上,把Java技术嵌入到交互电视中, 也是吸引人的一个项目,人们只要用遥控器就能在家里点播所需要的任何电视节目,并且可以与电视节目中的角色进行交互对话;
  7. 实时Java, 如实时性比较强的天气预报, 国防与航空控制等领域, 如飞机驾驶仓中的仪表控制都已经出现用Java技术实现的系统,受到出席会议的用户的青睐.

4. 反思与体会

  1. 企业对 Java的试用热度在不断地升温,从超大型的通用电气公司到中小行企业,都在纷纷转向B2B的模式, 我们应当抓住这个机遇;B2B的框架, 很重要的就是能提供基于Web技术的 Solution(综合问题求解方案), 由于用户使用的平台不同, 客户的环境相异, 因此通过 Java 来进行架构, 是比较理想的途径;因此,我国的企业要想发展, 适应WTO, 必须上马B2B, 这是迟早的事情, 企业的领导应有一个清醒的认识, 而Java+XML 几乎是唯一首选的技术与工具;
  2. 目前美国社会与经济的发展出现了滑坡现象, 但始终抓住与支持高新技术的发展, 是不可否认的共识, 而注重人才的培训, 是所有大中小公司的都非常重视的一个企业生存与发展的战略性措施, 培训Java人才,就是作为人才竞争的一种手段;
  3. Internet 的普及和深入社会生活, 对人们的日常生活的影响, 可以说怎么估计都不为过分, 因此,通过Internet 进行全球范围的交互通讯, 协作求解某一问题, 已成为现实与可能, 会议中不少人认为"下一个十年是实时协作计算的时代",即嵌入领域与RTOS的结合;
  4. 在网络计算模式下, 今后任何人, 在任何时间, 在任何地方都能从Web 上获取任何知识,获取任何模式的服务与信息, 也就是KOD(SOD) 模式(Knowledge On Demand, Service On Demand);
  5. Internet的迅猛发展和基于Web技术的信息服务已经渗透到人类社会的方方面面,在我们的经济发展和科学研究中,必须增强网络意识, 达到资源共享的目的,而Java 和XML则是重要的工具;
  6. 在科学研究和技术开发中要建立创新意识,必须从科学技术源头上创新,社会的信息化覆盖面很广,其源头就是要把社会事务"分门别类、分类管理",这就是"面向对象"的技术和方法,而软件的可重用思想则是这个方法的体现,起实现的途径就是"构件库设计",近年来一些发展迅速的信息公司就是通过"构件库设计"来达到目的的,如著名的电子商务平台供应商BEA公司,在5年时间里由三个人猛增到3000余人,市场实力能与Oracle较真,就是一例。因此,通过J2EE和EJB来实现"构件库设计",提供实现社会信息化创新的基础实施,为社会的发展和人类社会的进步作出贡献。

<淘宝热门商品:

小小豆叮

HTML、Swing还是XML,Java客户端工具选择?(三)

Swing存在的问题在于布署时的速度和兼容性问题。现在,它的一个重大改进解决了这些问题并使Java客户端应用程序重新成为一个可行的选择,CPU的速度在过去2年中翻了一番。在JDK 1.3中,基于Swing的应用程序的运行速度已经非常快了,所需要的内存也相当少。这就使我们在布署Swing方面还存在着最后一个问题,那就是如何进行布署,在这里,我们有三种解决方案可供选择。

  方案一:Java插件

  基于浏览器的Java中最精彩的特性之一是Java插件。对HTML网页作简单的修改就能够消除对浏览器JVM的依赖,并使我们可以在Sun的标准JVM中运行Applet。一旦安装了JRE,Applet就被下载到本地磁盘上,并被放置在高速缓冲区中,再打开带Applet的HTML网页的速度就会快许多,原因是所有的东西都是在本地磁盘上的。为说明其工作原理,我们首先来看看原来的Applet布署方式,HTML网页是如何使用插件的,我们假设你已经掌握了HTML和Java Applet的有关知识,并创建了如下的网页:

<HTML>
<HEAD>
<TITLE>My traditional applet page</TITLE>
</HEAD>
<BODY>
<APPLET CODE=HelloWorld.class ARCHIVE=HelloWorld.jar>
Sorry, looks like I bumped into another browser that doesn't support Java applets
</APPLET>
</BODY>

  这种方式的缺点是它依赖浏览器JVM来加载和执行HelloWorld类。考虑到市场上存在有多种浏览器,它们执行Java的方式各不相同,使得Applet的布署成为一件令人恐惧的事。你必须保证在经过测试的JVM中运行Applet。我们不要求浏览器运行Java,而要求浏览器安装和运行我们将要在其中运行Applet的JVM。在IE中,我们可以通过使用<OBJECT>标志来完成这一任务,在其他的浏览器中,这一标志可能会有所不同,例如在Netscape Navigator中是<EMBED>。修改后的网页如下所示:

<HTML>
<HEAD>
<TITLE>My new applet page</TITLE>
</HEAD>
<BODY>
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
width=100% height=100
codebase="./j2re-1_3_0_02-win.exe#Version=1,3,0,2">
<param name="code" value="HelloWorld.class">
<param name="archive" value="HelloWorld.jar">
<param name="cache_archive" value="HelloWorld.jar">
<param name="cache_option" value="Plugin">
</OBJECT>
</BODY>

上面的网页将使浏览器检查指定ClassID的对象是否已经安装,如果没有安装,则从指定的URL下载JVM,并进行安装。然后浏览器执行插件,并下载和显示Applet。我们可以通过http://192.9.48.9/products/plugin/1.3/demos/applets/GraphLayout/example1.html中的例子来学习其工作原理。关于Java插件更详细的资料请参阅Sun公司的网站。

  插件带来的好处是它可以支持各种操作平台上的所有浏览器,此外,它还提供了一个有保障的执行环境,插件只需要安装一次,就可以对所有Applet进行缓冲,使再次访问网站时非常容易。这一方法的一个最大不足之处是,在运行Applet之前,必须下载一个大小为5MB的插件,这在低速的互联网连接上尤其令人不能容忍。事实上,如果你的Applet只是一个大小为5KB的网页顶端的一个钟表,为此而下载一个5MB的插件是得不偿失的。

  方案二:使用Java Web Start

  布署Java应用软件的另一种方式是Sun公司的Java Web Start,它在本质上与Java插件相似,只是在第一个步骤上有明显的不同。Java Web Start要求在每台台式机上进行人工安装,这一点远不如插件的自动安装。Java Web Start的安装相当简单,一旦安装完毕,依赖Java Web Start的应用程序就可以被下载和安装。就象插件一样,应用程序也是通过互联网发行的。

  根据我的经验,Java插件在安装上与Java Web Start相似,但比Java Web Start的用户亲和性更好,原因是它要求的管理员或用户干预更少。也有一些公司创建了自己的功能类似的布署工具,这些工具有时候比Java Web Start还好用。例如,Sitraka公司的DeployDirector在性能上优于Java Web Start,并且安装也更简单。

  总而言之,通过使用Java插件和Java Web Start,基于Swing的应用程序的布署比原来要简单和安全许多,但仍然比点击一个只有JavaScript的HTML网页要复杂得多。而且有些用户可能对在本地机器上安装JVM所需要完成的步骤有被胁迫的感觉,或者没有发现Swing所带来的好处,但如果需要一个动态GUI用户界面,使用户享有更多地灵活性,没有一种方法比采用Swing Applet更好了。

  此外,如果整个开发都是基于Java的,在HTML请求数据和应用程序内部结构之间就无需进行映射。RMI可以提供快速的双向网络调用,它可以回叫客户端应用程序,提醒用户根据服务器的要求更新显示内容。

  方案三、以纯HTML方式布署Java Swing

  尽管HTML和Swing在开发客户端应用软件方面各有利弊,但很明显的是,理想的解决方案应该是二者都支持。然而,由于这二种技术在本质上具有较大的区别,在一个应用程序中只能采用二者之一。尽管大多数用户都会喜欢基于Swing的快速交互客户端应用程序,但下载并在客户端系统上安装JRE并非总是一个很好的选择。有时候,安全和防火墙方面的限制使得RMI很难在网络上运行。在这种情况下,我们需要的是一种可以在所有系统上运行的交互式客户端应用程序,即使我们能够使用的客户端应用程序只有浏览器。CreamTec公司的WebCream可以充当Swing-HTML之间的桥梁。

  WebCream是一种Java工具,它可以为基于GUI的Java应用程序和Applet提供自动的互联网访问,可以使我们利用AWT和Swing实现GUI前端应用程序,同时,可以自动地使HTML访问该应用程序。在一定程度上,可以把WebCream看作是动态的Java-to-HTML转换工具,它可以即时地把Java中的框架和对话转换为HTML。然后,将Webpage行为模仿为GUI事件,以保持应用程序原有的逻辑。WebCream不要求对现有的表格和业务逻辑进行修改,也无需学习任何新的API,它旨在发行现有的应用程序和applets。WebCream只是设置互联网服务器和描述应用程序属性文件的工具,它的标准版具有全部的功能,而且是免费的。WebCream还无需在客户端的机器上进行安装,甚至无需浏览器支持Java,因为浏览器接收到的全部都是HTML代码。

  据所我知,只有WebCream才具有这样的功能,没有其他的工具可以提供相似的解决方案。但也有一些产品采用不同的方法使原本不是为互联网设计的应用程序具有互联网访问功能。Windows 2000中有一种内置的终端服务器(Terminal Server)服务,可以使用户只要在本地系统登录就可以通过远程方式访问服务器。象Citrix系统公司的MetaFrame那样,终端服务器向远程终端发送一个视频流,并为在服务器上运行的应用程序模仿用户的行为。它在高速网络上可以很好地运行,在低速网络上的表现则不尽人意。它在Java应用程序方面还有问题,因为它们不使用本机的绘制和滚动例程。终端服务器的可伸缩性还不太强,原因是每个用户都在运行它的一个拷贝。由WebCream转换过的应用程序在形式上与在本地系统上运行的应用程序有所不同,但它的性能更好,因为只有用户在提交一个页面时,才会与服务器进行连接。所有由具有WebCream功能的应用程序服务的用户可以共享一个JVM,因此也可以大大降低资源的消耗。

  为了演示WebCream的工作原理,下面的2个图显示了使用WebCream时,一个样例GUI应用程序在HTML前端应用程序中是如何运行的。图1是一个正在运行的GUI应用程序(源代码),图2是WebCream管理着同一个应用程序,窗口表示浏览器中的网页。

 

(图1:例子中的GUI程序)
              

(图2:使用了WebCream后的GUI)


  Swing-HTML转换方式并不适合所有的用户,WebCream在一定程度上允许通过HTML访问前端应用而提高基于Swing的前端应用程序的价值。有95%的应用程序可以无缝地转换成HTML,另有5%的程序则需要改变数据的表达和处理方式。



参考:
HTML、Swing还是XML,Java客户端工具选择?(一) HTML、Swing还是XML,Java客户端工具选择?(二) HTML、Swing还是XML,Java客户端工具选择?(三) HTML、Swing还是XML,Java客户端工具选择?(四) <淘宝热门商品:

小小豆叮

servlet/jsp/xml Frameworks介绍

现在,已经有众多的基于Java的开源Web Framework,让我们能更加容易构造Web应用。我在这里给大家作一个简单的介绍。 Cocoon - 基于XML的Web内容发布 Cocoon是采用100%纯Java编写的一个内容发布框架。Cocoon让你能采用W3C的最新技术(DOM、XML、XSL)来提供Web内容。 新的Cocoon模式能将文档内容、样式、处理逻辑进行完全的分离,允许这三层能独立地设计、创建和管理,从而减少了管理开销,加强了工作的重用性,减少了开发时间。 下载地址:http://xml.apache.org/cocoon Xang - 快速开发动态网页 Xang能整合不同的数据源,让你能快速地开发数据驱动的、跨平台的Web应用。Xang体系结构能将数据、逻辑和表示完全划清。Xang基于开放的工业标准,例如HTTP、XML、XSL、DOM、ECMAScript(JavaScrip)。 下载地址:http://xml.apache.org/xang Slide - 内容管理框架 Slide是一个内容管理和集成系统,是一个内容管理底层框架。Slide提供了一个分级的结构,能将内容存储到任意的、分布式的数据仓库。出此之外,Slide还集成了安全、锁定、内容版本和其他一些服务。 下载地址:http://jakarta.apache.org/slide Struts - 基于MVC设计模式的JSP Struts是采用Java Servlet/JavaServer Pages技术,开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能: 1. 包含一个controller servlet,能将用户的请求发送到相应的Action对象。 2. JSP自由tag库,并且在controller servlet中提供关联支持,帮助开发员创建交互式表单应用。 3. 提供了一系列实用对象:XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。 下载地址:http://jakarta.apache.org/struts Jetspeed - 基于Web的组件 Jetspeed是实现了Enterprise Information Portal的开源软件。Jetspeed能从Internet的纵多资源中提取信息,来帮助用户管理大量的数据。这些信息能来自不同的内容类型,从XML到XMTP,到iCalendar这些新协议。 下载地址:http://java.apache.org/jetspeed Turbine - 基于Servlet的Web应用开发 Turbine是基于servlet的framework,使有经验的Java开发员能快速地构建web应用。 使用Turbine,可以通过创建使用特定服务来处理模板的Screen,来集成现有的模板技术(例如Velocity、Webmacro、Java Server Pages(JSP)、FreeMarker、Cocoon)。 下载地址:http://java.apache.org/turbine 各种Framework比较 在这些framework中,我觉得Cocoon、Struts和Turbine比较好。这三者各有所长,Cocoon是最好的XML Framework,Struts是最好的JSP Framework,Turbine是最好的Servlet Framework。 中华技术网整理发布 http://www.asfocus.com <淘宝热门商品:

小小豆叮

java中文问题详解

java中文问题详解


我来说一下tomcat如何实现jsp的你就明白了。
预备知识:
 1.字节和unicode
  java内核是unicode的,就连class文件也是,但是很多媒体,包括文件/流的保存方式
  是使用字节流的。 因此java要对这些字节流经行转化。char是unicode的,而byte是字节.
  java中byte/char互转的函数在sun.io的包中间有。其中bytetocharconverter类是中调度,
  可以用来告诉你,你用的convertor。其中两个很常用的静态函数是
   public static bytetocharconverter getdefault() ;
   public static bytetocharconverter getconverter(string encoding);
  如果你不指定converter,则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用
  8859_1
  
  我们来就一个简单的例子:
     "你"的gb码是:0xc4e3 ,unicode是0x4f60
     你用:
     --encoding="gb2312";
     --byte b[]={(byte)'\u00c4',(byte)'\u00e3'};
     --convertor=bytetocharconverter.getconverter(encoding);
     --char [] c=converter.convertall(b);
     --for(int i=0;i     --{
     -- system.out.println(integer.tohexstring(c[i]));
     --}
     --打印出来是0x4f60
     --但是如果使用8859_1的编码,打印出来是
     --0x00c4,0x00e3
     ----例1
     反过来:
     --encoding="gb2312";
        char c[]={'\u4f60'};
        convertor=bytetocharconverter.getconverter(encoding);
     --byte [] b=converter.convertall(c);
     --for(int i=0;i     --{
     -- system.out.println(integer.tohexstring(b[i]));
     --}
      --打印出来是:0xc4,0xe3
      ----例2
      --如果用8859_1就是0x3f,?号,表示无法转化      --
      很多中文问题就是从这两个最简单的类派生出来的。而却有很多类  
  不直接支持把encoding输入,这给我们带来诸多不便。很多程序难得用encoding
  了,直接用default的encoding,这就给我们移植带来了很多困难
  --
  2.utf-8
  --utf-8是和unicode一一对应的,其实现很简单
  --
   -- 7位的unicode: 0 _ _ _ _ _ _ _
  --11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _
  --16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
  --21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
  --大多数情况是只使用到16位以下的unicode:
  --"你"的gb码是:0xc4e3 ,unicode是0x4f60
  --我们还是用上面的例子
  --  --例1:0xc4e3的二进制:
  --  --    1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1
  --  --    由于只有两位我们按照两位的编码来排,但是我们发现这行不通,
  --  --    因为第7位不是0因此,返回"?"
  --  --   
  --  --例2:0x4f60的二进制:
  --  --    0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0
  --  --    我们用utf-8补齐,变成:
  --  --    11100100 10111101 10100000
  --  --    e4--bd-- a0
  --  --    于是返回0xe4,0xbd,0xa0
  --  --
  3.string和byte[]
  --string其实核心是char[],然而要把byte转化成string,必须经过编码。
  --string.length()其实就是char数组的长度,如果使用不同的编码,很可
  --能会错分,造成散字和乱码。
  --例:
  ----byte [] b={(byte)'\u00c4',(byte)'\u00e3'};
  ----string str=new string(b,encoding);  ----
  ----如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字  ----
  --这个问题在处理分页是经常发生
  4.reader,writer/inputstream,outputstream
  --reader和writer核心是char,inputstream和outputstream核心是byte。
  --但是reader和writer的主要目的是要把char读/写inputstream/outputstream
--一个reader的例子:
--文件test.txt只有一个"你"字,0xc4,0xe3--
--string encoding=;
--inputstreamreader reader=new inputstreamreader(
----new fileinputstream("text.txt"),encoding);
--char []c=new char[10];
--int length=reader.read(c);
--for(int i=0;i----system.out.println(c[i]);
  --如果encoding是gb2312,则只有一个字符,如果encoding=8859_1,则有两个字符
  --------
--
--
  
   ----
 2.我们要对java的编译器有所了解:
 --javac -encoding
  我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。
  如果没有指定encoding,则按照系统的默认encoding,gb平台上是gb2312,英文平台上是iso8859_1。 
 --java的编译器实际上是调用sun.tools.javac.main的类,对文件进行编译,这个类 --
 有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。
 编译器就是根据这个变量来读取java文件的,然后把用utf-8形式编译成class文件。
 一个例子:
 --public void test()
 --{
 ----string str="你";
 ----filewriter write=new filewriter("test.txt");
 ----write.write(str);
 ----write.close();
 --}
 ----例3
--如果用gb2312编译,你会找到e4 bd a0的字段
--
--如果用8859_1编译,
--00c4 00e3的二进制:
--00000000 11000100 00000000 11100011--
--因为每个字符都大于7位,因此用11位编码:
--11000001 10000100 11000011 10100011
--c1-- 84-- c3--  a3
--你会找到c1 84 c3 a3 --
    
  但是我们往往忽略掉这个参数,因此这样往往会有跨平台的问题:
  --  例3在中文平台上编译,生成zhclass
  --  例3在英文平台上编译,输出enclass
  --1.  zhclass在中文平台上执行ok,但是在英文平台上不行
  --2.  enclass在英文平台上执行ok,但是在中文平台上不行
  原因:
 --1.在中文平台上编译后,其实str在运行态的char[]是0x4f60, ----
 --在中文平台上运行,filewriter的缺省编码是gb2312,因此
 --chartobyteconverter会自动用调用gb2312的converter,把str转化
 --成byte输入到fileoutputstream中,于是0xc4,0xe3放进了文件。
 --但是如果是在英文平台下,chartobyteconverter的缺省值是8859_1,
 --filewriter会自动调用8859_1去转化str,但是他无法解释,因此他会
 --输出"?" ----
 --2. 在英文平台上编译后,其实str在运行态的char[]是0x00c4 0x00e3, ----
 --在中文平台上运行,中文无法识别,因此会出现??
 --  在英文平台上,0x00c4-->0xc4,0x00e3->0xe3,因此0xc4,0xe3被放进了
 --文件
----
1.对于jsp正文的解释:
--tomcat首先看一下你的叶面中有没有"


http://localhost/test/test.jsp?value=你

结果:你好你

但这种方法局限性较大,比如对上传的文章分段,这样的做法是死定的,最好的
解决方案是用这种方案:


你好



必读好文,但解决方案不敢恭维
发言者:小熊
时 间:2000/10/17 17:21:31 来 自:www.javaunion.org


--------------------------------------------------------------------------------

1.网页传参数不提倡用get方法,而且用户可以调整是否用utf-8发送
2.建议jsp中最好不要用,实际上加不加这句都有实现中文正常显示的方案,我认为不加方便些,至少不用写这些代码,如下的配置我认为可以使中文正常显示:
a.所有的javabean用iso8859-1编译
b.jsp文件中不要写以上charset=gb2312的语句(写了反而错)

在tomcat情况下注意以上2点就行---了,等等,对于其他有可能不行的jsp服务器,加上以下
c.服务器上的操作系统语言设为英文(像没有装类似bluepoint中文系统的linux一般本来就是英文)
就行---了

谁要是还不对,请报告....


re:必读好文,但解决方案不敢恭维
发言者:congling
时 间:2000/10/17 21:06:23 来 自:www.javaunion.org


--------------------------------------------------------------------------------

tomcat的参数问题无论是get或是post方式都是用8859_1编码的。这个可以看tomcat servlet实现的源代码:
a) 对于post方法
 javax.servlet.http.httputils的parsepostdata方法: (对于post的form数据)
 string postedbody = new string(postedbytes, 0, len, "8859_1");)这里是没有问题的因为中文都会用%来说明。但是parsename这个函数,却没有把是中文的东西整合起来,他只是简单的拼凑,因此可以认定他是使用8859_1的编码规则
  sb.append((char) integer.parseint(s.substring(i+1, i+3), 16));
----  i += 2;
--
b) 对于get方法
 org.apache.tomcat.service.http.httprequestadapter
   -- line=new string(buf, 0, count,
       constants.characterencoding.default);
----constants.characterencoding.default=8859_1
 这段代码不好跟踪,千万不要被一些假象迷惑住。httprequestadapter是从requestimpl中派生的。但是,实际上用8080端口的server并没有直接用到requestimpl,而是用了httprequestadapter来获得querystring

对于加不加encoding,我保留我的意见,因为如果要解决上传文件分页问题,必须要用他来编码。而且编码能保证在一些beans当中的传递性。

看来我要在这里说明一下了
发言者:小熊
时 间:1970/01/01 07:59:59 来 自:www.javaunion.org


--------------------------------------------------------------------------------

tomcat仅仅是一个对jsp1.1,servlet2.2的一个标准的实现,我们不应该要求这个免费软件在细致末节上和性能上都面面俱到,它主要考虑的英文用户,这也是为什么不作特殊转换我们的汉字用url方法传递有问题的原因,我们大部分浏览器ie其高级设置中始终以utf-8发送url的选项缺省是选上的,如果说这是tomcat的bug也是可以的,另外tomcat不管当前的操作系统是什么语言,好像都按iso8859去编译jsp,我觉得也有点欠妥,但是不管怎么说,新标准的实现和热门的软件在语言的支持方面永远都是先考虑英文

我的方案什么说要好一些呢
1.还是那句话,英文国家的软件永远都是先考虑英文,java虚拟机的规范中要求虚拟机内部必须实现iso8859,unicode,utf-8三种,其他的不作要求,我们用的jdk中的虚拟机就是这样,嵌入式的就更不用说了,也就是说其他的encode都很可能不是java虚拟机内部直接支持的,我们的中文自然也不在其列,需要外部的包支持转换,sun jdk应该在i18n.jar中,用iso8859速度最快,不需要其它调用和交换什么的,更没有读包的io操作
2.至少少写了代码,没有额外操作,简洁的风格谁不喜欢
3.所写的jsp页面国际性化好,我才写了一个jsp+javabeans的聊天室软件(没有用到servlet,jsp真的确实很好),同样的程序美国人用他们的浏览器进入就是英文界面,中文进入就是中文界面,如果加上charset=gb2312至少很麻烦
4.限定了gb2312,如果用户要用gbk,怎么办,不加更好,不管什么的字符集,只要我当前浏览器设定的是,我就能显示出来

总结:无论从速度上,开发效率上,和可扩展性上考虑,我的方案都比你的好,另外,我找不到你的方案比我的好的地方

中华技术网整理发布 http://www.asfocus.com

<淘宝热门商品:

小小豆叮

利用JAVA语言实现支持视频点播的WEB服务器

宏志 一.项目简介:   JAVA语言是一种可移植的,简单的,健壮的嵌入式语言。并且对网络,数据库有很好的支持,基于JAVA语言的这种特性可以十分容易地建立一个小型INTERNET服务器。   本项目中,作者用JAVA语言编写了一个WEB微型服务器,对简单的HTTP请求进行响应,并通过后端数据库对用户的查询进行处理,从而动态地返回HTML页面。 二.项目实现: (一)项目具体功能分析与开发工具选择   可以利用一台较高配置的个人台式机就可以实现社区内的小型服务器,包括网页浏览,基于高速局域网的视频下载和播放,定时新闻组发布程序,邮件服务器等服务。   本软件实际上是一个HTTP协议的服务器。HTTP(Hyper Text Transfer Protocol),是一个专门为Web服务器和Web浏览器之间交换数据而设计的网络协议。它通过规定通用资源定位符(URLs)使客户端的浏览器与服务器的Web资源建立链接关系,从而奠定了用户对Internet透明访问的基础。   在本软件中通过传输HTML文件使客户端可以实现网页浏览。HTML是WWW的通用标记语言,它用来创建Web页面和控制Web信息显示格式。HTML不是编程语言,而是一种描述语言。HTML2.0得到了IETF(Internet Engineering Task Force)的支持而成为Internet国际标准。目前,HTML已经发展到3.0和4.0版,只是新版本的标准尚未完全统一,不同的商家对HTML2.0进行了一定的扩充,引入了更多新的功能。例如,Netscape公司在HTML3.0中增加了页面底图(Background Images)和表(Table)定义等标记,使得Web页面更加引人入胜。   CGI是通用网关接口(Common Gateway Interface)的简称,它是Web服务器与外部程序之间的通信接口,服务器并不关心外部应用程序是什么语言(如C、C++、Pascal、Delphi或Perl)编写的,它只是负责接收用户输入的信息,并把CGI程序所产生的结果--HTML文档或其他符合HTTP规定的文件回传给用户。事实上,CGI是动态Web页面制作的第一步,但由于CGI程序实现比较困难,而且效率不高,它已经逐渐被新的技术所取代。   网页浏览支持的网页包括HTML,JAVASCRIPT,APPLET,VBSCRIPT等编写的网页,但不支持PHP,ASP等服务器端动态程序的网页。由于服务器的规模较小,所以服务器端动态程序被集成进服务器中。但可以通过编写符合一定规则的JAVA的CGI程序实现服务器端的动态性,不过这种JAVA程序的安全性很难保证。 (二)服务器的实现   1. 处理连接策略:   对于每一个用户的连接我们采取了每次请求满足后,将用户与服务器的连接断开,这时用户如果有其他的请求,则进入请求队列重新进行资源竞争。 通常网页中的每一个图形都会被看成是一个单独的连接,也就是说对于一个图形很多的网页基于本服务器的连接策略将会进行多次请求,这样的好处是防止一个容量很大的网页独占网络资源。   2. 与数据库连接   在与数据库的连接中我们选用的后端数据库是微软的ACCESS数据库,由于本项目是面向小型社区的社区数据中心服务器,所以选用小型的数据库。由于JAVA的可移植性可以将服务器用在LINUX平台上,这时可以用本服务器提供的数据库配置程序连接到MySql等基于LINUX的小型数据库。   我们应用JDBC完成与数据库的连接。Java的一项出色能力是构建与平台无关的客户机/服务器数据库应用。在Java 1.1中,通过Java数据库连接(JDBC)实现了与各家公司之间的数据库的互连。数据库最主要的一个问题就是各家公司之间的规格大战。确实存在一种"标准"数据库语言,即"结构查询语言"(SQL-92),但各公司为了表示自己的与众不同对标准都有一些微小的改动。所以通常必须确切知道自己要和哪家数据库公司打交道,否则极易出问题,尽管存在所谓的"标准"。JDBC是面向"与平台无关"设计的,所以在编程的时候不必关心自己要使用的是什么数据库产品。和Java中的许多API一样,JDBC也做到了尽量的简化。我们发出的方法调用对应于从数据库收集数据时想当然的做法:同数据库连接,创建一个语句并执行查询,然后处理结果集,无论与我们打交道的是哪家数据库厂商的产品。   JDBC的使用:   为实现这一"与平台无关"的特点,JDBC为我们提供了一个"驱动程序管理器",它能动态维护数据库查询所需的所有驱动程序对象。所以假如要连接由数家公司开发的不同种类的数据库,就需要每个数据库的单独的驱动程序对象。驱动程序对象会在装载时由"驱动程序管理器"自动注册,并可用Class.forName()强行装载。   为打开一个数据库,必须创建一个"数据库URL",它要指定下述三方面的内容:   (1) 用"jdbc"指出要使用JDBC。   (2) "子协议":驱动程序的名字或者一种数据库连接机制的名称。由于JDBC的设计从ODBC吸收了许多灵感,所以可以选用的第一种子协议就是"jdbc-odbc桥",它用"odbc"关键字即可指定。   (3) 数据库标识符:随使用的数据库驱动程序的不同而变化,但一般都提供了一个比较符合逻辑的名称,由数据库管理软件映射(对应)到保存了数据表的一个物理目录。为使自己的数据库标识符具有任何含义,必须用自己的数据库管理软件为自己喜欢的名字注册(注册的具体过程又随运行平台的不同而变化)。 所有这些信息都统一编译到一个字串里,即"数据库URL"。本例中,我们想通过ODBC子协议同一个标识为"vod"的数据库连接,相应的数据库URL设为:    String dbUrl = "jdbc:odbc:vod"   同样如果通过一个网络连接,数据库URL也需要包含对远程机器进行标识的信息。   JDBC的连接方式:   首先,JDBC中在DriverManager中对数据库数据库驱动程序进行登记。   Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");   装载JDBC- ODBC桥驱动程序,这样做是为了让DriverManager可以找到数据库驱动程序。然后利用DriverManager打开与数据库的连接。   Mycon=DriverManager.getConnection(dbUrl);   本语句的作用是,确定与由dbUrl指定的数据库的连接。DriverManager将从其中登记的驱动程序中寻找最适当的驱动程序。返回的Mycon代表了与特定的数据库之间的连接。    Mysta=Mycon.createStatement();   生成可以执行无参数SQL语句的Statement接口。 然后就可以在Mysta中用executeQuery()函数执行SQL语句从返回的ResultSet获取执行结果。   3. 网络连接:   网络本身的概念并不难。我们想获得位于其他地方某台机器上的信息,并把它们移到这儿;或者相反。这与读写文件非常相似,只是文件存在于远程机器上,而且远程机器有权决定如何处理我们请求或者发送的数据。但大多数编程语言对网络编程都较困难,而Java最出色的一个地方就是它的"无痛苦连网"概念。有关连网的基层细节已被尽可能地提取出去,并隐藏在JVM以及Java的本机安装系统里进行控制。我们使用的编程模型是一个文件的模型;事实上,网络连接(一个"套接字")已被封装到系统对象里,所以可象对其他数据流那样采用同样的方法调用。除此以外,在我们处理另一个连网问题--同时控制多个网络连接--的时候,Java内建的多线程机制也是十分方便的。 服务器的主要任务是侦听建立连接的请求,这是由我们创建的特定服务器对象完成的。而客户机的任务是试着与一台服务器建立连接,这是由我们创建的特定客户机对象完成的。一旦连接建好,那么无论在服务器端还是客户机端,连接变成了一个IO数据流对象。从这时开始,我们可以象读写一个普通的文件那样对待连接。所以一旦建好连接,我们只需使用自己熟悉的IO命令即可。   首先,server=new ServerSocket(80,acceptamount);   生成一个服务器端的套接字。其中第一个参数是表示服务器的监听端口,端口是机器内独一无二的场所。有些时候,一个IP地址并不足以完整标识一个服务器。这是由于在一台物理性的机器中,往往运行着多个服务器(程序)。由IP表达的每台机器也包含了"端口"(Port)。我们设置一个客户机或者服务器的时候,必须选择一个无论客户机还是服务器都认可连接的端口。端口并不是机器上一个物理上存在的场所,而是一种软件抽象(主要是为了表述的方便)。客户程序知道如何通过机器的IP地址同它连接,但怎样才能同自己真正需要的那种服务连接呢(一般每个端口都运行着一种服务,一台机器可能提供了多种服务,比如HTTP和FTP等等)?端口编号在这里扮演了重要的角色,它是必需的一种二级定址措施。   在HTTP协议中的默认服务端口是80,当然在小型社区中也可以使用其它的端口。本例中使用了默认服务端口。 Socket s=server.accept();   这一句的作用是使服务器监听本机上的80端口,等待客户机的连接。在没有新的连接的情况下,服务器阻塞自身。当客户机连接到服务器后函数返回一个套接字。然后,通过套接字的输入,输出流即可用读取本机文件的方法与客户机进行通信。 (三)客户端设计   在客户端,理想的装置是电视机,因为当前电视机普及率高,有线电视线路遍布各地,可重用资源广泛。但目前的电视机绝大多数是模拟电视机,它们只能接收模拟电视信号,无法接收数字电视信号,因此这种电视机的彩色图像和伴音质量并不是很高。而数字电视无论从价格,电台改造,线路改装等方面都存在很大的困难,短期内难以普及。那么能否有一种折衷方案,即使目前的模拟电视机也能接收数字电视信号呢?回答是肯定的。但它们必须附加一个被称作机顶盒(STB)的装置。   1.机顶盒概念介绍:   机顶盒(STB,Set Top Box)的概念比较广泛。从广义上说,凡是与电视机连接的网络终端设备都可称为机顶盒,主要有有线电视网络的模拟频道增补器、模拟频道解扰器,上网机顶盒、数字卫星的综合接收解码器(IRD,Integrated Receive Decoder)、数字地面机顶盒,以及有线电视数字机顶盒都可称为机顶盒。从狭义上说,我们可以将模拟设备排除在外,按主要功能将机顶盒分为上网机顶盒、 数字卫星综合接收解码器、数字地面机顶盒,以及有线电视数字机顶盒,这些设备由于具有很好的网络功能,因此也成为信息家电的代表。 机顶盒也是信号传输介质与电视机之间的一种接口,并提供附加服务,可见它是一种中间电子设备。机顶盒可以把卫星直播数字电视信号、地面数字电视信号、有线电视网数字信号甚至因特网的数字信号转换成模拟电视机可以接收的信号,使现有的模拟电视机用户也能分享数字化传媒带来的清晰,高效的科技成果。同时,它也可以实现电视广播从模拟信号向数字信号的平稳过渡,以及由于种种原因暂时不想购买电脑的人们共享因特网的信息资源和现代化的通信手段。机顶盒有模拟和数字之分,但现在人们所说的机顶盒一般指的是数字机顶盒。   2.机顶盒设计:   本设计中推荐的是上网机顶盒,这种机顶盒实际上是将电视机作为显示器构成了一个多媒体电脑,所以又称为WEB TV。   这种机顶盒主要是通过某种传输介质实现internet接入技术,其传输介质可以是电话线(电话调制解调器),有线电视网络(电缆调制解调器)等。在这种机顶盒中较著名的有微软公司的维纳斯计划,另外我国有许多企业陆续推出了该类产品,如康佳的"光元"网络机顶盒、海信的"家庭网络快车"DB-200M互联网机顶盒、海尔的"网神"网络机顶盒等。但以上的机顶盒大都采用电话调制解调器,这样做的后果是占用了用户家中几乎所有的网络资源(电话线和电视机),却只能实现上网功能随着低价位PC机的普及其市场份额必将进一步下降。同时数字有线电视机顶盒技术却表现出了很大的发展空间。由于有线电视网络较好的传输质量以及电缆调制解调器技术的成熟,使得该类机顶盒可以实现各种交互式应用,从而满足各种用户的要求。事实上,该类机顶盒可以支持几乎所有的广播和交互式多媒体应用,如数字电视广播接收、电子节目指南(EPG)、准视频点播(NVOD)、按次付费观看(PPV)、软件在线升级、数据广播、Internet接入、电子邮件、IP电话和视频点播等。   3.机顶盒中的操作系统:   应用于数字有线电视机顶盒中的操作系统与大家比较熟悉的PC的操作系统,如DOS、Windows98、Windows NT、Unix、MacOS不同,机顶盒中的操作系统不是非常的庞大,但却要求可以在实时的环境中工作,并能在较小的内存空间中运行。这种操作系统称为实时操作系统。   目前流行的实时操作系统有Wind River System公司的VxWorks、Integrated Systems Incorporated公司的pSOS、Microware公司的DAVID OS-9、ST公司的OS20、Windows CE以及专为机顶盒开发的PowerTV等。这些操作系统各有所长,在机顶盒中都有应用。其中VxWorks、pSOS、OS-9、OS20等是通用的实时操作系统,在其他的嵌入式系统中也有广泛的应用。PowerTV是专为机顶盒开发的,并将中间件集成在一起的操作系统,在美国应用较广。随着嵌入式Linux的逐渐成熟,不仅为机顶盒厂商提供了一种选择,而且由于Linux的开放性和先进的结构,会对现有的实时操作系统构成巨大的威胁。   另外,作为UNIX系统的一种变种,LINUX系统在应用软件,系统集成,以及用户开发,使用习惯上都有十分大的优势,所以我们建议使用LINUX系统作为系统平台。   4.中间件   中间件是一种将应用程序与低层的操作系统、硬件细节隔离开来的软件环境,这种分层的思想在现代系统设计中十分常见,如大名鼎鼎的TCP/IP协议。中间件通常由各种虚拟机来构成,如HTML虚拟机、JavaScript虚拟机、Java虚拟机等。   一个完整的数字机顶盒由硬件平台和软件系统组成,可以将其分为4层,从底向上分别为硬件、底层软件、中间件、应用软件。硬件提供机顶盒的硬件平台;底层软件提供操作系统内核以及各种硬件驱动程序;应用软件包括本机存储的应用和可下载的应用;中间件将应用软件与依赖于硬件的底层软件分隔开来,使应用不依赖于具体的硬件平台。这样用户可以在任何厂家的硬件平台上进行应用软件开发,和应用软件下载。不必介意任何低层的有关信息。保证了机顶盒的开发专业化。目前成熟的用于机顶盒的商用中间件产品有Opentv的EN2、Liberate的TV Navigator for DTV、Enreach的EnreachTV for DTV、Canel+ 的Mediahighway和Intellibyte的IB EPG、IB SI Manager、IB Browser等,这些产品在市场上都占有一席之地,但彼此并不兼容。   标准组织已经认识到已有中间件产品兼容性差这个事实,并且开始着手建立开放的中间件标准。DVB提出了基于Java虚拟机的中间件标准DVB-MHP(多媒体家庭平台);ATSC成立了T3/S17技术专家小组委员会,致力于机顶盒软件环境的定义,该软件环境称为DTV应用软件环境(DASE)。ATVEF(先进电视发展论坛)也创建了一种称为Advanced Television Enhancement Forum Specification for Interactive Television 的规范。   其实,任何一种分层结构都不是要求完全一丝不差的按照其结构,在中间件中我们认为JAVA虚拟机较有发展前途。因为首先,JAVA的设计初衷就是为信息家电开发提供一种简单,健壮的嵌入式语言。正是基于这样一种设计目标,JAVA具有小型化的能力可以在简单的环境下运行。而价格方面的原因使机顶盒不可能,也不必要拥有同一时代的标准配置的台式机的功能,这种相对简单的硬件环境是可以运行JAVA虚拟机的。应用JAVA虚拟机的另一个原因是,现在出现了专门运行JAVA语言的JAVA芯片如果应用这种芯片作为机顶盒的CPU,则可以使用专门的JAVAOS作为操作系统,利用JAVA语言的可移植性在台式机上进行应用层开发,借鉴台式机的调试开发经验和工具。 (四)传输压缩方式   在视频点播,网上视频观看中不可避免的要与数据压缩打交道,如何将视频数据,音频数据在一定的失真范围内用最小的数据量传输是数据压缩要研究的一个重要的课题。数字多媒体技术的发展,突破了传统的模拟化图象的应用,图象的采集以及存储、处理、显示等数字化的发展,其使我们设计的可行性大大提高。数据压缩及编码技术是设计中向数字机顶盒传输数据时的关键技术。图象压缩编码从开始系统研究至今已有近50年的历史。1988年,CCITT(现ITU-T)制定了可视电话/会议电视的H.261建议是极具代表性的标准,后来的MPEG-1、MPEG-2、H.263等图象压缩标准都是以它为基础的。声音压缩编码的标准也很多,如ITU-T制定的G.711、G.722、G.728、G.723等。限于笔者的水平我们无法对各种压缩技术进行评价,所以在这里只作简单的介绍。   视频压缩技术中数字图象的压缩是多媒体通信的关键技术,"压缩比"是评价图象压缩方法性能的重要参数之一(也可按每象素多少比特反映压缩特性),图象压缩比反应了图象压缩的困难性和可能程度,ITU-T制订的各种标准压缩比都不同。一般来说,压缩比越大,算法越复杂,实时压缩解压缩的困难程度越大,要求的硬件环境也越高。对于可视电话,若原图象格式采用QCIF(176×144),则原始图象有4.5Mb/s的数据量,若最后用28.8kb/S的MODEM在PSTN上传输,则要提供150多倍的压缩,遵循ITU-T和H.263标准可实现此压缩,另外,H.261和MPEG-1也具有较低的码率,适合于在现有网络上传输视频。MPEG-1广泛用于VIDEO-CD的播放,H.261可应用于N-ISDN可视电话、会议电视、远程医疗、远程教学等各个方面。MPEG-2具有可分级性、可扩展性和互操作性,且易于与ATM、计算机网络联结等一系列高性能,但其码率仍高达4~20Mbps,其主要目标是针对广播电视演播室图象质量和HDTV,现也应用于VOD和DVD的制作。此外,具有高级交互功能、更高图象声音质量和更大灵活性的MPEG-4标准,国际上正在研究制订之中。 三.进一步工作:   新一代数字机顶盒的主要配量CPU将进一步提高主频,其中将具备硬盘和打印控制功能、实时视频解码功能(符合MPEG、Qutik Time标准)和实时音频解码功能(符合MPEG、AC-3和Real Audio标准);以及与电视机遥控器合成一体的遥控键盘,这种键盘可以与现在的键盘接口统一。它还具有硬盘存储、在线打印、画中画、电视与WWW跨接以及电子电视节目指南,电子邮件等功能,除为了实现实时视频解码的硬件解码器外,机顶盒将越来越接近个人桌面电子计算机。它的互联网接入功能将近一步使传统的媒体供应商向网络靠拢。电视节目制作商将自己选定的节目放入WWW网点地址(URL),用户可以通过点击这个标记连接WWW网点,以获取更多的信息,下载视频节目和应用软件。同时用户可以在观看电视节目时使用网上资源。例如,一个学生在观看一段有关火星探险的电视片时,可以点击屏幕上的NASA(美国宇航局)标记,进入NASA的WWW网点浏览最新的航天科技消息,由于传统媒体供应商在媒体制作和销售等方面的经验,现阶段的网络供应商将面对更大的挑战。这种功能对于电视广告商具有极大的吸引力。画中画功能可以使用户一边看电视,一边在因特网上"冲浪",或调阅电子邮件,或进行社区内具有针对性的小范围产品推销。由上可见,Web TV与其说是机顶盒,倒不如说它更像一台具有高速率通信能力的多媒体电脑,只不过它利用现有电视机作显示器,并可将电视机作为因特网终端,而且应用了当前的有线电视技术将电视与因特网融为一体。 参考书目: 1. 数字图象压缩编码在多媒体通信中的应用 北京邮电大学 张家谋 尹昊晖 2. 多姿多彩的数字机顶盒 3. 广播电视技术发展展望杜百川 4. 基于WEB的数据库技术研究 郑成增 陈志锋 陶勇 李思忠 5. Thinking in Java Bruce Eckel 中华技术网整理发布 http://www.asfocus.com <淘宝热门商品:

小小豆叮

HTML、Swing还是XML,Java客户端工具选择?(一)

[前言:] Java软件设计师和管理人员经常会面临这样的难题:在开发应用软件的客户端时,应该在Swing、HTML、XML三种技术中选择谁。在这篇文章中,我将把自己在这三种技术方面的经验与广大读者共享,并对在Java应用软件开发中选择哪一种技术提出一些标准和技巧。在文章的最后,还会介绍一种整合Java Swing和HTML的新方法。

  与现有的技术相比,Java有明显的优点,因此它已经在服务器端应用软件的开发中确立了主导地位。然而,由于每一个应用程序都有几种形式的用户界面和前端的表达形式,我们中的许多人都对在客户端采用Java技术有不好的印象,因此在客户端的开发中采用HTML似乎已经成为唯一的选择了。

  实际情况是,在客户端应用程序的开发中不止只有HTML一种选择,我们将在本文讨论基于Java的应用软件开发中三种用户界面的解决方案。我将首先讨论HTML与JSP和servlet联合使用的优点和缺点,然后讨论Java最初的目标之一:通过GUI Applet实现交互式互联网。最后,我们将讨论XML以及由它所衍生出来的其他技术。

  JSP/Servlets环境下的HTML客户端

  大多数读者都曾编写过servlet、开发过JSP应用,清楚基于HTML的用户界面的优点和缺点。选择HTML的最大的理由仍然是其广泛的平台适应性,基本HTML的标准性很好,虽然比较枯燥,但它可以很好地完成工作。

  由于HTTP/HTTPS协议非常简单,可以使开发的应用程序很好地适应各种网络配置和防火墻。但这是有代价的,HTML缺乏与用户的交互性,而且对用户每个行为的响应都需要与服务器进行连接。作为一名编程人员,我们一直在追求简单性,并使开发的软件可以适合所有的浏览器?然而简单性并不总是好的,简单地说,与静态HTML相比,JavaScript可以较好地实现不太复杂的交互性,但对于开发复杂的用户界面而言,它还是不能胜任的。

  除非拥有高速的互联网连接,否则你一定有过焦急的等待加载一个网页的经历。尽管瘦客户端提供了一些很好的非交互性的用户界面,但传统的胖客户终端一般情况下都比它们更聪明。例如,Netscape Communicator和MS Outlook等电子邮件的前端就比基于互联网的电子邮件工具具有更好的用户亲和性。

  用Java开发一个HTML前端应用是一个很好的选择,因为HTML提供了跨平台的内容传输能力。编程人员可以使用Java Servlets和JSP开发在任何操作系统平台上运行的服务器端应用程序。同时考虑到众多的Java API和它得到的广泛的服务器开发商的支持,对于开发可伸缩互联网站而言,Java是一种理想的选择。

  总而言之,配合使用Servlets和JSP的HTML前端开发工具是开发静态界面的很好的方式,但当需要对用户的行为作出快速反应和需要对数据进行高速处理的复杂应用时,这种方式则不大理想。



参考:
HTML、Swing还是XML,Java客户端工具选择?(一) HTML、Swing还是XML,Java客户端工具选择?(二) HTML、Swing还是XML,Java客户端工具选择?(三) HTML、Swing还是XML,Java客户端工具选择?(四) <淘宝热门商品:

小小豆叮

HTML、Swing还是XML,Java客户端工具选择?(二)

基于Swing的GUI客户端

  今天还有多少人在使用Java Applet作为客户端?也许使用基于HTML的UI更安全,但这是最好的选择吗?

  AT&T的一个业务部门Telecorp PCS曾经开发过一个应用程序,使其商店可以收集希望购买移动电话的用户的资料,检查其信用卡,然后立即开通移动电话,除了确认用户输入的信息外,应用还必须通过使用排序、选择和其他的标准数据库功能处理提交的报告。此外,当一个新的移动电话开通后,这个应用程序还需要显示一个通知。

  你能相像用HTML来完成这一切吗?也许可能,但它将非常讨厌,而且速度很慢,需要不间断地使用网络连接。Telecorp PCS决定冒险在交互的Applet中使用Java,那么结果如何呢?完全成功,这一应用程序在开发时采用了Swing,并布署在采用了Java插件的互联网网站上。通过使用Swing UI类,很简单地完成了应用所要求的功能。

  我相信许多开发人员在早期使用Java时,都使用过applet,并且在解决各种浏览器之间的不兼容性、applet下载时间、性能方面花费过大量的时间。对客户端Java最大的批评来自其对象性,但现在情况已经有了很大的改观。Sun已经花费了大量的时间来改进其代码的质量,下面我将向你说明为什么基于Swing的UI是值得一试的。

   Swing及其布署模式

  我无需对Swing的内部架构以及类和界面的设计、设计模板的实现方面有多少新思想多作叙述了。Swing几乎是我见过的最彻底的窗体系统,它的容器、组件和UI元素之间的关系非常清晰。Swing的架构是基于Model-View-Controller(MVC)设计模板的,其数据与数据的表达和处理相互独立。

  大多数的Swing模型都是由各种UI元素共享的。例如,JTable使用和JList、JTree相同的模型集,这就使得学习和使用Swing非常简单,而且Command、Observable和Listener等模板提供了很好的灵活性和良好的面向对象特性。也许Swing架构中唯一的不足之处是所有的事件都被交付到相同的EventDispatch线程中,使整个GUI客户端应用程序只有一个线程。但我们可以通过使用不同的线程响应用户的命令而不通过EventDispatch线程来完成所有操作,就可以很简单地克服Swing这一缺点。

  Sun发布的每个JDK版本都对Java和Swing的性能都进行了改进。JDK 1.3中与Swing相关的改进表现在性能、内存消耗和一个输入确认框架。性能和内存消耗方面的改进相当可观。我们公司将客户端的应用程序由JDK 1.2.2升级到1.3后,内存消耗降低了30%,一些应用程序内存占用减少得更多。由于Swing内部的初始化过程被优化了,我们的客户端应用程序的运行速度和响应速度都更快了。简而言之,对速度影响最大的是加载其他界面组件时自动产生的大量的类,而这一方案中只包含有一个类。另一个重大的变化是缺省的JVM是HotSpot Client VM,它专门针对GUI绘制和客户端应用程序执行进行了优化,可以通过在命令行方式下运行java命令得到缺省的JVM。
  
  输入确认框可以使我们很方便地通过编程实现命令字段或输入确认。在这以前,如果要在处理下一个字段之前,对前一个用户输入进行处理,必须在该部件上添加一个监听程序,每当该部件不再是焦点后都需要对它进行确认,这种方式非常单调和乏味。使用新的InputVerifier类,可以通过创建InputVerifier子类的一个实例,并将它赋予需要确认的JComponent,就能达到相同的目的。在焦点转换之前,部件将自动地调用verify()方法。

 



参考:
HTML、Swing还是XML,Java客户端工具选择?(一) HTML、Swing还是XML,Java客户端工具选择?(二) HTML、Swing还是XML,Java客户端工具选择?(三) HTML、Swing还是XML,Java客户端工具选择?(四) <淘宝热门商品:

小小豆叮

安装配置Jboss

1、 Jboss的配置安装 1.1、Jboss的下载 Jboss的下载地址为:http://www.jboss.org/。目前的最新版本是:Jboss2.2.1。建议你下载Jboss2.2.1和tomcat3.2.1集成的下载包,这样避免了单个下载后两者之间配置的问题。下载地址是:http://prdownloads.sourceforge.net/jboss/JBoss-2.2.1_Tomcat-3.2.1.zip 下载完成后,解压到一个目录,这个目录名为E:\program files\jb_tom(这个目录名是笔者自定的)。下面有如下子目录: E:\program files\jb_tom\jboss和E:\jb_tom\tomcat 注意:这里的目录稍微做了改动,建议你将TOMCAT_HOME加到CLASSPATH中,否则E:\program files\jb_tom\jboss里的run_with_tomcat.bat这个文件要做相应改动才能正常运行。 1.2、配置运行 在启动Jboss前应该先安装好JDK,建议安装JDK1.3以上的版本(目前最新的正式版本是JDK1.3.1),然后将系统的Classpath设置好。Jboss不要任何配置和修改,当然,最好将TOMCAT_HOME加到Classpath中,这样,E:\program files\jb_tom\jboss里的run_with_tomcat.bat这个文件前的TOMCAT_HOME就可以去掉了。 运行E:\program files\jb_tom\jboss里的run_with_tomcat.bat这个文件,这样,Tomcat端口在8080,Jboss为8083,运行http://localhost:8080/将出现tomcat首页,运行http://localhost:8083/将出现无错误的空白页。 2、 测试EJB 2.1、启动JBOSS: 方法么,这里就不多作描述了,因为前面已经写过了^&^。 2.2、下载并配置EJB例程 到http://www.wodejia.net/softdownload/java/interestejb.zip下载interestejb.zip,这就是我们用于测试的EJB例程。将压缩包解开,出现如下目录: interest/com interest/docs …… 将该目录下所有文件全部copy到jboss安装目录下的examples目录下,如果没有examples目录,就自己建立一个,结构如下: E:\ program files\jb_tom \jboss\examples\interest... 将文件E:\program files\jb_tom\jboss\examples\interest\interest.jar复制到:E:\program files\jb_tom\jboss\deploy下。 在Classpath中加入如下文件:e:\program files\jb_tom\tomcat\lib\servlet.jar;e:\program files\jb_tom\jboss\client\jboss-client.jar;e:\program files\jb_tom\jboss\client\jnp-client.jar;e:\program files\jb_tom\jboss\lib\ext\ejb.jar;e:\program files\jb_tom\jboss\examples\interest\interest-client.jar 为了测试Client通过servlet调用EJB,必须将: E:\program files\jb_tom\jboss\examples\interest下EJB.class和EJB.java复制到: E:\program files\jb_tom\tomcat\webapps\ROOT\WEB-INF\classes目录下 将目录E:\jb_tom\jboss\examples\interest\com以及此下的所有文件都复制到E:\program files\jb_tom\tomcat\webapps\ROOT\WEB-INF\classes下。 重新启动JBOSS_TOMCAT。 2.3、command下client测试运行: command下,进入目录E:\ program files\jb_tom\jboss\examples\interest java InterestClient 将出现: Got context Got reference Interest on 1000 units, at 10% per period, compounded over 2 periods is: 210.00000000000023 Jboss窗口将出现: [Interest] Someone called `calculateCompoundInterest!` 2.4、web下client通过Servlet测试运行: http://localhost:8080/servlet/EJB 将出现: Interest on 1000 units, at 10% per period, compounded over 2 periods is: 210.00000000000023 Jboss窗口将出现: [Interest] Someone called `calculateCompoundInterest!` 到此已经成功了。 注意:这里将JBoss-2.2.1_Tomcat-3.2.1.zip解压后复制到E:\program files\jb_tom目录下 <淘宝热门商品:

小小豆叮

HTML、Swing还是XML,Java客户端工具选择?(四)

基于XML/XSLT的客户端应用程序

       在这里,我们假定你已经对XML有了基本的理解,我将重点讨论其前端应用程序的开发。与XML相关的用户界面开发的一个主要特征是内容和表达方法之间互不干涉。简单地说,就是数据被保存为XML文档,而不再负责数据的使用和显示,根据决定数据格式和在网页上输出方式的样式表(XSLT)在HTML、WML、XHTML和其他表达形式中选择一种数据表达形式。通过使各层之间保持相对的独立,让每个层处理各自的任务,这种方法的优点是非常明显的。

  尽管XML提供了很好的数据发布模式,可以生成不同的表达模式,它仍然不能解决所有的问题。XML值得称道的是让开发人员专注于数据的处理,而让设计人员和艺术家来处理数据的表达形式。应用程序则把生成的XML文件保存在内存或存储在磁盘上,为得到指定的表达类型,例如HTML,可以通过适当的XSLT类型表对内容进行转换,该类型表可以将XML文档转换为HTML文档。类型表与判断文档中的内容应当如何分布在网页上的模板类似。它还可以转换数据,执行传统的命令和循环来处理数据,进行决策,因此它也可能变得非常复杂。

  类型表的优点之一是,如果要从一部移动电话上访问同一个应用程序,所需要作的全部工作就是再创建一个新的WML类型表。从理论上说,这个应用程序的所有其他部分都无需作任何改变,这使得服务器端的编程工作变得非常高效。采用XML实现一个前端应用程序将使一些任务变得简单,因为显示的数据和处理这些数据的代码都无需改变。开发应用程序各部分的开发小组可以独立工作,从而加快开发进程。

  然而,我曾经在基于XML的前端应用程序开发中吃过苦头,它的二个最主要的缺点是缺乏帮助生成XML以及类型表开发方面的工具和处理速度,第一个因素对那些使用DreamWeaver和FrontPage等可视化HTML开发工具创建HTML网页的开发人员的影响更大。就我本人而言,我还是喜欢使用DreamWeaver,但我实在不能从在文本编辑器中编写HTML代码中得到什么乐趣。毕竟,现在已经是21世纪了,我们来看一个将XML文档转换为HTML的非常简单的XSLT类型表:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="page">
<html>

<head>
<title><xsl:value-of select="title"/></title>
</head>

<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="title">
<h1><xsl:apply-templates/></h1>
</xsl:template>

</xsl:stylesheet>



  如果所选的XSL类型表适当的话,上面的代码会生成如下所示的HTML代码:

<html>
<head>
<title>My first page</title>
</head>

<body>
<h1>Hello, world</h1>
</body>
</html>

  我们会发现,上面的代码与我们用HTML开发工具得到的代码不大相同。不幸地是,我们必须用手工的方式对它进行编辑,在一个可以生成HTML文档的工具中对它进行处理后,然后在浏览器中打开生成的文档。如果仅仅是为了美观而改变字体的大小,那么就无需这么作了。

  第二个问题是在运行时完成所有的任务需要许多时间。如果数据格式不是XML,还需要生成XML文档,在类型表对XML进行转换处理后,才能生成HTML代码。与在Servlet或JSP应用程序中向内存缓存中写文件相比,速度和简洁性实在不是基于XML的前端应用程序的优点。

  总而言之,如果需要动态地生成不同版面和窗体的表达形式时,就需要使用XML。如果表达形式需要经常变化或需要非常灵活,就应该让设计人员重新设计新的类型表。需要记信的是,设计人员只要掌握XML和XSLT就万事大吉了。

  另一个需要使用基于XML的UI的场合是你需要处理的资料是XML文档,而不是Java对象或关系数据库。XML是一种在未来颇有前途的新技术,然而,目前使用JSP开发前端应用不是比较方便的,尤其是HTML是唯一一种前端开发工具时更是如此。使用JavaBeans和JSP标识库等一些著名的设计模式则能够使数据的内容和表达形式很好的分离。随着自动对XML/XSLT进行编辑的工具的出现,这些技术在使用方面将更加简单方便。

  结论

  具体到你自己的Java应用程序,这三种前端技术各有利弊,任何一种技术都不能在所有方面超过其他二种。针对具体的应用程序,我们必须对需求、用户的期望进行详细分析,对这三种技术进行评估。下面是一些基本的准则:

  使用HTML/JSP:

   ━━适合于由大量图形和美术作品组成的静态内容。

   ━━前端应用程序的界面面向使用所有平台的用户。

   ━━用户所使用的互联网连接较慢。

   ━━希望快速地构建功能比较单一的应用程序。

  使用Java Swing:

   ━━适合创建具有内置、与界面相关的逻辑的GUI。

   ━━可以减轻网络流量,提供尽可能的即时响应。

   ━━如果用户对界面的质量和功能有较高的期望。

   ━━如果UI的功能比其美感更重要时。

  使用XML/XSLT

   ━━需要支持许多不同的而且经常变化的窗体。

   ━━数据是XML格式。

   ━━需要个性化。

   ━━计划提供无线访问等不同的访问方式。


参考:
HTML、Swing还是XML,Java客户端工具选择?(一) HTML、Swing还是XML,Java客户端工具选择?(二) HTML、Swing还是XML,Java客户端工具选择?(三) HTML、Swing还是XML,Java客户端工具选择?(四) <淘宝热门商品:

小小豆叮

给大家提供一个工具:Java混淆编译器

最近试用了几个Java混淆器(Java Obfuscator),感觉没有一个完全另人满意的,于是想干脆自己写一个得了。翻了几页Java虚拟机规范之后突发奇想,别的混淆器都是在编译好的byte code上做文章,能不能从源码直接编译成经过混淆的class文件呢?就这样花了一个多星期的时间写了一个Java混淆编译器(Java Obfuscator Compiler)。 Q: 什么是混淆器? A: 由于Java程序运行时是动态连接的,因此编译成的目标文件中包含有符号表,使得Java程序很容易被反编译,混淆器可以打乱class文件中的符号信息,使反向工程变得非常困难。 Q: 现有的混淆器有什么问题? A: 现有的混淆器都是对编译好的class文件进行混淆,这样就需要编译和混淆两个步骤。并不是所有的符号都需要混淆,如果你开发的是一个类库,或者某些类需要动态装载,那些公共API就必须保留符号不变,这样别人才能使用你的类库。现有的混淆器提供了GUI或脚本的方式来对那些需要保留的符号名称进行配置,如果程序较大时配置工作变得很复杂,而程序一旦修改配置工作又要重新进行。某些混淆器能够调整字节码的顺序,使反编译更加困难,但我经历过混淆之后的程序运行出错的情况。 Q: Java混淆编译器是如何工作的? A: Java混淆编译器是在Sun JDK中提供的Java编译器(javac)的基础上完成的,修改了代码生成过程,对编译器生成的中间代码进行混淆,最后再生成class文件,这样编译和混淆只需要一个步骤就可以完成。另外可以在源程序中插入符号保留指令来控制哪些符号需要保留,不需要单独的配置。 Q: 如何安装和运行JOC? A: 下载joc.jar (http://www.apusic.com/product/cpsy.htm),运行java -jar joc.jar就可以启动Java混淆编译器,joc的命令行参数和javac完全相同,但增加了一个新的参数-Xobfuscate,它的用法如下: -Xobfuscate: 其中指定混淆级别,可以是以下几种级别: -Xobfuscate:none 不进行混淆 -Xobfuscate:private 对所有private访问级别的元素进行混淆 -Xobfuscate:package 对所有private或package private元素进行混淆 -Xobfuscate:protected 对所有private, package private, protected元素进行混淆 -Xobfuscate:public 对所有的元素都进行混淆 -Xobfuscate:all 相当于-Xobfuscate:public 如果使用-Xobfuscate不带级别参数,则相当于-Xobfuscate:package Q: 如何使用符号保留指令? A: 除了在命令行用-Xobfuscate参数控制符号混淆级别外,还可以在源代码中使用符号保留指令来控制那些符号需要保留,符号保留指令是一个Java文档注释指令,可以插入在类和类成员的文档注释中,例如: /** * This class should preserve. * @preserve */ public class Foo { /** * You can specify which field should be preserved. * @preserve */ private int x; /** * This field is not preserved. */ private int y; /** * You can also preserve methods. * @preserve */ public void hello() {} /** * This method is not preserved. */ private void collect() {} } 如果没有@preserve指令,则根据混淆级别及成员的访问级别来确定符号是否保留。 对于类的符号保留指令可以附带一个保留级别参数,来控制类成员的符号保留,包括: @preserve 仅对类名进行保留,类成员的保留根据-Xobfuscate命令行参数决定 @preserve public 保留所有public成员 @preserve protected 保留所有public和protected成员 @preserve package 保留所有public, protected, package private成员 @preserve private 保留所有成员 @preserve all 相当于@preserve private Q: JOC有哪些限制? A: 不支持分别编译,必须对所有的源文件进行混淆编译。 最后给出一个JOC混淆的效果: 源文件: import java.awt.event.*; import javax.swing.*; public class AboutBox extends JDialog { public AboutBox() { initForm(); } JPanel panel1 = new JPanel(); JButton button1 = new JButton(); JLabel jLabel2 = new JLabel(); JTextArea jTextArea1 = new JTextArea(); /** * NOTE: The following code is required by the form designer. * It can be modified using the form editor. Do not * modify it using the code editor. */ private void initForm() { this.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE ); this.getContentPane().setLayout( new java.awt.CardLayout()); this.setModal( true ); this.setResizable( false ); this.setTitle( "About..." ); panel1.setLayout( null ); button1.setText( "OK" ); button1.setBounds( 272, 168, 88, 24 ); panel1.add( button1 ); jLabel2.setText( "File System Viewer for Swing 1.1.1" ); jLabel2.setVerticalAlignment( SwingConstants.TOP ); jLabel2.setBounds( 64, 32, 240, 56 ); panel1.add( jLabel2 ); jTextArea1.setFont( new java.awt.Font( "Dialog", 0, 10 )); jTextArea1.setLineWrap( true ); jTextArea1.setOpaque( false ); jTextArea1.setText( "This computer program is protected by copyright law." ); jTextArea1.setWrapStyleWord( true ); jTextArea1.setBounds( 8, 112, 256, 80 ); panel1.add( jTextArea1 ); this.getContentPane().add( panel1, "Card1" ); this.setSize( 376, 228 ); button1.addActionListener( new java.awt.event.ActionListener(){ public void actionPerformed( java.awt.event.ActionEvent ev ){ button1_actionPerformed( ev ); }}); } private void button1_actionPerformed(ActionEvent ev) { this.dispose(); } } 经Javac编译后用JAD反编译的结果: import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.text.JTextComponent; public class AboutBox extends JDialog { JPanel panel1; JButton button1; JLabel jLabel2; JTextArea jTextArea1; public AboutBox() { panel1 = new JPanel(); button1 = new JButton(); jLabel2 = new JLabel(); jTextArea1 = new JTextArea(); initForm(); } private void initForm() { setDefaultCloseOperation(2); getContentPane().setLayout(new CardLayout()); setModal(true); setResizable(false); setTitle("About..."); panel1.setLayout(null); button1.setText("OK"); button1.setBounds(272, 168, 88, 24); panel1.add(button1); jLabel2.setText("File System Viewer for Swing 1.1.1"); jLabel2.setVerticalAlignment(1); jLabel2.setBounds(64, 32, 240, 56); panel1.add(jLabel2); jTextArea1.setFont(new Font("Dialog", 0, 10)); jTextArea1.setLineWrap(true); jTextArea1.setOpaque(false); jTextArea1.setText("This computer program is protected by copyright law."); jTextArea1.setWrapStyleWord(true); jTextArea1.setBounds(8, 112, 256, 80); panel1.add(jTextArea1); getContentPane().add(panel1, "Card1"); setSize(376, 228); button1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionevent) { button1_actionPerformed(actionevent); } }); } private void button1_actionPerformed(ActionEvent actionevent) { dispose(); } } 经JOC混淆编译后用JAD反编译的结果: import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.text.JTextComponent; public class AboutBox extends JDialog { JPanel _$1; JButton _$2; JLabel _$3; JTextArea _$4; public AboutBox() { _$1 = new JPanel(); _$2 = new JButton(); _$3 = new JLabel(); _$4 = new JTextArea(); _$1(); } private void _$1() { 2; this; JVM INSTR swap ; setDefaultCloseOperation(); getContentPane().setLayout(new CardLayout()); true; this; JVM INSTR swap ; setModal(); false; this; JVM INSTR swap ; setResizable(); "About..."; this; JVM INSTR swap ; setTitle(); _$1.setLayout(null); _$2.setText("OK"); _$2; 168; 272; JVM INSTR swap ; 24; 88; JVM INSTR swap ; setBounds(); _$1.add(_$2); _$3.setText("File System Viewer for Swing 1.1.1"); _$3.setVerticalAlignment(1); _$3; 32; 64; JVM INSTR swap ; 56; 240; JVM INSTR swap ; setBounds(); _$1.add(_$3); _$4; JVM INSTR new #13 ; JVM INSTR dup ; 0; "Dialog"; JVM INSTR swap ; 10; Font(); setFont(); _$4.setLineWrap(true); _$4.setOpaque(false); _$4.setText("This computer program is protected by copyright law."); _$4.setWrapStyleWord(true); _$4; 112; 8; JVM INSTR swap ; 80; 256; JVM INSTR swap ; setBounds(); _$1.add(_$4); getContentPane().add(_$1, "Card1"); 376; this; JVM INSTR swap ; 228; setSize(); _$2.addActionListener(new IIlIlIIIIlllIIII(this)); return; } private void _$1(ActionEvent actionevent) { dispose(); } /* static void access$0(AboutBox aboutbox, ActionEvent actionevent) { actionevent; aboutbox; JVM INSTR swap ; _$1(); return; } */ // Unreferenced inner classes: /* anonymous class */ final class IIlIlIIIIlllIIII implements ActionListener { public void actionPerformed(ActionEvent actionevent) { AboutBox.access$0(AboutBox.this, actionevent); } { AboutBox.this; this; JVM INSTR swap ; this$0; } } } <淘宝热门商品:

小小豆叮

国产J2EE应用服务器大显身手,中小型网站采用领先技术

日前,由香港天空科技网络有限公司投资营运的天运网(www.365tt.com)技术改造完毕,正式开通试运行。 天运网是采用先进网络技术和运用现代物流管理思想为一体的一站式交通运输商业应用服务(TBSP)网站。立足传统的物流产业资源,以深圳为窗口,面向全国和香港特区提供BSP服务。在天运网总体技术构架设计中,基于JAVA的J2EE技术大显身手,在页面并发响应、网站事务处理、用户查询速度及整体性能上发挥着重要的作用。 天运网项目立项之初,投资方从节约费用的角度考虑,决定将整个项目的技术平台构筑于微软的Windows之上,采用ASP动态网页技术,并投资十几万元人民币委托深圳一家软件公司负责网站开发。由于技术起点低、项目管理能力弱、系统稳定性差,开发出来的网站未能获得多方认可。 第一期网站项目的失败促使天运网必须选择更佳的技术平台和寻找更为成熟的开发团队。经过广泛比较筛选,天运网最终选择了金蝶阿派斯软件公司(www.apusic.com)。Apusic是金蝶国际软件集团的子公司,其自主研发的Apusic Application Server是国内第一个完全符合SUN的J2EE规范、支持企业级应用开发和快速部署的应用服务器。因具有技术与世界同步、性价比高、满足中国国情、本地化服务等诸多优点,成为国内中小型电子商务应用的最佳选择。 金蝶阿派斯公司的主要开发人员均有长期的大型网络商业应用软件开发和项目管理经验,从天运网与阿派斯公司接触开始,JAVA技术和Apusic应用服务器的众多优良特性就打动了天运网的领导和技术人员。采用JAVA组件开发技术就意味着天运网将来有更强大的系统能力和更大的扩展空间。 JAVA技术虽然很好,但天运网考虑到资金投入问题还是有所顾虑,因为,在IT人士的习惯思维里,JAVA技术是高端昂贵的技术。过去,有很多案例表明:采用JAVA技术,虽然一方面能保证项目的快速开发,具有强大的系统能力和简化维护、高扩展性等优秀特性,但选用JAVA平台同时也意味着需要高额的投入,先抛开采用JAVA语言需支出的开发费用比采用其它语言高30%左右不谈,光买一套支持单CPU的国外的应用服务器产品就需要二十多万元人民币,而大型电子商务系统的服务器往往由很多CPU组成,一个完整的电子商务运行平台包括操作系统、大型数据库、高端服务器、应用服务器加起来将是一笔巨大的投入! 目前在美国,80%左右的企业级电子商务平台都选用JAVA,各种迹象也表明JAVA技术即将成为国内电子商务和企业应用开发的主流,但面对“高昂”的投入,许多企业欲言又止。 在金蝶阿派斯公司向客户提交了完善实用的“天运网技术改造策划建议书”后,打消了天运网方面的所有顾虑。方案中选用阿派斯独立自主开发的国产J2EE应用服务器,并推荐采用Linux操作系统和ORACLE8i for Linux大型数据库,在很大程度上降低了总体费用。    与国外同类产品相比,Apusic应用服务器处于同一技术水平,而且还有很多国外产品所不具备的优良特性:如热部署、远程管理等。另外,Apusic应用服务器还有不可比拟的本地化服务与技术支持优势,其核心技术掌握在国人自己手里,随时可根据用户的需求进行调整。 天运网站技术改造总体构架采用国际最为流行的J2EE三层体系结构,构筑在Linux平台之上,数据库采用ORACLE8i for Linux,中间层为Apusi Application Server1.1。前端采用JSP+Servlet,保证了网站的稳定性和页面的快速响应,后端采用了大量的EJB组件,大大提高了网站的可靠性和整体运行性能。 天运网仅用国外同类网站1/10的投入就采用了先进的JAVA技术,满足了性能、可靠性、伸缩性、安全性、跨平台等多方面较高的要求。天运网项目的顺利实施,为国内众多正在寻求电子商务解决方案的企业指明了一条理想之路:由金蝶阿派斯公司提供的国产J2EE应用服务器系列产品,彻底打破了国外同类产品的垄断地位,为各行各业立志建设高效、安全的电子商务应用的企业,提供了采用JAVA平台来构筑企业级计算这种技术高端而投资划算的可行参考。 在金蝶阿派斯的不懈努力下,将加速JAVA技术在国内的迅速普及! <淘宝热门商品:

小小豆叮

谈谈JAVA程序的反编译

Sina.com.cn 于瑶   如今JAVA语言在全世界范围正如火如荼般的流行,它广范地应用在INTERNET的数据库、多媒体、CGI、及动态网页的制作方面。1999年在美国对JAVA程序员的需求量首次超过C++!   作者因最近分析一些JAVA程序,对JAVA的反编译进行了一番了解,下面将我所了解的情况作以下介绍,希望对JAVA爱好者有所帮助。   JAVA是采用一种称做“字节编码”的程序结构,分为小程序(嵌入到HTML文件中)和应用程序(直接在命令状态下执行)两种类型。无论哪种结构,一旦用JAVAC 命令编译后,均变成后缀为CLASS的同名可执行文件。这种文件是不可阅读的代码。   经查阅了SUN公司的JDK(JDK1.1.3)文档资料后,我找到了一个据称是可反编译JAVA的JAVAP文件(EXE),这个文件位于\JDK\BIN\ 下面,经按说明使用后,感到失望,原来这个“反编译”仅可反编译出JAVA程序的数据区(定义)、若干方法和类的引用等。   这里我用了一个简单例子来说明问题。   JAVA的源程序hello_java.java如下:   import java.applet.*;   import java.awt.*;   public class hello_java extends Applet   {   public void paint(Graphics g)   {   g.drawString("Hello Java!\n",20,20);   }   }   经用反编译命令:javap -c -package -public -private hello_java hello.java   得到的反编译结果(hello.java)如下:(有关javap命令的选择参数请见其使用说明,这里-c表示选择了反编译)   Compiled from hello_java.java   public synchronized class hello_java extends java.applet.Applet   /* ACC_SUPER bit set */   {   public void paint(java.awt.Graphics);   public hello_java();   Method void paint(java.awt.Graphics)   0 aload_1   1 ldc #1   3 bipush 20   5 bipush 20   7 invokevirtual #6   10 return   Method hello_java()   0 aload_0   1 invokespecial #5 ()V>   4 return   }   从上述结果不难看出该反编译未能将源程序全译出来,像语句g.drawString("Hello Java!\n",20,20); 就没有。随着程序量增加,未能编译的JAVA语句还会更多。所以这个反编译程序仅能起个参考作用。   幸亏有了INTERNET,笔者通过YAHOO很快找到了一个JAVA反编译“自由软件”(SHAREWARE),http://www.inter.nl.net/users/H.P.van.Vliet/mocha.htm 。 这个软件叫MOCHA,据说是一位30来岁的加拿大的研究生所完成,仅是个“?”版,原因是这位叫做H.P.VAN.VLIET的小伙子患癌逝世了,十分可惜呀!   经使用MOCHA反编译软件,感到这个软件十分好用,笔者试反编译多个JAVA程序,均得到很好的结果。   这里给出如何使用这个软件,首先,用WINZIP等将"mocha-b1.zip" 解开得到"mocha.zip"文件,"mocha.zip"不须再解开,这个包内包括了反编译的类文件,只需将其拷贝到JDK所在的目录下,如:c:\jdk\bin\ 此外,须设置路径:SET CLASSPATH=c:\myclasses;c:\jdk\bin\mocha.zip   MOCHA用法:   java mocha.Decompiler [-v] [-o] Class1.class Class2.class ...   "java" 调用Java虚拟机   "mocha.Decompiler" 指示要进行JAVA反编译   "-v" 选择详细输出   "-o" 选写入已有的.mocha 文件   "ClassX.class" 指出要反编译类名   注意,不需给出输出的JAVA文件名,因为MOCHA自动产生一个与CLASS同名但扩展名为MOCHA的JAVA源文件。   对于上例,可用命令:   java mocha.Decompiler [-v] [-o] hello_java.class   得到的源文件:   /* Decompiled by Mocha from hello_java.class */   /* Originally compiled from hello_java.java */   import java.applet.Applet;   import java.awt.Graphics;   public synchronized class hello_java extends Applet   {   public void paint(Graphics g)   {   g.drawString("Hello Java!\n", 20, 20);   }   public hello_java()   {   }   }   我们不难发现,此文件与编译前的JAVA源文件完全一样!笔者曾经用MOCHA反编译出最大为80K的源文件,均取得成功。   在此,笔者向英年早逝的VLIET表示敬意,感谢他给我们留下这个工具软件。 <淘宝热门商品:

小小豆叮

使用Java语言编写CGI程序

公共网关界面(CGI)是一种编程标准,符合标准的程序(CGI程序),通过WEB服务器与 运行WEB浏览器的客户进行交互。这些程序允许WEB开发者通过浏览器传送动态信 息(通常嵌于HT ML中)。CGI程序可用WEB浏览器能运行的任何语言来书写,其中包 括Java。CGI程序通常用于加入搜索机制、客户登记应用程序、数据库查询机制、 交互式用户论坛和其它一些WEB站点的交互式应用程序。   CGI程序必须解释发送给它的信息,并以某种方式处理这些信息,生成相应结果 回送给客户。   CGI规定了一组标准的环境变量和参数格式,CGI程序的绝大多数输入通过环境 变量传入程序内部。本文将演示如何把环境变量传递给一个Java程序。除环境变 量之外的输入作为标准输入可直接被程序读取。   CGI程序的处理过程可能很简单,也可能象从一个数据库中请求数据那么复杂 。这由具体处理需要而定。   CGI程序可以返回多种类型的文档。因此必须在输出内容中放置一个短的文档 头(HEADE R)(ASCII码文本),使客户知道该如何解释它生成的信息。CGI程序最常 生成的是HTML文档。生成文档头之后,CGI程序以它的本机格式生成输出中的体(B ODY)。在下文中我们将使用一个预先编制的Java库,它包含生成HTML文档头的方法 header()。   一、将CGI环境变量传递给Java程序   编写CGI Java程序较为容易。首先Java程序需要包在另一个脚本中运行。实 际嵌入服务器的脚本将是能把环境变量传入Java程序的UNIX外壳脚本或Windows批 处理文件。   由于Java不再提供直接访问环境变量的方法(最新的JDK版本取消system.get env()方法),因此,建议使用Java解释器的-D命令行参数传递CGI的每个环境变量。 下面将介绍如何使用D参数。   Java使用方法system.getproperty()来访问命令行参数。Java程序需要的任 何一个CGI 环境变量,均可用上述方法来访问。例如,访问server-name环境变量, 可写下行:     string server-name = system.getproperty("cgi.server-name");   下面是一个名为hello.cgi的UNIX脚本文件,它调用名为hello的Java程序。注 意-D命令行参数把CGI环境变量传入Java程序: #!/bin/sh java \ -Dcgi.content-length=$CONTENT-LENGTH \ -Dcgi.request-method=$REQUEST-METHOD \ -Dcgi.query-string=$QUERY-STRING \ -Dcgi.server-name=$SERVER-NAME \ -Dcgi.server-port=$SERVER-PORT \ -Dcgi.script-name=$SCRIPT-NAME \ -Dcgi.path-info=$PATH-INFO \ hello   上述方案不能在Windows 95和Windows NT平台上很好地实现,因为它们在命令 行长度上有限制。但可以把环境变量名及其相关的值写入一个临时文件,然后将该 文件名传递给Java 程序,Java程序读此文件并从中分析出环境变量/值对。   二、JAVA CGI库   为避免重复工作,简化编制程序的过程,可先将一些常用的或固定的处理写成 函数或方法,组成函数库。以后编制CGI程序时,只需考虑主要的处理过程。下文中 使用的方法Header() 和ReadParse假设已在名为cgi-lib.java的函数库中。   三、编制JAVA CGI程序   下面以编制第一节中被hello.cgi调用的hello.java程序为例,说明如何编制 CGI程序。我们将编制一个简单程序来处理"Hello There"格式。它提示用户NAME 和EMAIL地址。要处理的格式(名为hello.html)为: Hello and Welcome!

Hello and Welcome


What is your name?

What is your email address?


  下面开始编制处理"Hello There"格式的Java CGI程序,它实现与客户的交互 。步骤如下:   1.首先,让客户知道该CGI程序将要生成HTML格式。在cgi-lib.java中方法He ader()将生成所需的字符串,因此,Java程序将调用Header()方法及使用system.o ut.println系统调用打印字符串。 // // 打印所需的CGI头 // system.out.println( cgi-lib.Header( ) );   2.其次,要处理通过浏览器发送来的数据。在cgi-lib.java中ReadParse方法 完成这方面的工作,并回送结果到一个哈希表中。本例中,经分析后哈希表的每项 包括两个关键项值。一个是"name"输入域,另一个是"email"输入域。这两个域的 值即是用户在"Hello There"格式中输入的内容。 // // 分析格式中数据后将其放入哈希表中(HashTable) // Hashtable form-data=cgi-lib.ReadParse(system.in)   3.在分析并获取格式数据后,就可以根据需要处理这些数据。完成所需的处 理后再生成HTML文档回送到用户浏览器。为简单起见,本例将不对这些数据作任何 处理,仅仅把它们回送给发数据的用户。我们将对哈希表对象使用get方法,以选取 格式数据值赋给字符串,供程序使用。下例说明如何选取name的值(由用户键入)给 一个字符串对象。     string name=(str ing)form-data.get("name");   综合以上三步,可以生成一个简单程序,即下述用于处理"Hello There"格式的 Java应用程序(hello.java): import java.util.*; import java.io.*; class hello public static void main( string args[ ]) // // Here is a minimalistic CGI program that uses cgi-li b // // // Print the required CGI header. // system.out.println( cgi-lib.Header( ) ); // // Parse the form data into a Hashtable. // Hashtable form-data=cgi-lib.ReadParse(system.in); // // Create the top of the returned HTML page // string name=(string)form-data.get("name"); system.out.println(cgi-lib.Htmltop("Hello There"+name+ "!")); system.out.println("

Hello There"+name + "!

"); system.out.println("Here are the name/value pairs from the form:"); // // Print the name/value pairs sent from browser. // system.out.println(cgi-lib.Variables(form-data)); // // Print the Environment variables sent in form the un ix script. // system.out.println("Here are the CGIenvironment variab les/value pairs"+ "Passed in form the UNIX script:"); system.out.println( cgi-lib.Environment( ) ); // // Create the Bottom of rturned HTML page to close it cleanly. // system.out.println( cgi-lib.HtmlBot( ) );   四、结论   在初步掌握了用Java编写CGI程序的方法之后,我们可以在自己的Web应用中, 以更为适合的方式开发服务器端的应用程序。同时加深对CGI协议的理解,正是CG I协议为客户浏览器和服务器提供了这种通迅途径,使客户可以和Web服务器进行交 互。 <淘宝热门商品:

小小豆叮

我的面向对象程序观

我的面向对象程序观
* description:  描述我对面向对象的一些理解,思想上并不成熟,文章随时都在更新,希望大家都来参与讨论
* copyright:    copyright (c) 2001
* company:      matrixfox
* @author 莫特探员
* @version 本文章还在继续更新中。
*/

我的面向对象程序观

1)面向对象概念的一些误解

“面向对象”是一个如今被人叫烂的词汇,就像去年人们都喜欢把自己的公司打上“.com”的标记一样。其实有多少人能真正理解这个词汇呢,很难说。我喜欢这样来比喻人们对“对象”一词的滥用。“对象”就好比人们经常说的“酷”和“爽”,很多人并不仔细考虑这两个词的差别,在很多情况下他们是通用的,“酷”和“爽”通常表达“心情不错”的意思,你可以在你玩的高兴的时候,大声的叫嚷“太酷了,太爽了”,这个时候两个词汇是通用的。但是你可以说“这个人很酷啊”,但是你不能说“这个人很爽啊”。人们对“对象”这个词汇的滥用就发生在这里,“面向对象”和“基于对象”就好比“酷”和“爽”,这是两个不同的概念,但是人们通常将这两个词汇混为一谈,一律用“面向对象”来表达。常见的错误可以在此列举一些:

1)有个人兴高采烈的和你说“我不喜欢 flash 4 的脚本语言,flash 5 版本的 action script 采用了新的面向对象的“.”语法,写起来很舒服。我现在一直用 flash 5 来做东西。”(同样的话语也发生在 director 的 lingo 脚本语言中)

2)visual basic 采用了面向对象的属性和方法,比起过去的 basic 语言有了很大的提高。

3)javascript 是面向对象的。

等等。

通常听到类似的话,你都要认真审视说话之人,分析他说的话。可以肯定一点,他并非真正懂得什么是面向对象的思想。很多人没有区分“面向对象”和“基于对象”两个不同的概念。面向对象的三大特点(封装,继承,多态)却一不可,通常“基于对象”使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点,而“多态”是表示为父类类型的子类对象实例,没有了继承的概念也就无从谈论“多态”。现在的很多流行技术都是基于对象的,它们使用一些封装好的对象,调用对象的方法,设置对象的属性。但是它们无法让程序员派生新对象类型。他们只能使用现有对象的方法和属性。所以当你判断一个新的技术是否是面向对象的时候,通常可以使用后两个特性来加以判断。“面向对象”和“基于对象”都实现了“封装”的概念,但是面向对象实现了“继承和多态”,而“基于对象”没有实现这些,的确很饶口。


2)java 比 c++  在贯彻面向对象的思想方面更加彻底。
我最近上的学习班的老师对我说:“c++ 是打着面向对象的幌子,干着过程编程的勾当”,这句话我非常的赞同,而且我一直以来也是这么认为的。但是仔细听他讲解后,我才发现,我是只是理解了这句话前两层的意思。但是还有一层意思我没有理解。你可能要问,“难道 c++ 不是面向对象的吗?”。事实上 c++ 是真正的面向对象编程语言。但是它也是过程编程语言。为什么怎么说呢, c++ 的产生不但考虑了面向对象的特性,而且也更多的考虑了对 c 语言的向后兼容,使得 c++ 这种杂合语言表现出“过程”和“对象”编程的双重性。你通常既可以继续用 c++ 编译器来编写传统的 c 程序,也可以使用 c ++ 的类库或者编写自己的类来作面向对象编程。这种“两面性”使得人们可以继续保留原有的 c 代码,同时也阻碍了面向对象思想的推广。


举个简单的例子,94 年的时候,我开始学习 c++ ,当时是学习 turbo c++ 自己带的一个叫作 turbo vision 的类库来做项目。我的同学也用 turbo c++ ,但是他一点也没有学习过 c++ 这个语言,他只是用 turbo c++ 编译器来重新编译他以前用 turbo c 写的程序,然后他自豪的对我说:“瞧,我用 c++ 做的东西”,好像意思是说“我用 c++ 开发项目了”,在那个 c 比 pascal 高档, pascal 比 foxbase 高档的年代里, c++ 的标签绝对是个很"酷"的标志。我其实很清楚他的行为。这就是“c++ 是打着面向对象的幌子,干着过程编程的勾当”的第一重意思,也就是说, c++ 编译器对 c 程序的兼容性造成了最底层的“过程勾当”。在国内有很长一段时间,人们都是在用 c++ 编译器做 c 编程。 我当时在想,比起我那个同学,我才是真正懂得面向对象的人。 我学习了 c++ 语言,我懂得封装,继承和多态,我学习了 turbo vision 的类库,我派生了 turbo vision 的类库并编写了自己的类,所以我是懂得面向对象的。从某种意义上说,我这么想是对的。但是从面向对象程序员的分类来说,我又不完全懂得面向对象的思想。从事面向对象编程的人按照分工来说,可以分为“类库的创建者”和“类库的使用者”,通常创建类库的人才是真正懂得面向对象思想的人,他们创建类库供给那些“客户程序员”来使用,他们从头开始制作类库,他们进行面向对象的分析,设计,实现的全过程。当学习完 c++ 后,我的第一个感觉是,从头创建一个类库真是很麻烦的事情,通常用 c 过程编程很容易实现的功能,你必须按照类的思想来从新建立对象,但是一旦类库建立好后,使用类库和派生类,以及维护代码都是非常舒服的事情。使用类库的人并不都是具备了面向对象思想的人,通常知道如何继承和派生新对象就可以使用类库了,然而我们的思维并没有真正的转过来,使用类库只是在形式上是面向对象,而实质上只是库函数的一种扩展。这就是我理解的“c++ 是打着面向对象的幌子,干着过程编程的勾当”的第二重意思,实际上用 c++ 编程的人,大部分不自己创建类,而是使用类库,这样就造成了他们把类库作为一种高级的库函数库来理解,并没有真正理解面向对象的思想。


c++ 的面向对象的思想推广很慢,直到 mfc ,owl ,vcl 这样的类库出来以后,人们才渐渐的接受了一些面向对象的思想。为什么这条面向对象的道路那么难走?我的答案是“因为 c++ 给了我们第二条道路去走过程编程”,当然原因是为了考虑兼容 c 语言,然而正是由于有了第二条老路才使得使得我们不会再去考虑新的面向对象编程思维方式。


直到出现了 java ,才真正迎来了面向对象的曙光。java 真正是革命性的东西吗?不是,所有现有的 java 的思想都是继承自其他的语言和技术,没有什么革命的地方,虚拟机的概念早在 20 年前的 ucsd pascal 中就采用了,只是当时的机器速度太慢,虚拟机仿真造成的性能降低对于当时的硬件来说是相当严重的。java 本身的很多东西也借鉴了 c++ 语言,连它的创始人也说,java 是 "c++--" 也就是说 java 去除了 c++ 的一些不太好的地方。所以说 java 本质上没有什么革命的东西,所以那些对 java 的赞美之词都是 sun 公司的宣传伎俩。没有一种语言会长久的存在下去,你很难说你的孩子在二十年后还会继续使用 c++ 或 java,所以我们要抛开这些浮华词汇的背后,找寻真正我们需要学习的东西。否则今天我们大家都是微软的傀儡,明天 sun 公司起来了,我们就都是 sun 的傀儡。仔细研究美国电脑技术发展的历史,美国人一向喜欢象第三世界兜售他们的过时技术,而他们始终可以自豪的说,我们将永远领先你们第三世界国家二十年。我们始终在跟在美国人的后面学习他们的东西,这的确让人担忧。我说着说着又跑题了。java 虽然没有什么真正的革命性的东西,但是 java 在真正推动面向对象编程思想方面是功不可末的。使用 java 编程,你无需考虑到向后兼容什么语言的问题,它是重新建立的语言,你在掌握这门语言之前,你必须将自己的编程思想由过程编程彻底转向面向对象编程,因为 每个 java 程序,本身就是一个类,你编写任何 java 程序,你都不自觉的在构造一个对象模板,没有第二条道路,只能是面向对象编程。( 我非常喜欢 java 将所有类定义和类声明放在一个文件中,而不是象 c++ 那样,cpp 和 .h 文件是分开的。通常刚刚开始学习 java 的人不习惯,不过学习一段时间,你就会体会到它的好处了。), 使用 java 编写程序(我更喜欢说---编写类,而不是程序)的时候,你会必须从一个对象的角度来考虑问题,因为你的程序就是一个类,你必须考虑把哪些东西作为成员变量,哪些作为方法,要生成几个类,哪些变量是成员变量,哪些是静态的变量和方法,等等。通常做完一个项目,你就已经将面向对象的思想运用其中了。之所以说 java 在面向对象的贯彻方面要比 c++ 彻底,就是因为你只能使用面向对象的方式来编写 java 程序,而 c++ 却可以采用另外一条非面向对象的方式来编写程序。java 并没有什么真正革命性的东西,它最大的贡献当然是推广面向对象的思想了。

java 总的来说是降低了继续过程编程的可能性,但是并没有完全消除它。面向对象是一种思想,是我们考虑事情的方法,通常表现为为我们是将问题的解决按照过程方式来解决呢,还是将问题抽象为一个对象来解决它。很多情况下,我们会不知不觉的按照过程方式来解决它,因为我们通常习惯于考虑解决问题的方法,而不是考虑将要解决问题抽象为对象去解决它。很多新的技术使我们更加趋向于过程而非对象的思想。最明显的就是 rad (快速应用程序开发)可视技术的出现,人们可以通过设置属性和编写事件函数来快速开发应用程序,编写事件函数就是典型的按照过程编程的思想(至少我是这么认为的),试问有多少人能区分vb 和 delphi ,c++ builder ,java 的事件函数编写有什么本质的区别, 后三者都采用了 delegation (委托模型),在 java 中是通过 anonymous 类(无名类),或者 adapter 类来实现delegation,这是一种面向对象的构想,但是 vb 不是,所以这底层的区别都被上层的相似性所抹杀了,使用 jbuilder 编程的时候,我们如果没有仔细研究 java 的 awt.event 编程方式的话,通常也是把它当作普普通通的“类 vb"的编写方式来写程序,而实际分析它在后台所生成的代码,你才能明白这些代码是真正的面向对象的,但是如果你只是简单的把它当作可视编程工具,你是永远不会明白什么是”委托模型“,什么是面向对象编程的。这是我理解的 “c++ 是打着面向对象的幌子,干着过程编程的勾当”第三重意思。无论是 c++ 还是 java 都有可能走过程编程的老路, java 降低的过程编写的可能性,但是如果你没有具备面向对象的编程思想,你还是可能走面向过程的老路的。 <淘宝热门商品:

小小豆叮

如何从 JAR 和 zip 档案文件中提取 Java 资源

如何从 jar 和 zip 档案文件中提取 java 资源
您是刚开始接触 jar 文件吗?这个新类可帮您解决问题!

作者:john d. mitchell 和 arthur choi
摘要
将一类 java 资源打包在一个 java archive (jar) 文件中是缩短下载时间、增强安全性和增强可管理性的极好方法。这篇技巧说明如何很容易地从 jar 文件中提取资源以供您自己使用。
多数 java 程序员都非常清楚使用 jar 文件将组成 java 解决方案的各种资源(即 .class 文件、声音和图像)打包的优点。(如果您不熟悉 jar 文件,请参阅后文的参考资源部分。)刚开始使用 jar 文件的人常问的一个问题是:“如何从 jar 文件中提取图像呢?”本文将回答这个问题,并会提供一个类,这个类使从 jar 文件中提取任何资源变得非常简单!

加载 gif 图像
假定我们有一个 jar 文件,其中包含我们的应用程序要使用的一组 .gif 图像。下面就是使用 jarresources 访问 jar 文件中的图像文件的方法:

    jarresources jar = new jarresources ("images.jar");
    image logo =
 toolkit.getdefaulttoolkit().createimage (jar.getresource ("logo.gif");

这段代码说明我们可以创建一个 jarresources 对象,并将其初始化为包含我们要使用的资源的 jar 文件 -- images.jar。随后我们使用 jarresourcesgetresource() 方法将来自 logo.gif 文件的原始数据提供给 awt toolkit 的 createimage() 方法。

命名说明
jarresource 是一个非常简单的示例,它说明了如何使用 java 1.1 所提供的各种功能来处理 jar 和 zip 档案文件。

关于命名的简要说明。java 中的归档支持实际上是以流行的 zip 归档格式为起点的(请参阅 "java tip 21: use archive files to speed up applet loading")。因此,在最初实现处理档案文件的 java 支持时,所有类文件以及诸如此类的东西并未放在 java.util.zip 包中;这些类通常以 "zip" 开头。但在转向 java 1.1 时,功能已发生了变化,档案文件的名称也更具有 java 特征。因此,现在我们称之为 jar 文件的文件基本上是 zip 文件。

工作方式
jarresources 类的重要数据域用来跟踪和存储指定 jar 文件的内容:

public final class jarresources {

   public boolean debugon=false;

   private hashtable htsizes=new hashtable();
   private hashtable htjarcontents=new hashtable();

   private string jarfilename;

这样,该类的实例化设置 jar 文件的名称,然后转到 init() 方法完成全部实际工作。

   public jarresources(string jarfilename) {
      this.jarfilename=jarfilename;
      init();
   }

现在,init() 方法只将指定 jar 文件的整个内容加载到一个 hashtable(通过资源名访问)中。

这是一个相当有用的方法,下面我们对它作进一步的分析。zipfile 类为我们提供了对 jar/zip 档案头信息的基本访问方法。这类似于文件系统中的目录信息。下面我们列出 zipfile 中的所有条目,并用档案中每个资源的大小添充 htsizes hashtable:

   private void init() {
      try {
          zipfile zf=new zipfile(jarfilename);
          enumeration e=zf.entries();
          while (e.hasmoreelements()) {
              zipentry ze=(zipentry)e.nextelement();
              if (debugon) {
                 system.out.println(dumpzipentry(ze));
              }
              htsizes.put(ze.getname(),new integer((int)ze.getsize()));
          }
          zf.close();

接下来,我们使用 zipinputstream 类访问档案。zipinputstream 类完成了全部魔术,允许我们单独读取档案中的每个资源。我们从档案中读取组成每个资源的精确字节数,并将其存储在 htjarcontents hashtable 中,您可以通过资源名访问这些数据:

          fileinputstream fis=new fileinputstream(jarfilename);
          bufferedinputstream bis=new bufferedinputstream(fis);
          zipinputstream zis=new zipinputstream(bis);
          zipentry ze=null;
          while ((ze=zis.getnextentry())!=null) {
             if (ze.isdirectory()) {
                continue;
             }
             if (debugon) {
                system.out.println(
                   "ze.getname()="+ze.getname()+","+"getsize()="+ze.getsize()
                   );
             }
             int size=(int)ze.getsize();
             // -1 表示大小未知。
             if (size==-1) {
                size=((integer)htsizes.get(ze.getname())).intvalue();
             }
             byte[] b=new byte[(int)size];
             int rb=0;
             int chunk=0;
             while (((int)size - rb) > 0) {
                 chunk=zis.read(b,rb,(int)size - rb);
                 if (chunk==-1) {
                    break;
                 }
                 rb+=chunk;
             }
             // 添加到内部资源 hashtable 中
             htjarcontents.put(ze.getname(),b);
             if (debugon) {
                system.out.println(
                   ze.getname()+" rb="+rb+
                   ",size="+size+
                   ",csize="+ze.getcompressedsize()
                   );
             }
          }
       } catch (nullpointerexception e) {
          system.out.println("done.");
       } catch (filenotfoundexception e) {
          e.printstacktrace();
       } catch (ioexception e) {
          e.printstacktrace();
       }
   }

请注意,用来标识每个资源的名称是档案中资源的限定路径名,例如,不是包中的类名 -- 即 java.util.zip 包中的 zipentry 类将被命名为 "java/util/zip/zipentry",而不是 "java.util.zip.zipentry"。

代码的最后一个重要部分是简单的测试驱动程序。该测试驱动程序是一个简单的应用程序,它接收 jar/zip 档案名和资源名。它试图发现档案中的资源文件,然后将成功或失败的消息报告出来:

   public static void main(string[] args) throws ioexception {
       if (args.length!=2) {
          system.err.println(
             "usage: java jarresources "
             );
          system.exit(1);
       }
       jarresources jr=new jarresources(args[0]);
       byte[] buff=jr.getresource(args[1]);
       if (buff==null) {
          system.out.println("could not find "+args[1]+".");
       } else {
          system.out.println("found "+args[1]+ " (length="+buff.length+").");
       }
   }

} // jarresources 类结束。

您已了解了这个类。一个易于使用的类,它隐藏了使用打包在 jar 文件中的资源的全部棘手问题。

练习
现在您对从档案文件中提取资源已有了一定的认识,下面是可用来修改和扩展 jarresources 类的一些说明:

  • 不在构造期间一次性加载全部内容,而要延迟加载。对于大型 jar 文件,构造期间可能没有足够的内存加载全部文件。

  • 不只是提供类似 getresource() 这样的一般读方法,我们还可提供资源特定的读方法 -- 例如,用来返回 java image 对象的 getimage() 方法,用来返回 java class 对象的 getclass() 方法(在自定义的类加载程序的协助下),等等。如果 jar 文件足够小,则我们可以根据它们的扩展名(.gif、.class 等等)预先构建全部资源。

  • 某些方法应该提供关于给定 jar 文件本身(基本上是 zipfile 的包装)的信息,包括:jar/zip 的条目数;返回全部资源名的 enumerator;返回特定条目长度(和其他属性)的读方法;允许编制索引的读方法,这仅仅是举几个例子。

  • 可对 jarresources 进行扩展,以供 applet 使用。通过利用 applet 参数和 urlconnection 类,就可以从网络上下载 jar 内容,而不是将档案作为本地文件打开。此外,我们还可将该类扩展为一个自定义的 java 内容处理程序。

小结
如果您曾经渴望知道如何从 jar 文件中提取图像,那么您现在已学到了一种方法。有了本技巧提供的这个新类,您就不仅可以用 jar 文件处理图像,而且可以将提取魔术用于 jar 文件中的任何资源。

作者简介
arthur choi 目前是 ibm 的一位顾问程序员。他曾先后在几个公司任职,包括 samsung network laboratory 和 mitre。他参与过的项目包括客户机/服务器系统、分布式对象计算和网络管理。他在各种操作系统环境下用过多种语言。他于 1981 年开始用 fortran iv 和 cobol 进行编程。后来他转向 c 和 c++,最近两年他一直在用 java 工作。他最感兴趣的 java 应用是广域网中的数据仓库和因特网上的并行处理和分布式处理(使用基于代理的编程)。reach arthur 的电子邮件地址为 arthur.choi@javaworld.com。

john mitchell,先后做过雇员、咨询人员,现在是自己公司的老板,过去十年他所投资的领域包括前沿计算机软件的开发、对其他开发人员提供建议和培训。他的咨询范围包括 java 技术、编译器、解释器、基于 web 应用和因特网商务等。john 是 making sense of java: a guide for managers and the rest of us 一书的作者之一,并在编程杂志上发表了许多文章。除了为 javaworld 撰写 java tips 专栏之外,他还主持着 comp.lang.tcl.announce 和 comp.binaries.geos 新闻组。reach john 的电子邮件地址为 john.mitchell@javaworld.com。

参考资源

  • 这是类文件 jarresources.java
    jarresources.java
  • jars
    http://www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • 有关 java 的归档支持的详细信息,请参阅 "java tip 21: use archive files to speed up applet loading"
    http://www.javaworld.com/javatips/jw-javatip21.html


<淘宝热门商品:

小小豆叮

Java中使用DirectDraw

java中使用directdraw

注释:directdraw®是微软directx® sdk的一个组成部分。java版的directx包含在java 2.0 sdk中。java中通过同directx一起安装的com.ms.directx包中的一套类访问directdraw。

介绍

本文将探讨用于java的directdraw sdk的一些优点、结构和使用。过去,使用动画的程序需要用c++编写(或者汇编语言),原因是动画需要很快的处理速度。动画是通过快速连续地显示一系列画面(或者叫做帧)实现的。为了使用户观看动画时没有闪烁感,至少需要达到每秒12帧的速率。更高的帧速率会产生更平滑的动画:例如,动画片的帧速率通常为每秒24帧。要达到最低的每秒12帧要求,在640´480,256色模式下每秒需要处理3.6m字节的图象数据。处理如此数量的视频数据是非常困难的。directdraw现在为java开发人员提供了这种视频数据处理能力。

开始使用directdraw api需要一些基本步骤。现将其列举如下,并且将会在后面的部分中解释:

  1. 创建directdraw对象。
  2. 设置协作级别。
  3. 创建需要的表面。
  4. 装入需要的位图。
  5. 显示表面。

directdraw对象

要在java中使用directdraw,必须先创建directdraw对象:

        dd = new directdraw();

一旦创建了directdraw对象,就需要设置协作级别。

协作级别

必须要设置directdraw在最高层窗口上拥有的控制级别。在最简单的级别上,directdraw的功能同其他程序相同,限制在windows® 95或者windows nt®窗口内。这是directdraw的正常级别操作。正常协作级别可以通过下面的语句设置:

dd.setcooperativelevel(hwnd, ddscl_normal);

注意   为了使程序能够利用更高级的directdraw特性,如改变显示模式或者修改directdraw的表面的行为,需要使用独占模式。然而,使用高级特性超出了本文的范围。要得到关于使用高级特性的更多信息,请参考directx文档。

创建表面

directdraw使用术语表面(surface)代表显示内容。表面既可以放在显示内存中,也可以放在系统内存中。然而,如果显示硬件没有足够的内存存放表面,directdraw会在系统内存中模拟表面。directdraw表面的最大优点是它总是以线性内存区域的形式提供给开发者。即使程序设置的显示模式不是线性的,表面为开发者提供的仍然是线性内存区域。考虑下面的例子,modex中显示内存是以一系列位面(plane)配置的(图1)。为了画一个点,必须防卫适当的内存位面以及正确的地址。directdrawsurface对象处理了所有这些细节。

图 1. mode x中的显示内存组织。

一个directdraw表面可以包含多个内存缓冲区,允许构建可以切换的表面。切换表面使程序可以利用双缓冲技术的优点。在双缓冲方法中,程序在后台缓冲区中绘制一些内容,画完后,快速地将后台缓冲区切换或者复制到前台缓冲区,使该画面显示出来。双缓冲方法速度非常快,尤其是当前台和后台缓冲区都在显示内存中时。此时,切换操作甚至不消耗任何cpu时间。

基于directdraw程序的用户看到的总是原始表面(primary surface)。为了改变用户看到的内容,可以简单地改变原始表面的内容。通常,需要创建一个或多个后台表面,这些表面中包含不同时间显示的画面。图2说明了一个复杂的双缓冲原始表面。该原始表面由一个后台缓冲区、一个前台缓冲区和四个后台表面组成。每个后台表面包含一个不同旋转阶段的位图。要使圆柱体动起来,程序将每个位图从后台表面中复制到原始表面的后台缓冲区中的一个位置。每当每个圆柱体的复制完成时,程序将后台缓冲区切换到前台缓冲区。

图2. 双缓冲表面之间的关系

directdraw在java中的实现包括两个为表面工作而特别设计的类。ddsurfacedesc类用来描述所创建表面的属性。directdrawsurface类包含为directdraw表面工作所做的定义、方法和变量。

要创建directdraw表面,不管是原始表面还是后台表面,必须先创建ddsurfacedesc对象,设置表面属性,并且把表面描述结构传递给directdraw对象的createsurface()方法。下面的语句创建了一个由一个缓冲区组成的原始表面:

// create a primary surface containing a single buffer.

ddsd = new ddsurfacedesc();

ddsd.flags = ddsd_caps ;

ddsd.ddscaps = ddscaps_primarysurface;

pdds = dd.createsurface( ddsd );

下面的语句创建了一个双缓冲原始表面:

//create a primary surface containing a back //buffer for double buffering.

ddsd = new ddsurfacedesc();

ddsd.flags = ddsd_caps | ddsd_backbuffercount;

ddsd.ddscaps = ddscaps_primarysurface | ddscpas_flip | ddscaps_complex;

ddsd. backbuffercount = 1;

pdds = dd.createsurface( ddsd );

下面的语句说明了如何创建一个320象素宽200行高的后台表面:

ddsd = new ddsurfacedesc();

ddsd.flags = ddsd_caps | ddsd_height | ddsd_width;

ddsd.ddscaps = ddscaps_offscreenplain;

ddsd.width = 320;

ddsd.height = 200;

pdds = dd.createsurface( ddsd );

将位图装入到directdraw表面中

位图是程序可以用来显示图形内容的图片。图2中的四个圆柱体每一个都是一张位图。java中的directdraw为操作位图文件提供了directdrawbitmap类。directdrawbitmap对象创建后,可以复制到directdraw表面。下面的语句将一个叫作frntback.bmp的位图文件读入到directdraw表面:

//read the bitmap file.

bm =  new directdrawbitmap();

bm.filename(“frntback.bmp”);

bm.initwidth(dx);

bm.initheight(dy);

if( bm.loaded() != 0 )

{

    // create a directdrawsurface for

    // this bitmap.

    ddsd = new ddsurfacedesc();

    ddsd.flags = ddsd_caps |

    ddsd_height | ddsd_width;

    ddsd.ddscaps = ddscaps_offscreenplain;

    ddsd.width = bm.width();

    ddsd.height = bm.height();

    pdds = dd.createsurface( ddsd );

    pdds.copybitmap(bm, 0, 0, 0, 0);

}

//off-screen surface pdds now contains the

//bitmap data.

显示表面

当所有表面都创建并初始化(例如将位图复制到表面中)以后,程序需要显示它们时就可以将它们复制到原始表面。这种表面复制通过directdrawsurface对象的blt方法完成。在缺省的操作模式下,如果切换程序忙(正在进行切换),dds.blt()方法立即返回一个错误码。因此,应该以某种循环的形式使用dds.blt()方法,或者指定dds.blt()方法的ddblt_wait标志。第二个选项改变了dds.blt()的行为,使得此方法等待,直到切换可以进行或者出现另一个错误。

下面的代码说明了如何使用directdrawsurface的blt方法。首先,有两点需要阐明。如果显示卡的模式改变或者程序使用对显示卡的独占访问而释放了当前在显卡上分配的所有表面内存,directdrawsurface就会丢失。当表面丢失时,需要恢复。恢复可以通过两个步骤完成。首先调用directdrawsurface对象的restore方法重新分配表面内存以及重新添加directdrawsurface对象。然后,重建相关表面的内容。

rc.left   = 0;

rc.top    = 0;

rc.right  = bm.width();

rc.bottom = bm.height();

// show the off-screen surface on the

//primary surface.

done = 0;

do

{

   int retval;

   retval = ddsprimary.blt( rc, ddsone, rc, 0);

   if( retval == dd_ok )

    {

        //if the bitmap has been successfully

        //copied, exit loop.

        done = 1;

    }

    else if ( retval == dderr_surfacelost )

    {

        while( ddsprimary.restore() != dd_ok &&

            ddsone.restore() != dd_ok )

        {

            reloadbitmap(ddsone, szbitmap);

        }

    }

    else if( retval != dderr_wasstilldrawing)

    {

        // undetermined error; quit the loop.

        done = 1;

    }

} while( done == 0);

其他信息

本文提供了初始化和使用java中directdraw sdk的背景和基本步骤。要获得java的directx sdk以及相关文档,可以从http://www.microsoft.com/java/下载microsoft sdk for java 2.0(其中包含directx sdk)。其中还包括几个示例程序,对于使用directx for java创建动画非常有用。这些例子列举如下:

示例

目录

示例内容

ddex3

ddraw\ddex3\ddraw.html

directdraw的基本使用

flipcube

d3d\flipcube\d3d.html

3d立即模式的基本使用

viewer

d3drm\viewer\direct3drm.html

direct3d保持模式的完整使用

castle

d3drm\castle\castle.html

direct3d保持模式的高性能

directinput

dinput\ddex3\dinput.html

操纵杆、鼠标、键盘和游戏键盘的使用

 



<淘宝热门商品:

小小豆叮

在 Linux 上安装Apache+ApacheJServ+JSP

在 Linux 上安装Apache+ApacheJServ+JSP 安装软件的顺序如下: I. 安装 Apache Web Server a. 使用 RPM 如果使用 RPM 套件,在取得 Apache Web Server 套件之后,只需要输入以下命令即可完成安装: [root@localhost root]# rpm -ivh apache-1.3.xx.i386.rpm ( xx 代表 Apache Web Server 版本 ) b. 使用 SOURCE 如果使用的是 Apache Web Server 的 Source,那么必需对 Source 进行编译并且加以安装: [root@localhost root]# gunzip apache_1.3.xx.tar.gz ( xx 代表 Apache Web Server 版本 ) [root@localhost root]# tar zxvf apache_1.3.xx.tar ( xx 代表 Apache Web Server 版本 ) [root@localhost root]# cd apache_1.3.xx [root@localhost apache_1.3.xx]# ./congifure \ > --prefix=/usr/local/apache/ \ ( 设定所想要安装的目录是/usr/local/apache/ ) > --enable-module=all \ > --enable-rule=SHARE_CORE [root@localhost apache_1.3.xx]# make clean ; make ; make install 完成了以上步骤之后,基本上己经完成了 Apache Web Server 的安装。 II. 安装 JDK ( Java Development Kits ) 依照下列步骤来完成 JDK 的完装: [root@localhost root]# gunzip jdk1_2_2rc2-linux-i386.tar.gz [root@localhost root]# tar zxvf jdk1_2_2rc2-linux-i386.tar [root@localhost root]# mv jdk1.2.2 /usr/local/jdk122 完成上述步骤后,还需要进行环境设定: [root@localhost root]# vi .bash_profile ... ... JAVA_HOME=/usr/local/jdk122 PATH=$PATH:$JAVA_HOME/bin CLASSPATH=/usr/local/jdk122/lib/tools.jar:. export JAVA_HOME export PATH CLASSPATH ★请注意:如果使用的是 JDK 1.1.x 版本,你的 CLASSPATH 必须设定如下: CLASSPATH=/path/to/your/jdk/lib/classes.zip:. III. 安装 JSDK ★请注意:如果使用的是 Java Apache RPM 版本,请跳过此节。 必须先取得并安装 JSDK ( Java Servlet Development Kits ),才能使 Java Apache 进行运作。但事实上,我们所需要的,只是 JSDK 中的一小部份 ( 一个叫 jsdk.jar 或是 servlet.jar 的档案 );现在所要做的,就是取得这个档案,并且将这个档案设定到 CLASSPATH 中: CLASSPATH=/path/to/jsdk/lib/jsdk.jar:$CLASSPATH export CLASSPATH IV. 安装 Java Apache . 使用 RPM 如果你是使用 RPM 套件,在你取得 Java Apache 套件之后,只需要输入以下命令即可完成安装: [root@localhost root]# rpm -ivh ApacheJServ-1.1-b2.i386.rpm a. 使用 SOURCE 如果你使用的是 Java Apache 的 Source,那么你必需对 Source 进行编译并且加以安装: [root@localhost root]# tar zxvf ApacheJServ-1.1.tar.gz [root@localhost root]# cd ApacheJserv-1.1 [root@localhost ApacheJserv-1.1]# ./congifure \ > --prefix=/usr/local/jsdk/ \ ( 设定你所想要安装的目录 ) > --with-apxs=/usr/local/apache/bin/apxs \( apache apxs 所在完整路径 ) > --with-jdk-home=$JAVA_HOME \ > --with-java-platform=2 \ ( 设定你所使用的 JDK 版本;1 代表 JDK 1.1.x;2 代表 JDK 1.2.x ) > --with-JSDK=/usr/local/jsdk/lib/jsdk.jar [root@localhost ApacheJserv-1.1]# make clean ; make ; make install ★请注意:请先往下阅读【Java Apach 测试】一节。 V. 安装 GNU JSP 在取得 GNU JSP 之后,请依照下列步骤进行安装: [root@localhost root]# gunzip gnujsp_0_9_10.tar.gz [root@localhost root]# tar zxvf gnujsp_0_9_10.tar [root@localhost root]# mv gnujsp-0.9.10 /usr/local/gnujsp [root@localhost root]# cd /home/httpd/servlets [root@localhost servlets]# mkdir compiled [root@localhost servlets]# chown nobody.nobody compiled 完成上述指令之后,我们还须要对几个档案进行设定: 1. /etc/httpd/conf/jserv/jserv.properties [root@localhost root]# cd /etc/httpd/conf/jserv [root@localhost jserv]# vi jserv.properties ... ... wrapper.classpath=/usr/local/gnujsp/lib/gnujsp.jar ... ... 2. /etc/httpd/conf/jserv/zone.properties [root@localhost jserv]# vi zone.properties ... ... repositories=/home/httpd/servlet,/usr/local/gnujsp/gnujsp.jar ... ... servlet.gnujsp.code=org.gjt.jsp.JSPServlet ... ... servlet.gnujsp.initArgs=repository=/home/httpd/servlets/ servlet.gnujsp.initArgs=compiler=/usr/local/jdk122/bin/java \ -classpath %classpath%:%repository% \ -d %repository% -deprecation %source% ... ... 3. /etc/httpd/conf/jserv/jserv.conf 附录 在 Linux 上安装Apache+ApacheJServ+JSP所需要的软件   I. Apache Web Server o http://www.apache.org/ o http://www.redhat.com/ o http://cle.linux.org.tw/ II. JDK o http://java.sun.com/ III. JSDK o http://java.sun.com/ IV. Java Apache o http://java.apache.org/ V. GUN JSP o http://www.gnu.org/ o http://java.apache.org/ <淘宝热门商品:

小小豆叮

利用UDP Sockets技术实现IP多点传送

杨绍方 摘 要 本文介绍了UDP Sockets的基本概念和IP多点传送的原理,详细讨论了Java中的相关类及使用方法,提供了一个IP多点传送的开发流程。 关键词 Java UDP Sockets    IP 多点传送 MulticastSocket 类IP多点传送(multicast delivery)是针对点到点的传送和广播传送两种方式而言的,它是指在一定的组内对其成员进行的广播,是一种有限的广播。组中的某个成员发出的信息,组中的其它所有成员都能收到。它是UDP Sockets的一个分支。   IP多点传送特别适合与高带宽的应用,例如在网络上发送视频和音频。随着网络带宽的不断提高和网络通讯质量的不断改善,IP多点传送还将广泛地被应用于网上聊天及网上会议,分布式数据存储,联机事务处理,交互式游戏等方面。另外,多点传送还可以被客户机用于在网络上寻找相应的服务器,客户机发送一个多点传送的请求,任何监听服务器都可以与客户机连接并开始一个事务。 UDP Socket基础   使用用户数据报协议(User Datagram Protocol,简称UDP)进行会话必须将信息装配成一定尺寸的小报文,当发送一条信息,接收方能否收到并返回信息永远是不确定的,如果无法收到返回信息,我们就无法确定我们发送的信息是否被接收——它可能在途中丢失,接收者返回的响应信息也可能丢失,另外,接收者也可能忽略我们的信息,因此,UDP被描述为不可靠的、无连接的和面向消息的。   创建UDP sockets非常象创建一个邮箱。邮箱是使用地址来识别的,但是,我们不需要为每个发送信息的人构造一个新的邮箱,可以在含有发送信息的明信片上写上目的地址,将其放在邮箱中并发送出去。接收者可能会长久的等待,直到含有信息的明信片到达它的邮箱,而明信片上标识了发送者的返回地址。 IP多点传送的原理   为了支持IP多点传送,某些范围的IP地址被单独留出专门用于这个目的,这些IP地址是D类地址,其地址的最高四比特的位模式为“1110”,即IP地址的范围在224.0.0.0和239.255.255.255之间。它们中的每一个IP地址都可以被引用作为一个多点传送组,任何以该IP地址编址的IP报文将被该组中的其它所有机器接收,也就是说,一个IP地址就相当于一个邮箱。另外,组中的成员是动态的并随时间而改变。   对于IP多点传送,网间网组管理协议(Internet Group Management Protocol,简称IGMP),用于管理多点传送组中的成员。支持多点传送的路由可以使用IGMP决定本地的机器是否赞成加入某个组,一个多点传送路由可以决定是否转发一个多点传送报文。   影响多点传送报文的一个重要参数是time-to-live(TTL)。TTL用于描述发送者希望传送的信息能通过多少不同的网络。当报文被路由器转发,报文中的TTL将减一,当TTL为零时,报文将不再向前发送。   在实际使用中,我们必须注意下面几点:   1.这些IP地址只能作为信宿地址使用,绝对不能出现在任何信源地址域中,也不能出现在源路径或记录路径选项中:   2.由于IP多点传送是一对多的传送,因此,不能利用差错与控制报文协议(Internet Control Message Protocol,简称ICMP)产生出错报文。   3.发送一个信息到一个组,发送主机可以不是组中的成员;   4.一些组被Internet Assigned Numbers Authority(IANA)分配,保留用于特殊的目的,详情参见:ftp://ftp.internic.net/rfc/rfc1700.txt。另外,避免使用一些保留组,从224.0.0.0到224.0.0.225仅限于本地子网使用。建议在224.0.1.27和224.0.1.225之间任意选取一个IP地址。   5.如果我们选取的组已经被使用,与其他机器的通讯将会混乱,一旦发生,可以退出应用,试试其他的地址。   6.当一个机器加入一个多点传送组,它将开始接收该IP多点传送地址的信息。如果多点传送报文分发到网络上,任何监听该信息的机器都会有机会接收它。对于IP多点传送,没有一个机制对相同网络上的机器能否加入该多点传送组加以限制。因此,安全性是我们必须考虑的问题之一。   7.选择的TTL参数应尽可能小。一个大的TTL值会不必要地占用Internet带宽。此外,还可能破坏不同区域使用相同组的其它的多点传送通讯。 Java中与IP多点传送相关的类   java.net包中含有UDP通讯所需要的工具,其中包括IP多点传送。 DatagramPacket类   我们可以使用DatagramPacket类创建一个用于发送的数据报,而当接收UDP数据报时,可以使用DatagramPacket类读取数据报中的数据,发送者及其它信息。   为了创建一个数据报并发送到远地系统,可以使用下面的构造器:   Public DatagramPacket(byte ibuf,int length,InetAddress iaddr,int iport,);   ibuf是编码信息数据的字节数组,它的长度length就是数据报放在其中的字节数组的长度,iaddr是一个InetAddress对象,存储着接收方的主机名和IP地址等信息,iport标识数据报发送到接收主机的端口。   为了接收数据报,必须使用DatagramPacket构造器,其原型为:public DatagramPacket(byte ibuf,int ilength);ibuf是指接收的数据报的数据部分, ilength是该部分数据的长度。如果 ilength 小于机器接收的UDP数据报的尺寸,多余的字节将被Java忽略。   另外,类中有一些方法(method)可以让我们得到一些相关的信息:   public int getLength(); //得到数据报中数据块的字节尺寸   public bytegetData();//得到接收数据报中的数据   public InetAddress getAddress(); //为发送者提供一个 InetAddress对象   public int getPort(); //得到UDP端口   值得注意的是,TCP sockets的编程中,我们无须将传送的数据分块,然而,当我们创建一个基于UDP的网络通讯应用程序时,必须创建一套方法,在运行时刻决定需分割的数据报的长度。对于TCP/IP,最大的数据报可以含有65507字节的数据,然而,主机仅能接收最多548字节的数据,支持8192字节的大数据报的平台是利用IP层对数据报进行分割的。如果在传送期间,任何含有IP报文的一个数据块丢失,都会造成整个UDP数据报的丢失,因此,我们在确定应用中数据报尺寸时,对其尺寸的合理性一定要谨慎。   下面就是分割数据的一个例子:   //循环地从输入流input中读一行数据   while((nextLine=input.readLine())!=null){   //定义一个空数据报,其尺寸为512   mcastBuffer=new byte[512];   //如果读入的数据的长度大于定义的数据报的长度,   //则使用定义的长度,否则使用读入数据的长度   if(nextLine.length()>mcastBuffer.length){   sendLength=mcastBuffer.length;   }else {   sendLenth=nextLine.length();   }   //将读入的数据转换为byte类型   lineData=nextLine.getBytes();   //将数据复制到用于创建数据报的byte数组   for(int i=0;i

小小豆叮