<%-- studentedit.jsp --%>
<jsp:useBean id="table" scope="page" class="manger.bean.EditStudentBean" />
<%table.processRequest(pageContext);%>
<p> </p>
<form name="EditForm" action="editstudent.jsp">
<INPUT TYPE="hidden" NAME="event" VALUE="<%=table.getEvent()%>" >
<table width="75%" border="1">
<tr>
<td colspan="2">
<div align="center"><b>编辑学生信息</b><淘宝热门商品:
来源:程序员网
一些嵌入式设备开发者认为Java技术在应用中就其功能来说是不完善的:太慢、太不可预测或是太大。这里有一些可供选择的方法可实现Java技术,并能有效地解决这些问题。
据Sun Microsystems公司估计,现在已有70多万个开发者在使用Java技术。尽管Java平台在公司或企业应用中已有许多成功的事例,但对其在嵌入式设备开发中的应用话还鲜有公开的论述。为了更客观地认清当前的情形,让我们从两个方面对Java技术做一评述:规范和实现。现有的Java平台“规范”并没有问题,但是现有的很多“实现”(特别是针对PersonalJava和EmbeddedJava)对于大多数嵌入式设备并不可行。
适于Internet的Java
Java平台于1995年面市,作为一种编程语言和运行环境,它特别适用于与Internet相关的应用。Sun Microsystems倡导“网络就是计算机”,他们已经意识到强大的微处理器正逐渐应用于许多消费类和嵌入式设备,这些设备会越来越多的与网络相连。网络连接从工作站和PC开始,随后迅速波及打印机、扫描仪、复印机及其它办公设备。最近,个人数字助理、机顶盒、双向寻呼机、智能电话,甚至数字手表等带有微处理器的新式设备也连到了数字网络。在Java之前,网络基本被视为储存和提供相对静态的信息的大型系统,也许用“网络就是虚拟磁盘驱动器”来描述可能更贴切一些。现在,Java技术为联网的计算设备提供了一种有效的方法,用于存储和分布动态和可扩展的功能性,从而扩展了网络的实用性。
Java结构包含有几个截然不同但又相互关联的技术,其中每一个在Sun的规范中都有详细说明。这些技术包括Java编程语言、Java虚拟机(JVM)和Java API(见图1)。下面我们将集中在JVM及一些实现方面的问题,这些问题可能会影响Java技术对嵌入式应用的适用性。

图1:Java体系包括若干个截然不同但又相互关联的技术。
跟所有的虚拟机器一样,JVM也定义了一个抽象的计算机。其规范定义了每一个JVM必须具有的功能。但是对于每一种应用的设计者,它都会给予几乎无限制的自由。例如,每一个JVM都可以使用任何技术去执行Java字节代码。事实上,JVM可以软件或硬件的形式实现,或两者不同程度的混合。这种灵活性意在使JVM可在各种计算机和嵌入式设备上实现。
在最上层,JVM的主要目的是装载Java类文件并执行它们(见图2)。在执行期间,JVM实现在两个方面会影响Java技术对特定应用的适用性:用于执行字节代码的方法;系统资源(主要是内存)管理。

图2:Java虚拟机的组成和功能。
JVM执行字节代码的缺省方式是解释性执行。鉴于C/C++应用程序是被编译成自然指令集并存储在单个可执行文件里的,Java应用程序便被编译成Java字节代码且存储在由JVM装载和执行的单独的类文件里。当Java应用程序运行时,JVM便载入类文件并将字节代码作为指令流加以解释。
一般地,当JVM使用纯解释方法执行时,性能将会比同等的自然编译的C/C++程序慢10到20倍。然而,有其它方法能够提高字节代码的执行速度。例如,just-in-time(JIT)编译方法就能比纯解释执行方法将应用程序性能提高达十倍。不仅仅只解释字节代码,每当JVM第一次遇到新的字节代码时,它就调用JIT编译器将那个代码编译成自然指令。随后这些自然指令由JVM保存,在下一次Java应用程序需要时可再次调用。然而,性能的提高是有代价的。JVM纯解释版本的主要优点之一是它只占用较小的内存量——典型的实现以所包含的库不同,需要0.5至3MB的ROM。而JIT编译技术一般情况下需要四倍于纯解释方法的内存量。此外,它须编译所遇到的所有代码,这需要极大数量的内存,而且经常需要磁盘和虚拟内存对编译的代码段进行分页。因此,基于JIT的执行适用于拥有强大CPU、足够系统内存(大于32MB)的计算平台,而且还要有可支持插拔的快速磁盘驱动器。但是,对于通常有更多资源限制的大多数嵌入式设备,它却不太适用。
动态编译与JIT
一种更适用于嵌入式设备的字节代码执行方法是自适应动态编译。与JIT相似,自适应动态编译利用快速的编译技术来提高解释性字节代码的执行性能。然而,与JIT不同的是,自适应动态编译器通常更小一些(大约为100KB);有更多的Java字节代码选择以便编译成自然代码;不需要虚拟内存;与可用的系统内存匹配。在字节代码的解释执行期间,JVM将监控应用程序的运行并测定出运行瓶颈在哪里。然后,它会调用自适应动态编译器(以一个线程来实现)以编译那些执行最为频繁的字节代码段。根据实现方法的不同,自适应动态编译可能编译整个类、单个方法或仅仅是某一方法内的一个模块。为了快速存取,所得到的自然指令将存储在RAM中。随后,JVM会找到下一个执行最频繁的代码段并对其编译。这一过程一直重复,直到所有可用的代码缓冲区用完。因为动态编译器是自适应的,当它遇到一个比先前编译并存储的代码执行更为频繁的新代码段时,它就会编译这些新的Java字节代码并把它们存储在容纳较低使用频率代码的缓冲区内。用户可以配置用于编译的系统内存容量,以及用于存储已编译自然指令的代码缓冲区的大小和数量。在有更高可预测性的执行期间,应用程序也可通过自适应动态编译器的线程优先级,而得到可靠的控制,从而为嵌入式设备提供更合适的特性(见图3)。

图3:自适应动态编译器与JIT和解释性方案的内存占用量及相关性能之对比。
可靠性和可预测性问题
内存的有效管理对于嵌入式设备特别关键,因为它们需要更多可预测的行为。JVM在管理内存方面扮演着重要的角色。事实上,应用程序本身仅仅为新对象发出内存分配请求,并不明确地释放不必要的内存。JVM可自动地管理内存的释放。每一个JVM必须执行“垃圾收集器”功能以提供内存管理的便利。有几种不同的“垃圾收集器”实现方法,其中有一些比其它的更适用于嵌入式系统(见图4)。

图4:垃圾收集的不同实现。
例如,一个可运行完整的批循环且不能被抢占的“垃圾收集器”将导致Java技术对大多数嵌入式设备都不适用,因为它的行为太不可预测。而一个递增的“垃圾收集器”能够以步进的方式回收内存,而不是从单一的途径收集所有的无用内存。这种实现方法可能会导致比分批垃圾收集更加不可预测的行为。尽管如此,如果不能被抢占,递增的“垃圾收集器”可能会堵塞应用程序(尽管时间很短)。一种“并发”的“垃圾收集器”可递增地执行垃圾收集且能够被完全抢占,它将能提供比所有其它类型更可预测的特性。
除了其执行模式外(分批、递增或并发),“垃圾收集器”还能以不同程度的效能和效率执行它们的任务。要把有效的对象从垃圾中分离出来有两种基本方法:“参考计数”和“跟踪”。参考计数是一种较老的垃圾收集技术,而且要为堆栈中的每个对象保留一个参考计数。实质上,对给定对象的每一个新参考,参考计数是递增的;当某一对象的参考超出界限时,参考计数是递减的。所有带一个零参考计数的对象都能被垃圾收集。然而,在其它的缺点之中,由于参考计数不能承受在每次对象被参考时递增和递减参考计数的系统开销,使它基本上无法适用于嵌入式设备。
精确与保守
更适合JVM的方法是跟踪垃圾收集技术。跟踪垃圾收集从根节点开始跟踪对象参考树。在跟踪期间遇到的参考对象被标记出来,跟踪完成后未做标记的对象就可以被垃圾收集。在跟踪过程中,“垃圾收集器”既可使用“精确”策略也可以使用“保守”策略来识别对象的参考。保守的垃圾收集器可能辩别真正的对象参考和相似或克隆的对象参考(例如对象指针对应32位整数)。尽管这种方法可能快一些,但是它也可能导致内存溢出。另一方面,精确的垃圾收集器可以辨别真正的和相似的对象参考之间的区别,并且适当释放所有未参考的对象。垃圾收集最后一个需要考虑的重要方面就是能否处理好堆栈分段存储。考虑到大多数嵌入式设备的有限内存量,一个并发、精确和紧凑的垃圾收集策略应该可以处理大多数可预知的系统行为。
附栏
嵌入式设备的Java兼容环境
Jeode平台是专为嵌入式设备设计的,是Sun公司EmbeddedJava和PersonalJava规范的一个快速实现,由Insignia独立开发。它通过了Sun的EmbeddedJava技术和PersonalJava平台兼容性测试,获得了“Sun认可虚拟机(Sun Authorized Virtual Machine)”的殊荣。它采用“自适应动态编译”技术,所需内存量只有JIT技术的四分之一。此外,由一家独立咨询公司进行的测试宣称其平均速度要比纯解释性JVM快6倍。Jeode使用了“精确并发”的垃圾收集技术,可作为优先抢占的线程运行,并具有内存压缩功能以清除内存碎片。使用Jeode平台,开发者将得到全功能的、完全与Java兼容的虚拟机技术,可针对其特殊的嵌入式应用进行配置和调整。Jeode平台既可在小至358K的内存中运行,也可在大到完全配置的2.7MB ROM中运行。它包括仅支持英语的所有Java类库和所需动态链接库。带所有Java类库的完整国际语言支持需要大约5MB ROM。该平台可在多种操作系统和目标处理器上运行,现可支持Windows CE和NT、VxWorks和Linux,所支持的处理器有MIPS、ARM、Intel x86、PowerPC和Hitachi SH。
欲了解更多信息,请联系作者:E-mail:jeode@insignia.com
<淘宝热门商品:
来源: 程序员网
WebSphere Application Server作为e-Business应用的核心,提供了基于Java Servlet技术的引擎,它把基本的HTTP Server扩充成为基于Java的应用服务器,提供了比CGI技术更优的性能。本文旨在对Java Servlet技术作一般性的介绍,并与传统的CGI技术进行比较。
Servlet是用Java编写的Server端程序,它与协议和平台无关。Servlet运行于Java-enabled Web Server中。Java Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务。
最早支持Servlet技术的是JavaSoft的Java Web Server。此后,一些其它的基于Java的Web Server开始支持标准的Servlet API。Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。这个过程为:
·客户端发送请求至服务器端;
·服务器将请求信息发送至Servlet;
·Servlet生成响应内容并将其传给Server。响应内容动态生成,通常取决于客户端的请求;
·服务器将响应返回给客户端。
Servlet看起来像是通常的Java程序。Servlet导入特定的属于Java Servlet API的包。因为是对象字节码,可动态地从网络加载,可以说Servlet对Server就如同Applet对Client一样,但是,由于Servlet运行于Server中,它们并不需要一个图形用户界面。从这个角度讲,Servlet也被称为Faceless Object。
Servlet的优势
Java Servlet提供了许多优势:
·Servlet可以和其他资源(文件、数据库、Applet、Java应用程序等)交互,以生成返回给客户端的响应内容。如果需要,还可以保存请求-响应过程中的信息。
·采用Servlet,服务器可以完全授权对本地资源的访问(如数据库),并且Servlet自身将会控制外部用户的访问数量及访问性质。
·Servlet可以是其它服务的客户端程序,例如,它们可以用于分布式的应用系统中。
·可以从本地硬盘,或者通过网络从远端硬盘激活Servlet。
·Servlet可被链接(chain)。一个Servlet可以调用另一个或一系列Servlet,即成为它的客户端。
·采用Servlet Tag技术,可以在HTML页面中动态调用Servlet。
·Servlet API与协议无关。它并不对传递它的协议有任何假设。
·像所有的Java程序一样,Servlet拥有面向对象Java语言的所有优势。
Servlet与CGI-BIN
概括来讲,Servlet可以完成和CGI相同的功能。
CGI应用开发比较困难,因为它要求程序员有处理参数传递的知识,这不是一种通用的技能。CGI不可移植,为某一特定平台编写的CGI应用只能运行于这一环境中。每一个CGI应用存在于一个由客户端请求激活的进程中,并且在请求被服务后被卸载。这种模式将引起很高的内存、CPU开销,而且在同一进程中不能服务多个客户。
Servlet提供了Java应用程序的所有优势——可移植、稳健、易开发。使用Servlet Tag技术,Servlet能够生成嵌于静态HTML页面中的动态内容。
Servlet对CGI的最主要优势在于一个Servlet被客户端发送的第一个请求激活,然后它将继续运行于后台,等待以后的请求。每个请求将生成一个新的线程,而不是一个完整的进程。多个客户能够在同一个进程中同时得到服务。一般来说,Servlet进程只是在Web Server卸载时被卸载。(见图1)
图1 Servlet运行模式
图2 Servlet生命周期
Servlet生命周期
Servlet的生命周期(见图2)可以被归纳为以下几点:
·装载Servlet。这项操作一般是动态执行的。然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet(1);
·Server创建一个Servlet的实例(2);
·Server调用Servlet的init()方法(3);
·一个客户端的请求到达Server(1);
·Server创建一个请求对象(4);
·Server创建一个响应对象(5);
·Server激活Servlet的service()方法(6),传递请求(7)和响应(8)对象作为参数;
·service()方法获得关于请求对象的信息,处理请求,访问其他资源(9),获得需要的信息(10);
·service()方法使用响应对象的方法,将响应传回Server(11)、(12),最终到达客户端(13)。service()方法可能激活其它方法以处理请求,如doGet()或doPost()或程序员自己开发的新的方法;
·对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。一般Servlet只初始化一次;
·当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。
Servlet与CGI程序的比较
CGI(Common Gateway Interface)程序,主要用Perl、Shell Script或C编写,能够向客户端提供动态内容,即每次客户端浏览器访问某一页面时,可以看到不同的内容。这里对完成相同功能的CGI程序和Java Servlet程序作一比较,以便更清楚地看到Servlet的简单特性。
这里CGI和Servlet程序的功能均为获得客户端在浏览器表单中输入的参数(Firstname,Lastname),并将返回给客户端。相应的CGI程序和Servlet程序分别如下:
·CGI程序(Perl):
$query—string=$ENV{?QUERY—STRING?};
$query—string=As/%([dA-Fa-f][dA-Fa-f])/pack(″C″,hex()$1))/eg;$query—string=As/+//g;
@pairs=split(/&/,$query—string);
foreach $pair(@pairs) {
($key,$value)=split(/=/,$pair);
$form—data{$key}=$value;
}
$firstname=$form—data{″firstname″};
$lastname=$form—data{″lastname″};
print ″Hello,$firstname $lastname. Thank you for your visit! ″;
·Servlet程序:
public void service(HttpServletRequest request,HttpServletResponse response)
throws ServletExeption,IOExeption
{
ServletOutputStreamout=response.getOutputStream();
response.setContentType(″text/html″);
String firstname=request.getParameter(″firstname″);
String lastname=request.getParameter(″lastname″);
out.println(″Hello,″+firstname+″ ″+lastname+″.″);
out.println(″Thank you for your visit!″);
out.lose()
}
可以很明显地看到Java Servlet源代码比相应的CGI Perl Script简单许多。这里需要导入三个package:javax.servlet、javax.servlet.http和java.io。定义Servlet的类扩展了HttpServlet class,而不是GenericServlet class,因为此Servlet需要与HTML form进行交互。
在CGI程序中有很大一部分用于处理对参数的提取和解码过程,而在Servlet程序中,解码传递的参数部分并不需要额外编写。从HttpServlet class继承来的基本函数可以自动完成解码的过程。因此,程序员可以在Servlet service()方法中直接获取由客户端创建和编码的Key-value对。解码后的Key-value对可以直接从HttpServlet class的service()方法的第一个参数中获得。这将极大地减少程序员的劳动量和重复的代码劳动,并降低编码难度。
综上所述,Servlet在性能、编写难度、可移植性等方面比CGI有明显优势。在WebSphere Application Server中提供了功能强大的Servlet API,它们比JSDK拥有更多的功能和更优的性能,为Servlet的编程提供了很好的支持。随着WAS的日益推广和Java技术的普及,可以预见,Servlet技术将取代CGI,成为对Web Server功能扩充的标准技术。
<淘宝热门商品:
来源: 程序员网
Sun ONE 白皮书
(来源:http://www.sun.com.cn)
SunTM开放式网络环境
(Sun TM Open Net Environment)
(即Sun ONE)白皮书
SunTM开放式网络环境(Sun ONE)软件体系结构
1、介绍
互联网对用户的期望产生深远的影响。不久前,计算机用户是高度训练有素的个体,即公司把用户培训成了若干个特定应用领域的行家。但Web用户却完全不同,公司承受不了培训Web用户的负担。因此,Web应用必须凭直觉。更准确地讲,Web应用须是看不见的。Web用户只使用Web收发电子邮件、查找目录、支付帐单、审批支出请求等等,但不需要查看这些应用是如何执行的。用户只使用可从Web获得的服务。他们需要通过台式系统、PDA、移动电话和车载计算机等多种客户机设备,取得这些服务。更有甚者,用户希望这些服务能够理解各种背景情况,并对此作出不同的反应。譬如,我是身份是什么?我在什么地方?现在是什么时间?我是以一个雇员还是一个个体的身份给予反应?等等。
用户的上述新期望,促使公司改变了创建应用系统的方式。他们不再创建那种大而全的应用系统,转而着手采用面向服务的应用设计创建应用程序。应用软件被分割成规模较小、数量较多的模块化应用部件或服务,它们是应用软件的有机组成部分。这些应用服务使用的基础设施软件,也被分解成了独立的系统服务。所有这些独立的系统服务,都可以跨越连接互联网的任何数量的物理机器实现部署。此种模块化服务模式,在系统设计上为公司提供了巨大的灵活性。通过把少量的服务重新汇编成一种新配置,公司就可以创建新的商务服务。
2、服务
一种应用服务代表了某种类型的用户或商务活动,例如阅读电子邮件,接收股市报价、授权赊购业务和购物等。而系统服务代表系统基础设施和管理功能、例如存储、安全、交易、信息传递、故障克服等。
服务具有下列特点:
服务提供了一个可通过另一程序调用的接口。
服务可通过服务注册器进行注册和定位。
面向服务的系统并非是个新概念。面向服务的流行系统包括ONC RPC、DCE、COM、CORBA、RMI和Jini?技术。尽管所有这些系统都有许多可圈可点的优势,但它们均需要专用协议实现通信。COM客户机须使用COM协议,与COM服务执行通信,而Jini客户机须使用Jini协议与Jini服务实现交互。令人遗憾的是,这些专用协议在Web上不流行,而且防火墙往往又为通信设置了障碍。正是在这种背景条件下,一种面向服务的新型系统应运而生:即Web服务。
3、Web服务
一种Web服务代表商务、应用或系统功能的统一,可以通过Web接入。Web服务适用于任何类型的Web环境,无论是互联网、内联网还是外联网,重点是企业对消费者、企业对企业、部门对部门或同事对同事的通信。Web服务消费者可以是通过台式或无线浏览器接入服务的个人,也可以是应用程序,还可以是另一个Web服务。
Web服务具有下列特点:
Web服务可以通过Web接入;
Web服务提供一个XML接口;
Web服务通过Web服务注册器进行注册和定位;
Web服务使用XML信息,通过标准Web协议实现通信;
Web服务支持系统间的松散耦合连接。
恐怕Web服务最令人感兴趣的是,不管使用哪种技术创建它们都无关紧要。因为Web服务使用XML接口和XML信息,通过标准Web协议执行通信,而且所有的Web服务环境都具有互操作特性,至少在理论上是如此。
4、商家需求
自从1994年Web问世以来,商家就一直采用互联网密切他们与股东、员工、客户以及伙伴间的关系。他们使用互联网实现供应链自动化,改善商务过程的效益。电子商务再也不是未来的发展方向,而是成为了一种规范。如今,商家感兴趣的是Web服务的互联网计算模式,它预期可以实现更优异的跨行业集成,改进效率,密切客户关系。
但为使Web服务模式适合用户的胃口,商家必须能够利用现有应用资源,并把它们用于Web服务。商家需要工具和技术,以便减少转向此种新模式的成本、风险和复杂性。
5、Web服务技术
当前,已开始出现了一系列支持Web服务的技术,处于领先地位的技术包括UDDI、WSDL、SOAP和ebXML。虽然这些技术马上以支持产品的形式出现,但它们会很快日臻成熟的。
UDDI(Universal Description Discovery and Interoperability:通用描述发现与互操作)是一个由Accenture、Ariba、Commerce
One、康柏、Edifecs、富士、惠普、I2、IBM、英特尔、微软、Oracle、SAP、Sun和VeriSign等公司为首而成立的业界联盟组织,现在已有130多家公司加入。该组织旨在为UDDI
Business Registry通用Web商务目录,制定相关技术规范。截止发稿为止,UDDI V1技术规范已经出台,UDDI
Business Registry也正在执行beta测试。Ariba、IBM和微软联合运行UDDI Business Registry。IBM已通过其developerWorks
Open Source Zone,发布了适用于Java?技术开发工具箱的开放型源UDDI技术。
WSDL(Web Services Description Language:Web服务描述语言)是由Ariba、IBM和微软开发的技术,其宗旨是为描述Web服务制定的通用XML框架。迄今为止,IBM已通过其alphaWorks发布了
面向Java技术开发工具箱的WSDL技术。
SOAP(Simple Object Access Protocol:简单对象访问协议)是由DevelopMentor、IBM、Lotus、微软和Userland等公司开发的技术。SOAP提供了一种可扩展XML信息传递协议,并支持RPC编程模式。许多SOAP的执行方案已经面世,最受青睐的两个方案是Apache软件基金会的开放式源Java技术执行方案和微软在.NET
SDK的执行方案。尽管两个方案之间的互操作问题依然困挠着开发人员,但其性能还是相当稳定的。
惠普和微软已开发了SOAP的扩展型技术,名为SOAP Messages with Attachments。微软的BizTalk
Server 2000采用了SOAP Messages with Attachments,因此该项技术包含在一个支持性产品中。最近,W3C(World
Wide Web联盟)成立了一个XML协议工作组,目的是开发标准的的XML信息传递协议(XP)。SOAP开发人员已向W3C递交了SOAP技术规范,他们把该规范用作XP项目的一个起点。SOAP
Messages with Attachments也递交给了W3C。但W3C尚未向外界透露其工作进展的细节。
ebXML(电子商务XML)是由ebXML Initiative开发的一种B2B XML框架。ebXML Initiative是UN/CEFACT(联合国贸易促进与电子商务组织)和OASIS(结构化信息标准促进组织)执行的联合项目。ebXML成员包括来自2000多个公司、政府部门、科研团体、标准组织的代表和来自全球各地的个人。
ebXML是一种全面的B2B框架,通过共享基于Web的商务服务,实现企业协作。该框架支持B2B商务过程的定义与执行,B2B商务过程以商务服务交换的设计顺序来表示。该框架包括信息服务、协作伙伴协议、核心部件、商务过程方法、注册器与仓库等技术规范。2000年10月,执行了一个互操作方案的验证演示,参加的成员包括Ajuba
Solutions、Cisco、Extol、Fujitsu、IBM、IPNet、Netfish、NTT、Savvion、Sterling
Commerce、Sun、TIE、Viquity、WebMethods、XML Global和XML Solutions。ebXML技术规范预计2001年5月发表。
6、开发者面临的困境
尽管这些技术在迅速成熟,但新生的Web服务开发人员却在大量地使用他们自己的设备创建Web服务,缺乏有助于整合所有这些技术和标准的指导原则。开发人员可以使用对用户信息很敏感的XML编辑器,以人工方式定义Web服务接口,或者使用SOAP或WSDL工具箱生成一个接口。但是,开发人员将如何使新的Web服务接口与现行应用或服务相关联呢?他们将如何把大量的独立Web服务汇编成一种整合商务服务?看来,实现各厂商间的互操作仍然是一个挑战。分布式或异构Web服务要实现无缝汇编和集成,还是一个遥远的梦想。
7、共享用户信息
一个很重要的问题是需要共享用户信息。所谓的用户信息是指Web服务需要了解有关服务消费者的情况,以便提供定制化和个性化的服务。用户信息指消费者身份、地址,以及与消费者信息相关的隐私权限制。如要把许多服务汇编成一个整合型商务服务,这些服务就需要共享用户的这些信息。
以共享用户身份为例。提供拥有个性化特点的Web服务,将维护每个用户身份的信息。当个人使用服务时,他要向服务自报身份。有时,Web服务将根据个人系统中保存的一个cookie自动确定他的身份。有时,用户必须输入用户ID和口令。试想,在访问的所有网站中,你不得不记住多少个用户ID和口令,你在你的系统中保存了多少个cookie?有多少家公司需要维护各自的有关你个人信息的数据库。
在对广泛的分布式异构Web服务有透彻的了解和实现动态的互动之前,首先必须解决共享用户信息的问题,但靠一家供应商是无力解决这个问题的。不过,解决方案不能是专用的,而必须是开放的和可以互操作的,必须与任何Web服务执行协作。解决方案必须保护个人信息的安全与隐私权。
8、开发者需求
面对上述问题,开发者应该何去何从?显然,他们不应坐等新标准出现。他们需要现在就着手创建Web服务。但是,他们需要帮助,需要了解如何使各类不同的Web服务技术实现协同工作。他们还需要有利于保障Web服务实现互操作的指导原则,并需要能够创建"智能化"Web服务。
9、智能化Web服务
智能化Web服务是指能够分析具体的用户信息,并能够与其它服务共享用户信息的Web服务。它能够根据"谁"、"什么"、"何时"、"何地"和"为什么"诸要素,生成动态结果。智能化Web服务可以识别大量的用户信息,例如:
服务的消费者的身份,是个人还是公司,甚或是另一个Web服务;
消费者在调用服务时使用的职务;
消费者可能为某种服务定义的优先选择;
与消费者相关的安全方针;
与消费者相关的隐私权方针;
与消费者相关的商务方针;
消费者的具体的地理位置;
调用服务时使用的客户机设备类型;
与本服务或相关服务消费者相关的以往的历史情况;
消费者与本服务供应商之间存在的任何服务级别协议。
比如,你要调用智能化饭店查找服务,让他帮你选一家饭店。该项智能服务需要根据你住在何处,你喜欢什么,你最近去了哪家饭店,你要和谁一块进餐等情况,提出一个建议。你是和自己的孩子还是陪一位重要的客户共同进餐,情况可大不一样。因此,智能化饭店查找服务需要考虑你的身份、爱好、历史和职务等。
又比如,设想加州地区出现了能源危急,电力公司向所有用电消费者宣布进入三级供电短缺紧急状态。如果可行,该项通知将在所有的客户站点启动能源保护服务。在企业设施内,能源保护服务将按照时间与日期等诸如此类的参数和据此预定的方针,调节恒温器的温度或关闭照明灯,自动减少用电量。有的预定方针会被当时具体的情况参数所取代,例如在特定的生产运营期间生效的临时服务级别协议。在家庭,能源保护服务可以调节恒温器,关闭照明灯,控制青少年立体声系统的音量。不过,智能Web服务还将考虑谁呆在家里。例如,智能化服务知道婴儿在楼上睡觉,因此不会改变楼上供暖区的恒温器的供电情况。
最后,让我们举出订单执行过程为例。设想一个客户订购了六种不同的产品。客户下订单时,你承诺在两日内发货。但是,当采购服务部门向合同供货机构下订单时,却发现有一种产品供货受限,使你无法按预先的承诺向客户发送订购的所有产品。在诸如此类的情况下,你的标准政策是发运部分产品,但这样做将使利润受损。最令人不快的是,即使执行了多次发货,但产品却往往完全是同日到货,尽管客户或许不介意是今日还是明日到货。因此,你需求一种既节省成本,又能使客户满意的两全其美的方案。
智能Web服务不会自动执行多次发运,而是首先考虑客户概情况和过去历史,权衡赶制缺货部件与调整工厂生产计划所产生的利润影响,然后再据此确定一系列行动。智能Web服务还可能考虑库存成本、空间成本、预计运费和预计交付时间等其它参数。它可能采用电子邮件、SMS信息、自动语音应答信息、回复传真或客户概况中给出的其它某种交付渠道,向客户发送如下的查询-请求客户作出决定:
1.鉴于给你带来的不便,请接受我们提供的这项优惠券。一旦订单执行完毕,我们将即刻发货,目前估计发送需要5天时间。
2. 你订购的产品一旦有货,将分批发送。
10、提升Web服务智能化水平
任何人都能够创建与用户信息相关的Web服务。当然了,现在就有许多Web网站,根据你是谁和你访问网站的过去历史,提供高度定制化的服务。但符合用户的具体情况还只是问题的一半。智能化服务还必须能够和其它服务共享用户信息。令人遗憾的是,目前缺少代表这些用户信息的标准和规范。提供个性化服务的每个网站,都采用专用格式保存用户身份和历史情况等信息。
人们需要的是代表用户信息的一套新标准和一种XML框架,另外还需要一种开放式体系结构,以便定义智能化服务如何使用用户信息,保障服务的操作性能。
11、旨在实现互操作的智能化Web服务的开放式体系结构
Sun为支持互操作智能Web服务,定义了一种开放式软件构架。SunTM Open Net Environment(开放式网络环境,即Sun
ONE)软件体系结构,旨在解决诸如隐私、安全和身份等重要问题,定义支持诸如客户机设备类型和用户位置等用户情况的惯例和常规。它支持可以跨越许多网络系统,其中包括传统Web、无线Web和家庭网络。该体系结构的宗旨是要保证使用任何工具,开发智能Web服务,使之运行于任何平台,可以无缝地实现互操作。
Sun ONE体系结构基于一系列深受青睐的开放和流行标准、技术及协议。在定义该体系结构期间,Sun为满足完善该体系结构的需求,确定了一些新标准。Sun将与其它公司携手,通过相关标准组织,以及W3C、OASIS、IETF、UDDI、ebXML、Java
Community ProcessTM Program等诸如此类的行业技术,支持开发新标准。特别是,Sun将通过协作,推动开发支持共享用户信息的新标准。
12、核心标准与技术
从本质上讲,Sun ONE软件构架基于XML、Java技术和LDAP。Sun的技术原则是采用通用和流行技术,也就是说使用现行可用的技术,而不是要重新发明。Sun
ONE构架使用的核心标准如下:
XML标准与技术,其中包括核心W3C XML建议 (XML、DOM、XML Namespaces、XSLT、XPath、XLink和XPointer);开发团体的XML分析器、SAX;表现格式(XHTML、WML和VoiceXML);XML模式系统(DTD、XML模式、RELAX和正在出现的TREX技术规范);XML信息传递系统(新出现的W3C
XML协议、SOAP和ebXML信息服务);XML注册器与仓库(UDDI Business Registry、ebXML注册器与仓库以及OASIS
xml.org);XML服务描述语言(WSDL);XML管理信息交换框架(DMTF CIM与WBTM);B2B XML框架(ebXML协作伙伴协议、ebXML商务过程方法和ebXML核心组件);XML安全系统(XML签名、XML加密以及新出现的OASIS安全服务项目);
Java技术,其中包括Java 2平台企业版(J2EETM)、Java 2平台标准版(J2SETM)、Java
2平台Micro版(J2METM)、MID(Mobile Information Device)规定、Java
CardTM API、Java Servcet与JavaServer PagesTM
(JSPTM)软件、适用于数据库访问的Java API (JDBC)、适用于XML的Java API
(适用于XML处理的Java API、适用于XML数据联编的Java API、适用于XML注册的Java API、适用于XML信息传递的Java
API);
基础设施标准,例如HTTP、SLL和LDAP。
13、Sun ONE软件体系结构
Sun ONE软件体系结构是一种生机勃勃的系统体系,随着有利于增强该软件环境的新技术的不断出现,它将继续扩展。图1概括显示了Web服务体系结构主要部件的高级功能。
图1顶部是服务创建与汇编框。这一部分显示根据Web服务模式开发系统而使用的工具。通常,Web服务由一系列分离式服务部件组成,这些部件采用实例描述各种内容、商务逻辑和应用。因此,服务开发过程涉及两个不同阶段。
第一阶段涉及创建分离式服务,Sun ONE软件体系结构称之为微观服务。第二阶段是把微观服务汇编成整合服务,或宏观服务。开发人员使用集成开发环境、代码生成器、XML编辑器和创作工具,构建微观服务。(本文将在下面提供关于微观服务开发模式的详细信息)。服务汇编人员使用商用过程模式工具、工作流工具和其它类型的粘贴工具,汇编宏观服务。汇编人员还使用方针工具定义商务规则、安全方针,以及运行时可以动态方式改变宏观服务的与用户信息相关的方针。服务测试完毕后,就可以随时安装于部署平台,方针和规则可以部署于一个开放式目录。管理工具提供部署和管理服务环境的功能。
位于图1服务创建与汇编框的下部的是已部署服务框,它由商务服务(宏观服务)与服务部件(微观服务)组成。微观服务可以汇编、配置或再配置成任何数量的宏观服务。
图1的其余部分显示Sun ONE软件部署体系结构。图形从右至左显示服务消费者与服务接口的交互情况。服务接口提供连接、位置、发现和通信等基本功能。体系结构的这一部分包括各类用户和允许Web用户、无线用户、语音用户以及外部商务系统调用服务的各类商务门户。服务接口把每个请求,定向于相关的Web服务。
微观服务和宏观服务在某种类型的服务容器内执行。服务容器为服务提供运行时的环境,并为服务提供持续和状态管理。服务容器运行于服务平台,提供对数据库、目录和信息传递服务的访问。服务平台驻留于操作系统或虚拟机,提供对硬件、存储器和网络的访问。值得注意的是,Web服务可以部署于任何类型的平台或智能化设备。
过程管理工具与服务容器进行协同工作,管理服务工作流和事件处理。服务集成工具使用基础服务平台,访问其它Web服务与资源,例如数据库、文件、记录和传统应用。
为系统增加智能
附加功能。智能化方针的功能是,根据由用户身份、相关信息和职务等有关方针来协调各种相应的活动。智能化交付工具可根据用户信息,集合服务结构,并实现服务结果的定制化与个性化。智能化过程是根据用户信息,去更改商务服务工作流的过程。智能化管理将根据用户信息所确定的具体情况,保障用户的隐私权、安全性和访问权力。
15、Web服务处理模式
准备服务
准备服务
智能管理工具旨在管理、监控和维护Web服务,其功能如下:
保证通过一个或多个服务注册器,正确地注册和定位服务;
保证签署和正确地执行相关使用收费或订购协议;
协调服务提供,并保证按服务级别协议规定的最低服务质量或其它标准,执行服务。
从智能化方针工具确定管理和运行时方针。
智能化方针工具旨在管理和连接各种目录和仓库,其中包含的方针和商务规则将会影响服务的处理过程。
处理服务请求
服务请求可以通过任何类型的交付渠道提交。智能化交付工具根据用户地理位置、职务和要求服务的时间等信息,确定用户觉得信息,并将用户请求传递给服务去执行。
服务工作流
智能化过程工具旨在管理宏观服务的动作设计。它根据用户信息和为服务定义的方针与商务规则,保证按正确的顺序调用相关微观服务或外部服务。服务使用集成和资源访问引擎调用其它服务,并访问数据库、文件、传统的应用和其它资源。
交付服务应答
处理完毕后,智能化交付工具使用个性化与用户敏感性引擎,为消费者量体定制应答。最终的应答通过相关交付渠道,交付给用户。
16、标准背板
图4显示Web服务体系结构及其许多标准与技术。这些标准和技术为Sun ONE软件体系结构奠定了基础。并非每一种情况均需要所有这些标准,它们是作为实现互操作的指导原则和辅助手段而提供的。
智能化交付
智能化交付支持各种各样使用一系列设备专用表示格式的客户机,其中包括HTML、XHTML、WML和VoiceXML。
超文本标记语言(HTML)是向用户交付电子信息最常用的技术。
XHTML是与XML兼容的变体HTML。HTML和XHTML是W3C实现的技术。
无线标记语言(WML:Wireless Markup Language)是用于众多WAP兼容无线设备的表示格式,例如移动电话。WML是WAP论坛开发的技术,当前已采用XHTML的一个子集用作WML的后续产品。VoiceXML允许创建声频对话,声频对话拥有合成语音、数字化声频、语音和HTMF键盘输入识别以及语音输入、电话与混合型技术会话、纪录等特性。其主要目标是把基于Web的开发与内容交付优势,融合于交互式语音应答应用。VoiceXML是VoiceXML论坛与W3C的联合项目。
智能化交付工具还管理内容转换,通常使用XML和XSLT技术。可扩展标记语言(XML)是一种平台中立和语音中立数据表示格式,为以Web服务与电子商务为重心的每个重要项目,打造了一个基础。应用使用DOM或SAX操作XML。文档对象模式(MOD:Document
Object Model)是一种平台中立和语言中立应用编程接口,它允许程序以动态方式,访问和更新XML与HTML文档的内容、结构及格式。DOM为XML数据提供存储器树形结构访问,这样整个文档结构都可以执行读和写访问。Simple
API for XML (SAX)提供基于事件的串行XML分析程序。Extensible Stylesheet Language
Transformations (XSLT) 是把XML文档转换成XHTML、WML、VoiceXML、其它XML文档或其它数据格式的编程语言。XML、DOM和XSLT是W3C的工作项目。SAX是XML-DEV讨论组成员的一个协作项目。
Web服务显示一个XML接口,它是使用XML信息传递协议予以实现的,例如SOAP、ebXML信息服务(ebXML MS)或新出现的W3C
XP。诸如文档式样定义(DTD)、XML Schema和RELAX等XML模式语言,或新出现的TREX技术规范,旨在描述XML信息的格式。信息模式在一个模式注册器里执行注册,例如xml.org。Web服务可使用WSDL等Web服务描述语言执行描述,在UDDI
Business Registry和/或ebXML Registry与Repository执行注册。
服务容器
服务容器为Web服务提供运行时的环境。使用的服务容器类型,取决于托管服务所使用的平台类型。Sun ONE软件体系结构为相关服务器和其它设备都提出了很好的建议。
基于服务器的被建议的服务容器,是J2EE应用服务器。基于J2EE技术的服务,可以作为服务器小程序、JSP页面或Enterprise
JavaBeans? (EJB?)部件予以实现。当前,J2EE应用服务器以透明方式,管理与Web服务相关的大量复杂部署与执行。当Web应请求提供较多的用户信息以及有关服务的可用信息时,J2EE容器将发挥极其重要的作用,即以透明方式利用这些信息配置和定制Web服务。J2EE容器将扩展其现行说明方式,以使智能服务实现自动化开发与部署,不需要开发人员执行复杂的编程任务。这种说明方式现已应用于资源管理、交易管理、状态管理和安全等领域。J2EE说明编程技术大大减少了Web服务开发的复杂性。
基于设备的被建议的服务容器是J2ME技术,它为基于无线电话、PDA、电视、汽车信息系统和其它多种消费者设备与嵌入式设备的Web服务,提供一个部署平台。J2ME设备在一个启动文件里执行定义,其中包括Java虚拟机和一系列API,它们提供访问基础设备的能力。启动文件提供必要的抽象过程,允许跨越极其广泛、种类繁多的网络和设备,以透明方式部署服务与内容。当前可用的技术包括适用于无线电话和PDA的移动信息设备启动文件(MIDP)与适用于广播电视、机顶盒和个人录相机的Java
TV API。这些平台提供的应用模式,使服务可以访问设备的许多特性,包括存储器、用户界面和个性化服务等。
智能化管理
传统以来,系统与网络管理一直是使用大型分布式应用予以实现的。在这种情况下,系统管理软件供应商的专用代理软件,安装于被管理的每种资源,相同供应商生产的中央服务器要连接每个代理,以管理资源。尽管大多数管理代理遵循简单网络管理协议(SNMP)标准,但大部分管理系统鼓励采用同构的管理基础设施,以实现最大的收益。这种方式导致采用广泛部署的大型系统管理框架,从而把客户的整体管理束缚于一家供应商。
当前,系统管理正转向基于工业标准的Web服务,从而允许采用新一代模块化、互操作系统管理解决方案。在这种新型模式中,专用代理被为使用XML和HTTP等开放标准而设计的代理取而代之,中央服务器被使用这些标准与代理执行交互的Web服务取而代之。
在此种模式中,系统与网络设备将为他们的设备提供管理代理,许多公司将竞相提供以特定管理领域为目标的模块化Web服务。因此,客户再也不会被束缚于一家供应商,他们将能够为每个管理层面寻求最佳的供应商。
此种模式的标准被称为公用信息模式(CIM:Common Information Model),是由坚持以分布式管理为重点的标准组织,即分布式管理特别工作组(DMTF)定义的。CIM为系统管理发挥的作用,跟ebXML为B2B交易发挥的作用相同。CIM旨在为设计Web
服务,定义相关模式和协议标准。而且,这些Web服务能够独立工作,跟它们交互的其它服务和代理的基本设计无关。例如,CIM为通过网络访问服务器基本信息,定义标准的XML对象,其中的许多对象已经在大量服务器操作平台予以实现,例如Solaris?操作环境和Windows
2000。
此种模式在开放式智能Web服务领域产生了重要影响,表现在下列两个方面。
1. Web服务将由此种模式执行管理。开发人员可以使用Java管理扩展(JMX?) API改编Web服务,为管理Web服务的部署、健康和性能构建标准接口。CIM标准允许开发人员执行这项工作,他们是实现这些特性的最佳人选。当部署Web服务时,基于Web的管理服务将能够使用相同的标准查找这些服务,并通过其代理管理它们。
2. 作为定义明确的服务,公司将能够把系统和网络管理外包给第三方管理服务提供商(MSP),他们可通过网络执行这些任务。鉴于这些服务是模块化服务,客户可以逐项确定哪些管理任务需留给内部执行,哪些需实行外包。
p>
智能过程
智能过程工具允许实现与用户信息相关的服务的动作设计。基于用户信息的智能化处理技术,根据请求的用户信息,譬如所在地理位置、管辖范围或商务关系成熟与否等,以动态方式改变微观Web服务调用的设计顺序,进而改变宏观Web服务的结果。
在ebXML环境中,B2B商务过程表示为商务服务交换的设计顺序。每个基本服务交换都被称为商务交易。一般而言,商务服务是高级服务,例如订购服务或帐单支付服务。但在幕后,一种商务服务通过循环方式,由许多低级服务组成,例如产品查找服务、报价服务、货币兑换服务等。
交易中心标记语言(XAML)为设计商务服务提供了一种可选的方法。XAML计划是Bowstreet、惠普、IBM、Oracle和Sun联合发起的,宗旨是定义一系列XML信息格式与交互模式,以便协调和处理互联网上涉及多方的商务级交易。
智能化方针
Web服务可以使用方针引擎,根据考虑用户身份、授权等级和其它背景信息的规则,以动态方式适应处理和/或结果。面向用户信息的标准仍有待定义,但许多与安全相关的标准和协议已经存在。用户和方针信息维护在一个采用LDAP协议可以访问的开放的目录中。Kerberos与公钥基础构架(PKI)技术委员会的工作目标,就是为交换认证和授权信息定义一个XML框架。这样,就可以使用开放技术,以更加安全可靠的方式执行跨企业交易。该框架将为访问认证和授权服务,提供请求/应答协议,用XML形式编写请求和确认身份与权利的代码,为各种传送与通信协议提供安全信息联编。OASIS委员会把建议的两种安全技术规范,即安全服务标记语言(S2ML:Security
Services Markup Language)与AuthXML,合二为一。其中,S2ML技术规范由Bowstreet、Commerce
One,Jamcracker、Netegrity、Sun、Verisign和Web Methots等公司编写而成,AuthXML技术规范由以Outlook科技公司为首的一个业界联盟编写。
17、Web服务开发模式
尽管可以使用任何编程语言开发Web服务,但Sun ONE软件构架基于Java平台。Java平台包括XML本机支持。Java
API for XML Processing (JAXP)为连接DOM、SAX和XSLT,提供一个Java接口。面向XML的其它Java
API,通过Java Community Process Program,正处于不同的发展阶段。Java API for XML
Data Binding (JAXB)把XML数据和Java代码相连接。开发人员使用JAXB把XML模式信息编译成Java对象。在运行时,JAXB自动把XML文档数据变换成Java对象,反之亦然。Java
API for XML Messaging (JAXM)为连接ebXML MS、W3C XP和SOAP等XML信息传递系统,提供一
个本机Java接口。Java API for XML Registries (JAXP)为连接XML注册器和仓库提供一个接口,例如ebXML注册器/仓库与UDDI商务注册器。一种新的Java技术规范请求已经提交JCP,以便定义Java
API for XML RPC (TAX/RPC),后者将为适用于XML信息传递系统的RPC编程常规,提供直接支持,例如SOAP和即将出台的W3C
XP。
Web服务构成
图5从开发人员角度显示微观Web服务。Web服务由Web服务接口和一至两个服务部件组成。其中,Web服务接口负责管理和操作XML信息。服务部件包括实现服务的商务逻辑,并经常通过一系列集成服务,跟外部资源与服务执行交互。
Web服务接口
Web服务通过标准Web协议,例如HTTP,传送XML文档,由此实现通信。Web服务接口实现生成并消费XML信息的代码。Sun
ONE软件体系结构建议采用3类XML信息传递系统:即SOAP、ebXML MS和将来的W3C XP。
SOAP是一种轻型可扩展XML信息传递协议。尽管SOAP是通用XML信息传递服务,但特别适合于RPC类服务调用。SOAP信息是一种XML文档,由标题与正文组成。信息数据用XML详细说明,并封装于SOAP正文中。SOAP支持RPC编程常规,后者将自动把输入输出参数和SOAP信息正文里的XML元素相连接。由于XML文档不能包含另一个XML文档,故SOAP信息不能包含一个完整的XML文档,例如采购订单。SOAP协议还不支持多媒体文件的附件或其它非XML数据。SOAP不提供服务质量(QoS)框架。可以通过Apache软件基金会,获取实现SOAP接口的Java工具。基础SOAP环境可以扩展,以支持QoS框架,但现在还不能实现。
ebXML MS是一种XML信息传递服务,是为了支持B2B商务需求而设计的。EbXML信息是一种多方/MIME封装信息,可以传输任何数量的XML文档和非XML附件。ebXML不支持RPC编程常规,但支持QoS框架以保障可靠地交付信息。QoS框架可以扩展,以支持安全与交易语义。ebXML技术规范于2000年5月出台。
W3C XP技术规范处于开发之中。关于W3C的工作进展细节未向外界透露。 Web服务接口是作为运行于Web服务器内的JSP页面或服务器小程序予以实现的。JSP页面/服务器小程序接收XML信息,并析取XML文档。当前,该过程以人工方式执行。将来,开发人员可以使用JAX或JAX/RPC,以更有效的方式处理XML信息。然后,JSP页面/服务器小程序接收XML文档,把文档数据变换成Java对象数据。今天,开发人员可以使用JAXP处理XML文档,将来可使用JAXB自动把文档和Java对象相连接。
捕捉背景信息
Web服务接口还尽可能地捕捉许多背景信息。通过检索客户机系统的cookie目录,就可以捕捉用户身份,或者要求用户提供用户ID与口令。一旦服务接口确定了身份,服务就可以查询专用用户历史文件,以检索附加背景信息。当前,Sun与伙伴携手推进一个标准项目,为处理身份和用户信息定义标准框架。用户背景信息框架的细节尚未定义,但预计将有标准的API推出。届时,JSP页面/服务器小程序可以使用这些API,获取用户的背景信息。
商务逻辑
一旦JSP页面/服务器小程序把XML数据变换成Java数据,并捕捉了用户背景信息,然后便执行通常的会话管理服务,并调用商务逻辑,由商务逻辑执行实际服务。商务逻辑是作为EJB部件或适用于轻型应用的服务器小程序予以实现的。商务逻辑部件将与管理整合商务交易的工作流引擎相连接,并与根据用户身份和身份背景,实施相关商务规则的方针引擎相连接。目前,该过程的标准尚未定义。但无疑,ebXML、XAML和OASIS安全服务将在该过程中发挥作用。
集成服务
商务逻辑部件将需要连接各种资源。JDBC? API提供数据库访问,J2EE连接器与Java信息服务(JMS)提供其它应用系统访问,XML信息用于连接其它Web服务。当前,开发人员需要使用JAXP,以人工方式构建XML信息。将来,开发人员可以使用JAXM或JAX/RPC,以更便捷的方式操作XML信息。
回送结果
当商务逻辑部件完成工作后,将向JSP页面/服务器小程序接口部件回送Java结果对象。接口使用JAXP,把结果从Java对象变换成输出XML文档,将来可以使用JAXB。然后,JSP服务器小程序可以使用背景信息,进一步应答文档。定制完成后,应答将回送给请求者。
总结
Sun ONE软件构架旨在帮助开发人员成功地创建Web服务。当前可用的Web服务技术,仍然处于初期发展阶段。但这并未阻止开发人员向这个令人惊奇的新领域拓展。Web服务代表了下一代软件。而Sun
ONE软件构架为帮助开发人员整合各种XML标准、技术和计划,提供了一种指导原则。Sun ONE的开发模式为执行开发项目打造了一个基础,它表明哪些技术和API应该用于Web服务的各个层面。Sun将继续提供工具、技术、规范和建议,推动Web服务计算模式向前发展。
<淘宝热门商品:
来源:程序员网
java的网络功能与编程
徐迎晓
(上海大学计算中心25#)
摘 要:Java语言是Internet上最热门的编程语言,本文针对Java的网络功能,对Java从网络上获取图象、声音、HTML文档及文本文件等编程方法作了初步的介绍,同时介绍了动态获取网络上资源的方法作了介绍。文中提供了大量简明易懂的实例。
关键词:Java;Internet;网络
Java语言是Internet上新兴的编程语言,对Java的特性以及基本的编程方法已有很多文章作过介绍。但是,广大Java爱好者更希望了解Java更深一步的编程方法,本文就Java的网络功能及其编程方法
作一初步的介绍。
为了方便初次接触Java的读者,本文先就Java编程的一些常识作简单介绍。一、Java编程简介 1. 编程环境:对于大部分读者,以下的配置是较为经济的一种选择:操作系统 Win95 编译软件 JDK1.01 浏览软件 Netscape2.0以上(32位) 2. 编程方法:先用文本编辑器如Edit、NotePad等输入Java程序,以.java为文件名后缀存盘。再执行命令行:“Javac 文件名”来编译Java程序。编译后生成后缀为.class的字节码文件。最后,如果是Java Applitcation,则执行命令行:“Java 字节码文件名”来运行Java程序。如果是Java Applet,则用文本编辑器输入调用该Java Applet的HTML 文档, 以 .htm 为文件名后缀存盘。 再执行命令行:“appletviewer HTML文件名”来运行Java Applet。或用Netscape打开该HTML文档。 3. 关于本文中程序的说明为了使程序能够最简洁地体现其所代表的编程方法,本文中的程序一般采用最简单的形式,省略了线程等内容。因此,本文的程序不是“好”的程序,但最容易为初学者理解。本文的所有程序经编译后,生成的字节码文件及对应的HTML文档已上载到http://www.shu.edu.cn/~xyx/test/jvnet, 均可正确运行。连入Internet的读者可用浏览器打开该地址,查看运行效果。连入Internet的读者也可以在本地硬盘输入并编译本文的程序,用Netscape的File/Open File菜单打开HTML文档,体会编程方法并查看运行效果。如果读者想将Java Applet 放到自己的主机上或其他ftp服务器上,在Netscape中用http协议或ftp协议调用,出于安全性限制,应作如下修改:如果读者在某个WWW主机上有帐号,可以做个人Homepage(一般在用户根目录创建WWW或public_html目录即可,Homepage的地址为http://HostName/~个人帐号),可将本文程序中对应的http://www.shu.edu.cn/~xyx/部分修改为读者自己的Web结点地址,然后将编译后生成的字节码文件及对应的HTML文档上载到自己的结点上。如果读者的计算机连入了Internet,也可以找一个可以上载的ftp结点,如:ftp://ftp.shnet.edu.cn/incoming,将本文程序中对应的http://www.shu.edu.cn/~xyx/部分修改为ftp结点的地址,将编译后生成的字节码文件及对应的HTML文档上载到该结点上,以查看运行效果。如果读者的计算机没有联网,也可以在单机上运行Web 服务软件如Webstar for Win95,将本文程序中对应的http: //www. shu.edu.cn/~xyx/部分修改为“http://本地IP地址”的形式,来模拟网络编程。
二、Java网络功能及获取网络上资源的一般步骤 Java程序可以获取网络上结点的图象、声音、HTML文档及文本等资源,并可以对获得的资源进行处理。例如Java程序可以每隔一定时间读取某结点提供的最新数据,并以图表的形式显示出来。在编程处理上,一般先生成一个URL类型的对象,然后用 Java中相应的方法(method)获取该对象所代表的资源。下面分别介绍Java网络功能的几个例子,并由此介绍几种不同的编程方法。三、从网络上获取图象 Java Applet可以直接从网络上结点获取图象并显示出来。 为了了解其编程方法和从本地显示图象的编程有何不同,我们先不考虑网络功能,来看一个简单的图象显示的例子:
●程序1
import java.applet.*;
import java.awt.*;
public class imag0 extends Applet{
Image image;
public void init() {
image=getImage(getDocumentBase(),“test.gif“);
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0,this);
}
}
|
这是一个最简单的获取并显示图象的例子, 在该例中, 先用getImage(getDocumentBase(),图象文件名)从HTML文档所在位置调用图象test.gif,并由此生成一个Image类型的对象image, 然后用drawImage(image, 0, 0,this)在屏幕上将图象显示出来。
如果想从网络上其他结点获取图象,关键是创建对应于网络上其他结点的Image类型的对象,一旦获得Image类型的对象获得了,便可以对其进行任何可能的图象操作。
Java提供了如下方法可以创建对应于其他结点的图象:
getImage(new URL(字符串))
其使用格式可有两种:
String url = “结点URL“;
Image image;
try {
image = getImage(new URL(url));
}
catch(Exception e){
System.out.println(“Can‘t open the URL “);
}
或
URL imgur=null;
Image image;
try {
imgur=new URL(“结点URL “);
}
catch (MalformedURLException e) {
System.out.println(“Can‘t open the URL “);
}
image=getImage(imgur);
|
前一种格式用“new URL(url)”生成 URL 对象, 并直接作为getImage的参数,后一种格式先用“new URL(url)”生成一个 URL对象,再传给getImage。两种格式本质上是一样的。两种格式中,生成URL对象的部分都包含在
try{
获取URL对象
}
catch (MalformedURLException e) {
出错提示
}
|
中。
例如要调用http://www.shu.edu.cn/~xyx/img/shnet.jpg结点的图象,第一种格式完整的程序如下:
●程序2
import java.applet.*;
import java.net.*;
import java.awt.*;
public class imag extends Applet{
Image image;
public void init() {
String url = “http://www.shu.edu.cn/~xyx/img/shnet.jpg“;
try {
image = getImage(new URL(url));
} catch(Exception e){}
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0,this);
}
}
|
第二种格式完整的程序如下:
●程序3
import java.applet.*;
import java.net.*;
import java.awt.*;
public class imag2 extends Applet{
Image image;
URL imgur=null;
public void init() {
try {
imgur=new URL(“http://www.shu.edu.cn/~xyx/img/shnet.jpg“);
}
catch (MalformedURLException e) {
System.out.println(“Can‘t open the URL “);
}
image=getImage(imgur);
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0,this);
}
}
|
将上述两个程序分别以imag.java和imag2. java 存盘, 执行javac imag.java和javac imag2.java,将得到编译后生成的imag.class和imag2.class,最后创建调用这两个Java Applet的HTML文档,如imag.class对应的HTML文档可如下:
< html >
< head >
< title >Example < /title >
< /head >
< center >
< applet code=imag.class width=550 height=250 >
< /applet >
< /html >
|
将该HTML文档存入test.html文件,用Netscape打开, 如果你的计算机连入了Internet,便可以看到Java Applet 所显示的从网络上获得的图象了。(对于本文中其他不同的Java Applet, 对应的HTML文档只要修改其中相应的“code=imag.class”即可。)
四、从网络上获取声音
Java从网络上获取声音文件并播放声音的编程方法有两类,一是利用Java提供的play(URL)及play(URL,String) 直接播放网络上的声音文件,另一类是通过getAudioClip(URL)或getAudioClip(URL,String)先从网络上获取声音文件,并生成AudioClip 类型的对象,然后对该对象进行操作。
前者的使用格式是:
String Audur = “结点URL“;
try {
play(new URL(Audur));
} catch(Exception e){}
或
String Audur = “结点URL“;
try {
play(new URL(Audur),声音文件名);
} catch(Exception e){}
后者使用的格式是:
String Audur = “结点URL“;
AudioClip loopClip;
try {
loopClip = getAudioClip(new URL(Audur));
}
catch(Exception e){
System.out.println(“Can‘t open the URL “);
}
或
String Audur = “结点URL“;
AudioClip loopClip;
try {
loopClip = getAudioClip(new URL(Audur) ,声音文件名);
}
catch(Exception e){
System.out.println(“Can‘t open the URL “);
}
|
上面的四种格式都是将生成URL对象部分--“new URL(url)”直接作为play或getAudioClip的参数;和前面处理图象的例子一样,也可以先用“new URL(url)”获取一个URL对象, 再传给 play 或getAudioClip。如对第一种play(URL)的格式, 也可采用如下的编程格式:
URL Audur =null;
try {
Audur=new URL(“结点URL “);
} catch(Exception e){
System.out.println(“Can‘t open the URL “);
}
play(Audur);
|
下面对前述四种从网络上获取并播放声音文件的格式各举一简单的例子,
以作编程时参考:
●程序4 格式一
import java.applet.*;
import java.awt.*;
import java.net.*;
public class sound1 extends Applet
{ AudioClip loopClip;
public void paint(Graphics g) {
String Audur = “http://www.shu.edu.cn/~xyx/java/Animator/audio/bark.au“;
try {
play(new URL(Audur));
} catch(Exception e){}
}
}
|
●程序5 格式二
import java.applet.*;
import java.awt.*;
import java.net.*;
public class sound2 extends Applet
{ AudioClip loopClip;
public void paint(Graphics g) {
String Audur = “http://www.shu.edu.cn/~xyx/java/Animator/audio/“;
try {
play(new URL(Audur),“bark.au“);
} catch(Exception e){}
}
}
|
●程序6 格式三
import java.applet.*;
import java.awt.*;
import java.net.*;
public class sound extends Applet{
AudioClip loopClip;
public void init() {
String Audur = “http://www.shu.edu.cn/~xyx/java/Animator/audio/bark.au“;
try {
loopClip = getAudioClip(new URL(Audur));
} catch(Exception e){}
}
public void paint(Graphics g){
loopClip.loop();
}
}
|
●程序7 格式四
import java.applet.*;
import java.awt.*;
import java.net.*;
public class sound0 extends Applet{
AudioClip loopClip;
URL auur;
public void init() {
try {
auur=new URL(“http://www.shu.edu.cn/~xyx/java/Animator/audio/“);
}
catch (MalformedURLException e) {
System.out.println(“Can‘t open the URL “);
}
loopClip = getAudioClip(auur,“bark.au“);
}
public void paint(Graphics g){
loopClip.loop();
}
}
|
五、显示网络上其他HTML文档
利用Java提供的getAppletContext().showDocument(URL)可以显示其他结点的HTML文档,同前面的显示网络上其他结点的图象,有两种格式,下面各举一例:
●程序8 格式一
import java.applet.*;
import java.awt.*;
import java.net.*;
public class showdoc extends Applet
{
URL docur= null;
public void paint(Graphics g) {
try {
docur=new URL(“http://www.shu.edu.cn/~xyx/doc/manhua.html“);
}
catch (MalformedURLException e) {
System.out.println(“Can‘t open the URL “);
}
if (docur != null) {
getAppletContext().showDocument(docur,“_blank“);
}
}
}
|
●程序9 格式二
import java.applet.*;
import java.awt.*;
import java.net.*;
public class showdoc2 extends Applet
{
URL docur= null;
public void paint(Graphics g) {
try {
getAppletContext().showDocument(new URL(“http://www.shu.edu.cn/
~xyx/doc/manhua.html“));
}
catch (MalformedURLException e) {
System.out.println(“Can‘t open the URL “);
}
}
}
|
六、读取网络上文件内容
前述的网络功能只是显示或播放网络上结点的图象、 声音及HTML文档,并没有对其内容进行处理。事实上,Java还可读取网络上文件的内容,并对其内容进行处理。
读取网络上文件内容的步骤可如下:
1. 创建一个URL类型的对象
如:
String url = “ftp://202.120.127.218/incoming/test/readtxt.html“;
URL fileur;
try {
fileur = new URL(url); }
catch ( MalformedURLException e) {
System.out.println(“Can‘t get URL: “ );
}
|
2. 利用URL类的openStream(),获得对应的InputStream类的对象
如:InputStream filecon = fileur.openStream();
3. 将InputStream对象转化为DataInputStream类的对象
如:DataInputStream filedata = new DataInputStream(filecon);
4. 读取内容
如对前面的filedata,可用filedata.readLine() 一行一行读取内容,或用filedata.readchar一个字符一个字符读取内容。 对读取到的内容,可由Java Applet进行各种处理, 并将处理结果用各种方式显示出来。
下面的例子是读取 http://www.shu.edu.cn/~xyx/doc/manhua.html文件内容的例子,为简洁起见,该例中只将文件的内容逐行读出,并在文本区显示出来。
●程序10
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
public class showfile extends Applet{
URL fileur;
TextArea showarea = new TextArea(“Please wait a while for get
text“,10,70);
public void init() {
String url = “http://www.shu.edu.cn/~xyx/doc/manhua.html“;
try { fileur = new URL(url); }
catch ( MalformedURLException e) {
System.out.println(“Can‘t get URL: “ );
}
add(showarea);
}
public void paint(Graphics g) {
InputStream filecon = null;
DataInputStream filedata = null;
String fileline;
try {
filecon = fileur.openStream();
filedata = new DataInputStream(filecon);
while ((fileline = filedata.readLine()) != null) {
showarea.appendText(fileline+“\n“);
}
}
catch (IOException e) {
System.out.println(“Error in I/O:“ + e.getMessage());
}
}
}
|
七、动态使用网络上资源
在前面介绍的例子的基础上,可以动态地利用网络上的资源。其方法是编制一个线程,每隔一定时间自动到相应结点读取最新的内容。本文对线程的编制不再展开,读者可参考有关文章或直接套用下面的例子。
例如对上例中读取http://www.shu.edu.cn/~xyx/doc/manhua.html文件内容的例子,加入线程后如下所示。该例子每隔5秒更新一次数据。如果http://www.shu.edu.cn/~xyx/doc/manhua.html中存放的是一些变化较快的信息如股市行情等,并有程序随时动态地更新其内容,则在Web中加入这种Java Applet,可以让流览者得到动态的信息。进一步,也可以在程序中对数据进行处理,并用图形方式显示处理结果。例如将各时刻的数据绘制成曲线,流览者可以看到动态变化的曲线。
//程序11
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
public class dynashow extends java.applet.Applet
implements Runnable {
Thread dthread;
URL fileur;
TextArea showarea = new TextArea(“Wait for a while...“,10,70);
public void init() {
String url = “ http://www.shu.edu.cn/~xyx/doc/manhua.html “;
try { fileur = new URL(url); }
catch ( MalformedURLException e) {
System.out.println(“Can‘t get URL: “ );
}
add(showarea);
}
public void start() {
if (dthread == null)
{
dthread = new Thread(this);
dthread.start();
}
}
public void stop() {
if (dthread != null) {
dthread.stop();
dthread = null;
}
}
public void run() {
InputStream filecon = null;
DataInputStream filedata = null;
String fileline;
while(true){
try {
filecon = fileur.openStream();
filedata = new DataInputStream(filecon);
while ((fileline = filedata.readLine()) != null) {
showarea.appendText(fileline+“\n“);
}
}
catch (IOException e) {
System.out.println(“Error in I/O:“ + e.getMessage());
}
try{
dthread.sleep(5000);
}
catch (InterruptedException e){}
repaint();
}
}
}
|
八、Java网络能力的限制
出于安全性考虑,在用netscape浏览时,Java Applet 只能和其所在的主机建立连接,因此,前面的程序编译后大部分只能存放在http://www.shu.edu.cn/~xyx对应的主机上。存放到其他主机时需更改程序中的结点地址。否则浏览器将显示安全出错。
但对显示网络上其他HTML文档没有此限制(如程序8、9),读者可以将程序编译后放到任意WWW服务器或FTP服务器,均可正常运行。
此外,当浏览器从本地盘打开调用Java Applet的HTML文档时,也不受此限制。因此,本文所有的程序都可存放在本地盘编译,只要用netscape的File/Open File菜单打开,便可正确运行。
对于另一种Java程序--Java Application,也无此限制,例如对于读取网络上文件内容的程序10,对应的Java Application可作如下编程:
●程序11
import java.io.*;
import java.net.*;
import java.awt.*;
class showfile2 {
public static void main(String args[]){
InputStream filecon = null;
DataInputStream filedata = null;
String fileline;
String url = “http://www.shu.edu.cn/~xyx/doc/manhua.html“;
URL fileur;
try {
fileur = new URL(url);
filecon = fileur.openStream();
filedata = new DataInputStream(filecon);
while ((fileline = filedata.readLine()) != null) {
System.out.println(fileline+“\n“);
}
}
catch (IOException e) {
System.out.println(“Error in I/O:“ + e.getMessage());
}
}
}
|
将其以showfile2.java存盘,用javac showfile2.java编译后,只需执行“java showfile2”便可以在屏幕上打印出http://www.shu.edu.cn/~xyx/doc/manhua.html 文件的内容。
九、创建URL对象的方法
在前面的例子中我们统一使用new URL(url字符串)的形式创建URL对象。其实,Java提供了四种创建URL对象的形式:
1.new URL(url字符串) 本文中的程序均采用此种格式,如:
new URL(“http://www.shu.edu.cn/~xyx/doc/manhua.html“)
2.new URL(协议,主机名,文件名或路径) 如程序2中的
String url = “http://www.shu.edu.cn/~xyx/img/shnet.jpg“;
image = getImage(new URL(url));部分可改为:
image = getImage(new URL(“http“,“www.shu.edu.cn“,“/~xyx /img/shnet.jpg“));
3.new URL(协议,主机名,端口号,文件名或路径)1
如:new URL(“http“,“www.shu.edu.cn“,80, “/~xyx/doc/manhua.html“)
4.new URL(基准url,文件名或路径)
|
十、实现网络功能的其他方法
以上着重介绍了利用Java的URL类实现从网络上获取声音、 图象、HTML文档及文件数据的编程方法。Java的网络功能很强大,除上面介绍的外,还可以利用URLconnection 类实现更广泛的网络功能,如向WWW 服务器上的 CGI 程序发送信息等; 通过 Socket 及ServerSocket类,可以自己编写客户软件及服务软件,并可以自己设计通讯协议。
〖参考文献〗
Laura Lemay,Charles L. Perkins “Teach Yourself JAVA in 21 Days“
<淘宝热门商品:
来源: 程序员网
Java编程规则
动感教育网 发布日期:2001-6-15 字数:4500字
http://www.netqu.com 中华技术网会员 Wuxuehui 发布
包含了大量有用的建议,帮助大家进行低级程序设计,并提供了代码编写的一般性指导:
(1) 类名首字母应该大写。字段、方法以及对象(句柄)的首字母应小写。对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母。例如:
ThisIsAClassName
thisIsMethodOrFieldName
若在定义中出现了常数初始化字符,则大写static final基本类型标识符中的所有字母。这样便可标志出它们属于编译期的常数。
Java包(Package)属于一种特殊情况:它们全都是小写字母,即便中间的单词亦是如此。对于域名扩展名称,如com,org,net或者edu等,全部都应小写(这也是Java 1.1和Java 1.2的区别之一)。
(2) 为了常规用途而创建一个类时,请采取“经典形式”,并包含对下述元素的定义:
equals()
hashCode()
toString()
clone()(implement Cloneable)
implement Serializable
(3) 对于自己创建的每一个类,都考虑置入一个main(),其中包含了用于测试那个类的代码。为使用一个项目中的类,我们没必要删除测试代码。若进行了任何形式的改动,可方便地返回测试。这些代码也可作为如何使用类的一个示例使用。
(4) 应将方法设计成简要的、功能性单元,用它描述和实现一个不连续的类接口部分。理想情况下,方法应简明扼要。若长度很大,可考虑通过某种方式将其分割成较短的几个方法。这样做也便于类内代码的重复使用(有些时候,方法必须非常大,但它们仍应只做同样的一件事情)。
(5) 设计一个类时,请设身处地为客户程序员考虑一下(类的使用方法应该是非常明确的)。然后,再设身处地为管理代码的人考虑一下(预计有可能进行哪些形式的修改,想想用什么方法可把它们变得更简单)。
(6) 使类尽可能短小精悍,而且只解决一个特定的问题。下面是对类设计的一些建议:
■一个复杂的开关语句:考虑采用“多形”机制
■数量众多的方法涉及到类型差别极大的操作:考虑用几个类来分别实现
■许多成员变量在特征上有很大的差别:考虑使用几个类
(7) 让一切东西都尽可能地“私有”——private。可使库的某一部分“公共化”(一个方法、类或者一个字段等等),就永远不能把它拿出。若强行拿出,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。若只公布自己必须公布的,就可放心大胆地改变其他任何东西。在多线程环境中,隐私是特别重要的一个因素——只有private字段才能在非同步使用的情况下受到保护。
(8) 谨惕“巨大对象综合症”。对一些习惯于顺序编程思维、且初涉OOP领域的新手,往往喜欢先写一个顺序执行的程序,再把它嵌入一个或两个巨大的对象里。根据编程原理,对象表达的应该是应用程序的概念,而非应用程序本身。
(9) 若不得已进行一些不太雅观的编程,至少应该把那些代码置于一个类的内部。
(10) 任何时候只要发现类与类之间结合得非常紧密,就需要考虑是否采用内部类,从而改善编码及维护工作(参见第14章14.1.2小节的“用内部类改进代码”)。
(11) 尽可能细致地加上注释,并用javadoc注释文档语法生成自己的程序文档。
(12) 避免使用“魔术数字”,这些数字很难与代码很好地配合。如以后需要修改它,无疑会成为一场噩梦,因为根本不知道“100”到底是指“数组大小”还是“其他全然不同的东西”。所以,我们应创建一个常数,并为其使用具有说服力的描述性名称,并在整个程序中都采用常数标识符。这样可使程序更易理解以及更易维护。
(13) 涉及构建器和异常的时候,通常希望重新丢弃在构建器中捕获的任何异常——如果它造成了那个对象的创建失败。这样一来,调用者就不会以为那个对象已正确地创建,从而盲目地继续。
(14) 当客户程序员用完对象以后,若你的类要求进行任何清除工作,可考虑将清除代码置于一个良好定义的方法里,采用类似于cleanup()这样的名字,明确表明自己的用途。除此以外,可在类内放置一个boolean(布尔)标记,指出对象是否已被清除。在类的finalize()方法里,请确定对象已被清除,并已丢弃了从RuntimeException继承的一个类(如果还没有的话),从而指出一个编程错误。在采取象这样的方案之前,请确定finalize()能够在自己的系统中工作(可能需要调用System.runFinalizerson exit(true),从而确保这一行为)。
(15) 在一个特定的作用域内,若一个对象必须清除(非由垃圾收集机制处理),请采用下述方法:初始化对象;若成功,则立即进入一个含有finally从句的try块,开始清除工作。
(16) 若在初始化过程中需要覆盖(取消)finalize(),请记住调用super.finalize()(若Object属于我们的直接超类,则无此必要)。在对finalize()进行覆盖的过程中,对super.finalize()的调用应属于最后一个行动,而不应是第一个行动,这样可确保在需要基础类组件的时候它们依然有效。
(17) 创建大小固定的对象集合时,请将它们传输至一个数组(若准备从一个方法里返回这个集合,更应如此操作)。这样一来,我们就可享受到数组在编译期进行类型检查的好处。此外,为使用它们,数组的接收者也许并不需要将对象“造型”到数组里。
(18) 尽量使用interfaces,不要使用abstract类。若已知某样东西准备成为一个基础类,那么第一个选择应是将其变成一个interface(接口)。只有在不得不使用方法定义或者成员变量的时候,才需要将其变成一个abstract(抽象)类。接口主要描述了客户希望做什么事情,而一个类则致力于(或允许)具体的实施细节。
(19) 在构建器内部,只进行那些将对象设为正确状态所需的工作。尽可能地避免调用其他方法,因为那些方法可能被其他人覆盖或取消,从而在构建过程中产生不可预知的结果(参见第7章的详细说明)。
(20) 对象不应只是简单地容纳一些数据;它们的行为也应得到良好的定义。
(21) 在现成类的基础上创建新类时,请首先选择“新建”或“创作”。只有自己的设计要求必须继承时,才应考虑这方面的问题。若在本来允许新建的场合使用了继承,则整个设计会变得没有必要地复杂。
(22) 用继承及方法覆盖来表示行为间的差异,而用字段表示状态间的区别。一个非常极端的例子是通过对不同类的继承来表示颜色,这是绝对应该避免的:应直接使用一个“颜色”字段。
(23) 为避免编程时遇到麻烦,请保证在自己类路径指到的任何地方,每个名字都仅对应一个类。否则,编译器可能先找到同名的另一个类,并报告出错消息。若怀疑自己碰到了类路径问题,请试试在类路径的每一个起点,搜索一下同名的.class文件。
(24) 在Java 1.1 AWT中使用事件“适配器”时,特别容易碰到一个陷阱。若覆盖了某个适配器方法,同时拼写方法没有特别讲究,最后的结果就是新添加一个方法,而不是覆盖现成方法。然而,由于这样做是完全合法的,所以不会从编译器或运行期系统获得任何出错提示——只不过代码的工作就变得不正常了。
(25) 用合理的设计方案消除“伪功能”。也就是说,假若只需要创建类的一个对象,就不要提前限制自己使用应用程序,并加上一条“只生成其中一个”注释。请考虑将其封装成一个“独生子”的形式。若在主程序里有大量散乱的代码,用于创建自己的对象,请考虑采纳一种创造性的方案,将些代码封装起来。
(26) 警惕“分析瘫痪”。请记住,无论如何都要提前了解整个项目的状况,再去考察其中的细节。由于把握了全局,可快速认识自己未知的一些因素,防止在考察细节的时候陷入“死逻辑”中。
(27) 警惕“过早优化”。首先让它运行起来,再考虑变得更快——但只有在自己必须这样做、而且经证实在某部分代码中的确存在一个性能瓶颈的时候,才应进行优化。除非用专门的工具分析瓶颈,否则很有可能是在浪费自己的时间。性能提升的隐含代价是自己的代码变得难于理解,而且难于维护。
(28) 请记住,阅读代码的时间比写代码的时间多得多。思路清晰的设计可获得易于理解的程序,但注释、细致的解释以及一些示例往往具有不可估量的价值。无论对你自己,还是对后来的人,它们都是相当重要的。如对此仍有怀疑,那么请试想自己试图从联机Java文档里找出有用信息时碰到的挫折,这样或许能将你说服。
(29) 如认为自己已进行了良好的分析、设计或者实施,那么请稍微更换一下思维角度。试试邀请一些外来人士——并不一定是专家,但可以是来自本公司其他部门的人。请他们用完全新鲜的眼光考察你的工作,看看是否能找出你一度熟视无睹的问题。采取这种方式,往往能在最适合修改的阶段找出一些关键性的问题,避免产品发行后再解决问题而造成的金钱及精力方面的损失。
(30) 良好的设计能带来最大的回报。简言之,对于一个特定的问题,通常会花较长的时间才能找到一种最恰当的解决方案。但一旦找到了正确的方法,以后的工作就轻松多了,再也不用经历数小时、数天或者数月的痛苦挣扎。我们的努力工作会带来最大的回报(甚至无可估量)。而且由于自己倾注了大量心血,最终获得一个出色的设计方案,成功的快感也是令人心动的。坚持抵制草草完工的诱惑——那样做往往得不偿失。
(31) 可在Web上找到大量的编程参考资源,甚至包括大量新闻组、讨论组、邮寄列表等。下面这个地方提供了大量有益的链接:
http://www.ulb.ac.be/esp/ip-Links/Java/joodcs/mm-WebBiblio.html
本文摘自<>.
作者:Bruce Eckel
主页:http://www.BruceEckel.com
编译:Trans Bot
主页:http://member.netease.com/~transbot
<淘宝热门商品:
来源: 程序员网
这节教程将讨论一些在学习JAVA语言过程中可能遇到的共同问题。
问题一:编译器找不到类。
解决方法:
确保你已经导入了类或者它的包。
如果对CLASSPATH环境变量有进行设置,要重新复位。
确保类名的拼写跟定义的一样,要注意大小写问题。
如果类在包中,要确保它们处在正确的子目录中。
同时,一些程序员从.java文件名字为类使用不同的名字。要确保你是使用类名字而不是文件名。实际上,使类名
和文件名相同就不会出现这个错误了。
问题二:注释器不能找到其中一个类
解决方法:
确保你指定的是类名而不是类的文件名。
如果对CLASSPATH环境变量有进行设置,要重新复位。
如果类在包中,要确保它们处在正确的子目录中。
确保你从.class文件所在的目录中调用这个注释器。
问题三:程序不能工作?究竟出了什么错误?
以下是JAVA新手犯的公共错误,注意以下的各条:
你是否忘记在在switch语句中的每一个case语句使用break?
你是否在应该使用比较运算符号==的时候使用了赋值运算符=?
在循环语句中的终止条件是否正确?确保你没有过早或者过迟终止循环。也就是说,确保正确使用< 或<=或 >或 >= a运算符。
记住数组的索引是从0开始的,因此数组的循环应该是:
for (int i = 0; i < array.length; i++)
. . .
你是否在比较浮点型数使用了==?大于号和小于号(>和<)运算符在对浮点数的条件逻辑中更合适。
你是否对封装、继承或者其它面向对象编程和设计概念理解有问题?
确保语句块圈在大括号{和}中间。下面的代码块看起来好象是对的,因为它采用缩进的编写,但是你仔细看这里缺少了{ }:
for (int i = 0; i < arrayOfInts.length; i++)
arrayOfInts[i] = i;
System.out.println("[i] = " + arrayOfInts[i]);
你是否正确使用条件运算符号?要确保理解&& 和 ||以及正确使用它们。
你是否使用了否定运算符(!)?尽量不要使用它。这样会减少错误的发生。
你是否使用了do-while语句。如果有,你知道do-while语句至少执行一次吗?它跟while循环语句不一样的,它可以连一次都不执行。
你是否想从方法中改变参数的数值?在JAVA中的参数是由参数来传递的,它不能在方法中改变。
你是否无意地增加一个分号(;)来过早终止语句?比如:
for (int i = 0; i < arrayOfInts.length; i++) ;
arrayOfInts[i] = i
<淘宝热门商品:
 | 278.00 元 拍趣-拍你喜欢 享受乐趣 3皇冠 大遥控 灿凌RMBOX368(高清DVD/RMVB硬盘播放器) AOK
|
|
|
来源: 程序员网
一:Jini白皮书什么是Jini?
Jini是Sun公司的研究与开发项目,它能极大扩展Java技术的能力。Jini技术可使范围广泛的多种硬件和软件---即可与网络相连的任何实体---能够自主联网。
Jini可以使人们极其简单地使用网络设备和网络服务,就象今天我们使用电话一样---通过网络拨号即插即用。Jini的目标是最大限度地简化与网络的交互性。
Jini利用了Java技术的优势。Jini包含了少量类库格式的Java代码和某些惯例,可在网络上创建一个Java虚拟机的"王国",就象我们人类创造一个社区一样。在这个王国里的人、设备、数据和应用程序等网络公民均被动态地连接起来,从而能够共享信息和执行任务。
主要趋势---网络的普及这个世界正在网络化。例如,在今天,一个企业要想取得成功就必须建立网络。商业网络正在不断扩大,而且已经能够与供应商和客户实现直接交互。与无线网络的交互也几乎成为家常便饭。企业和消费者都要求能与网络进行更广泛的交流。出差在外的人无不希望在到达饭店后就能把自己的计算机插入网络接口,不但能与自己单位的工作环境进行交互工作,而且还能与饭店的本地服务,如打印机或传真机等进行交互工作。父母可能希望只需使用移动电话或笔记本电脑就能与家里的摄像机相连,通过它来察看家里的情况。人们无不希望随时随地能够连接和立即使用本地的定制服务。在不远的将来,我们将看到网络渗透到很多其它环境。例如,将会出现把电视机和立体声设备等音频/视频设备与家庭办公室的电脑和外设连接起来的网络,并控制安全监视器和温控恒温器等网络设备。电缆和ASDL等高带宽媒介将为家庭提供全新的服务。服务供应商不断为驾驶员提供越来越多的服务,网络也必将随之进入汽车领域。除导航系统外,游览景点和当地餐馆名单等本地服务也将出现在驾驶员的屏幕上。只要汽车与远程诊断设备相连,它就能自动完成对汽车的维护,并在汽车出现问题时通知驾驶员。
商业机遇---网络服务Jini所能带来的商业机遇是新型的网络服务。
例如,产品制造商将在基于网络的产品上提供新的服务。例如,磁盘可被看作与网络相连的存储服务,能向磁带和其它新型服务提供自动存储备份。联网的摄像机可能将提供诸如安全监视等新型成像服务。这些新的服务使制造商成为新型的网络服务供应商。
Jini还能帮助传统的服务供应商提供新型服务。
例如,某媒体服务供应商可能希望向某消费者的家庭打印机提供报纸打印服务。无线服务供应商可能希望通过蜂窝电话提供相似的服务。
Jini还可简化对现有服务的管理。
在隔天交货的情况里,Jini简化了分布在各处的工人与网络连通的方式。在个人银行里,基于Jini的计算机和外设可简化分行的系统管理。对于无线服务供应商,Jini可使蜂窝电话具备类似于电话的网络功能:屏幕大小、处理能力、使所提供的服务根据每一部电话的特点而专门设计。
问题是,在今天的环境中,联网还是太复杂了。例如,无论是把PC连接到网络上,还是使用联网的打印机都非常复杂。只有经验丰富的系统管理员才有能力处理装载驱动程序、设置配置文件等复杂的工作。显然,我们不可能指望一般消费者也能管理今天这样复杂的网络。
今天的网络还很脆弱和很不灵活。对网络稍加改动就可能造成不可挽救的大混乱。向网络中添加诸如磁盘存储等功能的过程也很复杂。例如,要想添加一个磁盘驱动器,我们就必须打开机箱,处理设置跳线器,并解决一系列复杂的设置问题。即使专家也会头疼。
实际上,从消费者的角度看,他们所需要的只不过是把硬件和软件插入联网的环境,并立即就能使用可用的服务:就象我们今天插接电话一样。在今天,当消费者从商店购买一部电话后,他不必对电话进行配置。消费者只需给电话服务供应商打一个电话,服务就会送上门。最后,消费者只需把电话插好,就能使用电话服务了。自主的联网。
Jini的价值Jini的作用就是能简化与网络的交互性。
从消费者的角度看,消费者把可插接的设备和软件插入网络,就像今天插接一部电话一样简单。
从传统服务供应商的角度看,Jini简化了Services Delivery (服务提供)的管理。设备不但能向网络推出增值服务,而且还能提供设备的属性和功能。现在,服务供应商可以针对每台设备设计服务。当然,Jini还将有可能打开一扇通向新的网络化服务的大门。
从产品制造商的角度看,Jini打开了全新的市场。因为Jini简化了设备向网络提供增值服务的能力。所以,产品就不仅仅作为商品而投入竞争,而是作为增值服务的产品参与竞争。
从Java程序员的角度看,Jini简化了编写分布式应用程序的工作,因而,任何Java程序员都能利用基于Jini的新设备编写应用程序和服务。因此,企业不再需要聘用有限的专家资源编写分布式应用程序,任何Java程序员都能为基于Jini的网络开发服务。
Jini的起源Bill Joy在1994年之前向Sun公司实验室提交了一份包括以下三个主要概念的建议书:
可在所有平台上运行的语言运行该语言的虚拟机,和允许分布式虚拟机像单一系统那样工作的网络化系统到1995年,这种语言和虚拟机相继面市,即Java编程语言和Java虚拟机。但该系统的概念则仍保留在Sun公司的研究与开发实验室,作进一步的研究和开发。这个系统的概念就是Jini。
Jini战略部署与合作伙伴Sun公司部署了广泛的战略,力求将Jini推向市场。我们可以这样说,Jini与任何向网络化环境提供产品和/或服务的企业都密切相关。这包括传统的设备制造商、服务供应商和软件开发商。
Jini将如何进行授权?
为推动Jini的进一步创新,使其尽快被市场所接受,Jini源代码将象Netscape公司的Mozilla模型一样向所有开发商公开。为确保兼容性和质量,正在考虑对商业产品进行标记。围绕授权方式的很多具体细节目前仍在最后确定过程之中。拟议中的授权草案将于今年8月公布。
Jini技术概述
Jini技术可划分为两个范畴:体系结构和分布式编程。此外,还将提供在Jini上运行的网络服务。
基础结构
Jini基础结构解决设备和软件如何与网络连接并进行注册等基本问题。
基础结构的第一种要素称作Discovery and Join (发现与联合)。Discovery and Join解决设备和应用程序在对网络一无所知的情况下如何向网络进行首次注册这样的难题。
基础结构的第二个要素是Lookup (搜索)。Lookup可被看作网络中所有服务的公告板。
Network Services ---网络服务Other Services ---其它服务Leasing ---租用Transactions ---交易Distributed Event---分布式事件Other OS ---其它操作系统Other CPU ---其它CPU DISCOVERY AND JOIN 设备或应用程序插入网络后需要完成的第一个任务就是发现该网络,并使网络发现该设备或应用程序。我们之所以使用Discovery and Join这样的说法,是因为设备或应用程序事前不可能对网络有任何了解。
Discovery的工作原理如下:
当基于Jini的设备插入网络后,它就通过一个众所周知的端口向网络发送一个512字节的多路广播Discovery包。在其它信息中,该包包含对自己的引用。
Jini Lookup在众所周知的端口上进行监听。当接收到Discovery包后,Lookup就利用该设备的接口将Lookup的接口传递回插接的设备或应用程序。
现在,该设备或应用程序已经发现了该网络,并准备将其所有特性上载到Jini Lookup。上载特性是Discovery and Join中Join这方面的特性。
现在该设备或应用程序使用在Discovery阶段所接收到的Lookup接口与网络相连。上载到Lookup的特性包括该设备或应用程序所提供的所有增值服务(如驱动程序、帮助向导、属性等)。
LookupLookup是网络上所有服务的网络公告板。Lookup不但存储着指向网络上服务的指针,而且还存储着这些服务的代码和/或代码指针。
例如,当打印机向Lookup注册时,打印机将打印机驱动程序或驱动程序接口上载到Lookup。当客户机需要使用打印机时,该驱动程序和驱动程序接口就会从Lookup下载到客户机。这样,就不必事先把驱动程序装载到客户机上。
打印机还可能把其它增值服务装载入Lookup。例如,打印机可能存储关于自己的属性(如它是否支持postscript,或它是否为彩色打印机)。打印机还可能存储可在客户机上运行的帮助向导。
如果网络上没有Lookup,则网络就会使用一个Peer Lookup (对等Lookup )程序。当需要服务的客户机在网络上找不到Lookup时,Peer Lookup就开始工作。在这种情况下,客户机可发送与Lookup所用的相同的Discovery and Join包,并要求任何服务供应商进行注册。随后,服务供应商就会在客户机上注册,尽管那不是Lookup。
分布式编程Jini分布式编程为Java增添了创建分布式系统所必需的其它功能。尤其是Jini分布式编程可提供租用、分布式交易和分布式事件。
租用租用与租用一套公寓很类似。我们在租用一套公寓时,一般会商定使用该公寓的时间。类似地,在Jini中,对象彼此之间商定租期。例如,当某设备使用Discovery and Join协议发现网络时,它就注册一段租用时间。在租约到期之前,该设备必须重新商定租期。这样,如果租约到期或设备拔下后,该设备在Lookup中的记录就会被自动删除。这就是分布式垃圾收集的工作原理。
分布式事件在单一的计算机中,事件肯定能被接收方接收到,序列也肯定能按照顺序进行。
但在分布式环境中,分布的事件可能不是按照顺序被接收,或者,某个事件还可能丢失。
为便于在Java环境中处理分布的事件,Jini为分布的事件提供了一个简单的Java API。例如,当一个分布的事件发生时,该事件都带有一个事件号和序列号。利用这种信息,接收方就能检查事件是否丢失(序列号丢失)或事件是否按照顺序接收(序列号顺序不对)到。
分布式交易在分布式Java环境中,有时需要一种很简便的方法,来确保在整个交易完成之前,在该交易中发生的所有事件都被真正提交了(两阶段提交)。
为便于进行此类分布式计算,Jini提供了一种简单的Java API。该API可使对象起动一个能管理交易的交易管理器。每个参与交易的对象都向交易管理器注册。
当交易发生时,如果某个参与的对象说,交易中的某个事件没有发生,则此信息就被送回交易管理器。随后,交易管理器就告诉所有参与的对象回滚(rool back)到前一个已知状态。类似地,如果所有对象都完成了其交易的过程,则整个交易就向前进行。
Jini上的网络服务在Jini基础结构和分布式编程之上,可提供便于分布式计算的网络服务。JavaSpace就是这样的一种网络服务。
欲知有关JavaSpace的详细情况,请访问http://java.sun.com/products/javaspace我们期待着将来在Jini上建立更多其它的网络服务。
欲知有关Jini技术的详细情况,请访问http://java.sun.com/products/jini
<淘宝热门商品:
|
|  | 24.00 元 輝縂、QQ业務连鎖店 官方秒开QQ会员QQ紫钻QQ黄钻QQ红钻QQ蓝钻QQ粉钻8元/月
|
|
来源: 程序员网
熟悉JSP服务器
本“JSP由浅入深” 系列教程是面向中级和高级用户的,它需要HTML和Java的基础。你应该会将HTML网页连接到一起,并且会利用Java来进行编程。如果你还没有这个基础,建议你还是先打好基础为好。这个系列教程将通过编制简单的例子到复杂的例子来教会你JSP。本系列教程是采用循序渐进的方法来进行阐述的,即由浅入深。为了使你能够获得最大的进步,建议你再学习的过程中将所有的例子自己进行调试。开始的例子可能会很简单,所以开始的时候你要特别耐心,不要认为太简单而跳过。如果你仔细地调试例子,那么你就会很快地熟悉JSP的本质方法。
好吧,开始我们的第一个教程:熟悉JSP服务器。
如果你没有一个JSP网络服务器,那么你在开始教程之前还是先下载它吧。以下的几个服务器可以免费下载或者进行开发:
Blazix (1.5 Megabytes, JSP, Servlets and EJBs)
来自www.blazix.com/blazix.html
ServletExec (3.8 Megabytes, JSP and Servlets)
来自www.unifyeware.com/servletExec/
JRun (11 Megabytes, JSP, Servlets and EJBs)
来自www.jrun.com/
WebLogic(44 Megabytes, JSP, Servlets and EJBs)
来自www.beasys.com/
WebSphere (105 Megabytes, JSP, Servlets and EJBs)
来自www-4.ibm.com/sofeware/webservers/
如果你还没有服务器,那我建议你下载Blazix,因为它包含了标签库(可以用于以后关于标签库的教程)。Blazix同样也是很小的并且它可以很容易地下载,而且可以运行于所有的操作系统,包括处于主流的Windows98。还有一个优点,就是它的安装的速度更块。
为了真正学习JSP,最重要的是,你要在一个真实的服务器来调试教程的例子。最好的方法是通过自己的实践来学习JSP的技巧。如果你现在还没有服务器,那就先下载一个安装它就行了。
装上网络服务器以后,你应该学会以下关于网络服务器的的一些知识:应该在哪里放置文件?怎样访问来自浏览器的文件(是以http:开头的,而不是file:开头)?
你首先要创建以下的简单文件,比如:
< HTML>
< BODY>
Hello, world
< /BODY>
< /HTML>
怎样放置文件并在浏览器(以http://)中浏览它,这个步骤对应不同的网络服务器是不同的,所以你需要参看网络服务器的文档并找出答案。
<淘宝热门商品:
来源: 程序员网
将你的对象分开放置
使一个应用程序中的对象相互区分的好方法是确保对象的实际实现部分与你的主程序--即包含了main()方法的类是分离的。为一个目的创建一个类然后在那个类里塞进一个main()方法会使得人们很难找到你的应用程序的入口。
main()方法应该被封装进一个属于它自己的类中去,而main()函数要使用的任何其它的对象都应该在它们自己的类里。例如,一个使用Queue(队列)的应用程序看起来应该象表A一样。
我并不是说创建一个单一的类,里面包括了main()方法和Queue的实现是不对的。我只是说这样分开以后能够让其它的开发者更容易明白类Queue就是一个队列,再没有别的东西了。
表 A
public class Queue { //实现一个队列抽象数据结构. }
class MainQueue { //使用这个对象的main函数所在的类
public static void main(String[] args)
{
Queue q = new Queue(); //创建一个队列
//其它工作
}
}
<淘宝热门商品:
来源: 程序员网
基本技术:
在Java中实现动画有很多种办法,但它们实现的基本原理是一样的,即在
屏幕上画出一系列的帧来造成运动的感觉。
我们先构造一个程序的框架,再慢慢扩展,使之功能比较齐备。
使用线程:
为了每秒中多次更新屏幕,必须创建一个线程来实现动画的循环,这个循环
要跟踪当前帧并响应周期性的屏幕更新要求。实现线程的方法有两种,你可以创建
一个类Thread的派生类,或附和在一个Runnable的界面上。
一个容易犯的错误是将动画循环放在paint()中,这样占据了主AWT线程,而
主线程将负责所有的绘图和事件处理。
一个框架applet如下:
public
class Animator1 extends java.applet.Applet implements Runnable {
int frame;
int delay;
Thread animator;
public void init() {
String str = getParameter("fps");
int fps = (str != null) ? Integer.parseInt(str) : 10;
delay = (fps > 0) ? (1000 / fps) : 100;
}
public vois start() {
animator = new Thread(this);
animator.start();
}
public void run() {
while (Thread.currentThread() == animator) {
repaint();
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
break;
}
frame++;
}
}
public void stop() {
animator = null;
}
}
在你的HTML文件中这样引用:
applet code=Animator1.class width=200 height=200>
/applet
上面的参数fps表示每秒的帧数
保持恒定的帧速度:
上例中,applet只是在每两帧之间休眠一个固定的时间,但这有些缺点,有时
你会等很长时间,为了每秒显示十帧图象,不应该休眠100毫秒,因为在运行
当中也耗费了时间。
这里有一个简单的补救方法:
public void run() {
long tm = System.currentTimeMillis();
while (Thread.currentThread() == animator) {
repaint();
try {
tm += delay;
Thread.sleep(Math.max(0,tm -
System.currentTimeMillis()));
} catch (InterruptedException e) {
break;
}
frame++;
}
}
Java图像处理技术之一
Java图像处理技术之二
Java图像处理技术之三
Java图像处理技术之四
<淘宝热门商品:
来源: 程序员网
画出每一帧:
剩下的就是将每一帧图象绘出。在上例中调用了applet的repaint()
来绘出每一帧图象。
public void paint(Graphics g) {
g.setColor(Color.black);
g.drawString("Frame " + frame, 0, 30);
}
生成图形:
现在我们来画一些稍微困难的东西。下例画了一个正弦曲线的组合,
对于每一个x,画一条短的垂直线,所有这些线组成了一个图形,并且每帧变化。
但不幸有些闪动,在以后我们将解释为什么闪以及怎样避免。
public void paint(Graphics g) {
Dimension d = size();
int h = d.height / 2;
for (int x = 0 ; x < d.width; x++) {
int y1 = (int)((1.0 + Math.sin((x - frame)*0.05))*h);
int y2 = (int)((1.0 + math.sin((x + frame)*0.05))*h);
g.DrawLine(x, y1, x, y2);
}
}
避免闪烁:
上例中的闪烁有两个原因:绘制每一帧花费的时间太长(因为重绘时要
求的计算量大),二是在每次调用pait()前整个背景被清除,当在进行下一帧的
计算时,用户看到的是背景。
清除背景和绘制图形间的短暂时间被用户看见,就是闪烁。在有些平台
如PC机上闪烁比在X Window上明显,这是因为X Window的图象被缓存过,使得闪烁
的时间比较短。
有两种办法可以明显地减弱闪烁:重载update()或使用双缓冲。
重载update()?
当AWT接收到一个applet的重绘请求时,它就调用applet的update()。
缺省地,update()清除applet的背景,然后调用paint()。重载update(),将以前
在paint()中的绘图代码包含在update()中,从而避免每次重绘时将整个区域
清除。
既然背景不在自动清除,我们需要自己在update()中完成。我们在绘制
新的线之前独自将竖线擦除,完全消除了闪烁。
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
Color bg = getBackground();
Dimension d = size();
int h = d.height / 2;
for (int x = 0; x < d.width; x++) {
int y1 = (int)((1.0 + Math.sin((x - frame)*0.05))*h);
int y2 = (int)((1.0 + Math.sin((x + frame)*0.05))*h);
if (y1 > y2) {
int t = y1;
y1 = y2;
y2 = t;
}
g.setColor(bg);
g.drawLine(x, 0, x, y1);
g.drawLine(x, y2, x, d.height);
g.setColor(Color.black);
g.drawLine(x, y1, x, y2);
}
}
Java图像处理技术之一
Java图像处理技术之二
Java图像处理技术之三
Java图像处理技术之四
<淘宝热门商品:
来源: 程序员网
|