posts - 9, comments - 5, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2007年11月10日

  随着Internet网络的迅速发展,基于互联网的企业应用要求软件平台具有开放性、分布性和平台无关性。于是就相继出现了RPC/COM/CORBA等技术,但这些技术在实际应用中存在着许多不足和局限。它们的特定协议难以通过防火墙,因而不适于Web上的应用开发。为了进一步开发基于Web的应用,出现了Sun公司的Sun ONE(Open Net Environment 开发网络环境)和Microsoft公司的.NET等Web 服务技术体系。
  Sun ONE体系结构以Java语言为核心,包括J2SE/J2EE/J2ME和一系列的标准、技术及协议。它包括Sun独有的iPlanet软件系列,其中有在市场上受欢迎的LDAP目录服务器软件,以及Forte for Java——便于在任何环境下书写Java 语言的软件工具。我们很容易就能从网上免费获得和使用包括Java 集成开发环境、Java数据库和中间件(Application Server)服务器等产品,以及它们的源代码。Sun ONE更接近或能满足互联网在智能化Web服务方面对分布性、开发性和平台无关性的要求。

 随着Java技术的不断发展,它根据市场进一步细分为:针对企业网应用的J2EE(Java 2 Enterprise Edition)、针对普通PC应用的J2SE(Java 2 Standard Edition)和针对嵌入式设备及消费类电器的J2ME(Java 2 Micro Edition)三个版本。本文就Sun ONE的Java核心应用——J2SE/J2EE/J2ME作一些介绍。

J2EE技术应用

 J2EE是Sun公司推出的一种全新概念的模型,比传统的互联网应用程序模型更有优势。

J2EE模型

 J2EE的应用编程模型(J2EE Blueprints)提供了一种用于实施基于J2EE多层应用的文档和实例套件的体系模型,简化了这项复杂的工作。它被开发人员用作设计和优化组件,以便开发人员从策略上对开发工作进行分工。

 J2EE应用编程模型要求开发者将自己的工作分成两类:商业逻辑和表示逻辑,其余则由系统资源自动处理,不必为中间层管道进行编码。这样,开发人员就能将更多的时间花在商业逻辑和表示逻辑上。对重视缩短项目周期的公司来说,这种转变深受欢迎。

J2EE平台

 J2EE平台是运行J2EE应用的标准环境,由J2EE部署规范(一套所有J2EE平台产品都必须支持的标准)、IETF标准集和CORBA标准组成。最新的J2EE平台还添加了JavaBean组件模型。开发人员可以利用JavaBean组件模型来自定义Java类实例,并可通过已定义的事件访问Java类。

 J2EE支持EJB,因此开发人员可以执行多用户交易功能。当在J2EE服务器上运行时,Enterprise JavaBeans将应用逻辑分成可再利用和可扩展的代码段。Enterprise JavaBeans并不是新特征,但是通过定义标准客户端和服务API,J2EE增强了它的能力和可移植性。

 EJB在服务器的一个容器内运行,提供所有典型的中间层服务,如事务管理、安全、远程客户连接、生存周期管理和数据库连接缓冲。为了让事务系统在存在EJB容器的情况下运行,开发人员只需在部署描述文件中定义Beans的事务属性即可。

 J2EE通过定义一组标准的结构来实现它的优势,例如:

 1.J2EE Application Programming Model,是一种用于开发多层次、瘦型客户用户程序的标准设计模型;

 2. J2EE Platform,是一个标准的平台,用来整合J2EE的应用程序,并指定一系列的接口和方法;

 3. J2EE Compatibility Test Suite,是一套兼容测试组件,用来检测产品是否同J2EE平台兼容;

 4.J2EE Reference Implementation,用来示范J2EE的能力。

J2EE服务器

 Sun的J2EE服务器通过Java 命名和目录接口(JNDI)、认证、HTTP及与Enterprise JavaBeans兼容的能力,提供命名和目录服务。JNDI是Java平台的一种标准扩展版,向企业内的命名和目录服务提供具有Java功能的,带有统一接口的应用,包括LDAP。

 J2EE服务器还利用了Java Servlet技术。Java Servlet可以看作是运行在服务器上的一个小程序,它向开发人员提供以组件为基础创建基于Web应用的、独立于平台的方法。它不像利用CGI那样具有性能局限。Java Servlet是一种扩展Web服务器功能的简单技巧。由于它是用Java编写的,因而能够访问整个Java API库,也包括用于访问企业数据库的JDBC API。

 JSP是Java Servlet的一种扩展。Java Servlet提供开发和显示来自服务器的交互式Web页。如今JSP又有了进一步的改进,它使得创建和支持静态模板和动态内容相结合的HTML和XML页面更加容易。

安全性

 J2EE平台定义了一种标准的公开存取控制规则,当程序在企业平台上开发时就已被程序师定义和解释了。J2EE也需要提供一个标准的注册机制,以便应用程序不会将这些注册机制和逻辑相混合,从而使相同的工作执行于大量的不同环境中时并不需要改变源代码。例如:J2EE应用程序开发人员可以指定几个安全级别,当用户访问数据时,他们可写出代码来检查当前用户权限的级别。在开发阶段,开发人员赋予多组用户适当的安全级,使应用程序在执行限制操作之前能够容易的判断限制级。

 J2EE 平台是Java技术企业级应用的最佳平台,它可以让程序员迅速、快捷地开发和分布企业级应应用程序。以下便是它的相关技术:

 1.Enterprise JavaBeans Architecture,企业级JavaBeans 定义了一个应用程序接口。它可以使程序员迅速开发、发布和管理跨平台的、基于组件的企业级应用程序。

 2.JavaServer Pages,JSP 技术提供了一种简单、快速的方法来创建动态网页。通过它,可以快速地开发基于Web的应用程序,并且这些应用程序都是与平台无关的。因为JSP与ASP很相似,所以熟悉ASP的人学习它就很容易了。

 3.Java Servlet,提供了应用程序接口。通过它可以简单快速地开发并扩展服务器功能。就发展趋势来看,它将来有可能取代CGI。

 4.J2EE Connector,提供了一种标准结构来联接不同的企业信息平台。

 5.Java Naming and Directory Interface(JNDI),在Java 平台与商业信息之间,JNDI提供了统一、无缝的标准化连接。通过使用JNDI,程序员可以在企业多命名与目录服务之间传送Java 应用程序。

 6.Java Interface Definition Language(JIDL),通过使用CORBA,可以提供协同工作的能力。JIDL包括一个IDL-to-Java 编译器和支持IIOP(Internet Inter-Orb Protocol)的ORB。

 7.JDBC,几乎是为所有的数据库提供了统一的接口,同时可以创建高级工具和接口。

 8.Java Message Service(JMS),它几乎规范了所有企业级消息服务,如可靠查询、发布消息、订阅杂志等各种各样的PUSS/PULL技术的应用,并且为它们提供了一个标准接口。

 9.Java Transaction API(JTA),为分布式系统中可处理的应用程序规定了一个高级的管理规范。

 10.JavaMail,JavaMail应用程序接口提供了一整套模拟邮件系统的抽象类。通过JavaMail,可以创建邮件或消息应用程序。

 11.RMI-IIOP,使用它就可以只用Java 技术和Java RMI接口开发客户机与服务器的远程接口。

 J2EE使用固定的文件格式捆绑某个模块:用.ear文件捆绑J2EE应用程序;用.jar捆绑Enterprise Bean。例如,一个.ear文件包含一个.xml文件作为其分布描述,还包含一个或多个.jar和.war文件;一个.jar文件除了包含它的分布描述外,还包含了作为Enterprise bean的.class文件。

 J2EE应用程序的开发阶段分为四步:1.Enterprise Bean创建;2.Web Component创建;3.J2EE应用程序装配;4.J2EE应用程序分布。以下是J2EE兼容产品部分列表:

 BEA WebLogic Server 6.0、Borland App Server、HP Bluestone Total-e-Server、IBM WebSphere Application Server、IONA iPortal Application Server、iPlanet Application Server、Macromedia JRun Server、Oracle 9i Application Server、SilverStrean Application Server、Sybase EAServer、TogetherSoft ControlCenter、Java 2 SDK Enterprise Edition。

J2ME技术的应用

 J2ME(Java 2 Platform Micro Edition)是为无线电子市场所设计的,包括JVM规范和API规范。其API规范是基于J2SE(Java 2 Standard Editon)的。J2ME 定义了一套合适的类库和虚拟机技术。这些技术可以使用户、服务提供商和设备制造商通过物理(有线)连接或无线连接,按照需要随时使用丰富的应用程序。

 J2ME又被称为Java 2 微型版,被使用在各种各样的消费电子产品上,例如智能卡、手机、PDA、电视机顶盒等方面。当然了,J2ME也提供了Java语言一贯的特性,那就是跨平台和安全网络传输。它使用了一系列更小的包,而且Javax.microedition.io 为J2SE包的子集。J2ME可以升级到J2SE和J2EE。

 在J2ME出现之前,我们更多接触到的是Java卡(Java Card)、嵌入式Java(Embedded Java)和实时Java(Real Time Java)等。其中Java卡是针对SIM卡、智能卡等设备而定制的最小Java子集,比J2ME还要小,移植性也不强。嵌入式Java则针对特殊用户自行配置Java类库和VM(Virtual Machine,虚拟机)。它对资源需求极小,可运行在无图形用户接口和网络的设备上,可以添加用户专用的API,但是它就无法移植。实时Java是由IBM领导的实时定制Java专家组负责实施的,现在还在不断完善中。不过,从严格意义上来说,它们都不是真正的J2ME。

 像其它版本一样,J2ME具有很多Java技术特性,主要有:

 1.可以在各种支持Java的设备上运行;

 2.代码短小;

 3.充分利用Java语言的优势;

 4.安全性好;

 5.用J2ME实现的应用可以方便地升级到J2SE、J2EE。

J2ME的配置和框架

 为了支持用户和嵌入式市场提出的灵活性和可定制性要求,J2ME被设计得更加模块化和可缩放化。J2ME在设备原有的操作系统上建造了3层软件来实现这种要求:

 1.JVM层,这层基于宿主操作系统,按照某一种J2ME的配置,实现了JVM。

 2.配置层,这层对于用户可见度要低一些,但对框架层非常重要。它针对“水平”市场的需求,定义了Java虚拟机的最小功能集和Java类库的最小集合。在某种意义上,配置层定义了开发者在所有设备上都可以使用Java特性和类库的“最小公分母”。

 3.框架层,这层对于用户和应用程序提供者来说是最常见的。它针对“垂直”市场的需求,定义了Java虚拟机的最小功能集和Java类库的最小集合。其框架是基于特定的配置层实现的。只要设备支持相同的框架层,针对特定框架层开发的应用程序就可以移植到其它设备上。一个设备可以支持多个框架层。

 在J2ME设备中,JVM与配置层紧密相连,它们体现了每一类设备的基本功能。框架层针对不同的设备,在配置层的基础上规定了附加的API。为了满足不断更新的应用程序,框架层可以扩充新的Java库类。在不远的将来,随着新设备的不断出现,J2ME技术将提供范围广泛的框架层、配置层和VM。JCP(Java Community Process)可以为客户和开发商提供规范。根据JCP的定义,J2ME目前的一种配置层是“面向连接的设备配置”层(Connected Device Configuration),它采用典型的Java虚拟机技术。这种全功能的VM包含了基于台式机系统上的虚拟机的所有功能,适用于拥有至少几兆字节内存的设备。对于无线设备和其它内存不足的设备,J2ME采用“面向连接的受限设备配置”(CLDC)技术。

 KVM是J2ME的核心特征。它是一个可移植性非常高的JVM,专用于内存小、资源有限、能上网的设备,例如蜂窝电话、寻呼机和个人组织器等。这些器件一般都含有16或32位的处理器,最低128KB内存。KVM能够被灵活应用到各种行业、各种类型的设备上,并能够适应这些设备的多样化所带来的问题,比如处理器的耗电量、内存的大小、设备和应用程序的特殊功能等问题。

CLDC技术

 CLDC定义了目标Java平台,该平台基于小型的、资源较少的、内存仅有160~512K的设备。CLDC是由KVM和用在蜂窝电话、数字产品、双向寻呼机、个人组织器和家用电器等核心库类及接口组成。使用CLDC技术有很多优点:

 1.跨平台,这点保留了Java一贯的特点,应用程序不会随着平台差异而产生变化。

 2.动态性,这点也是很吸引人的,可以根据需要下载自己喜欢的应用程序和服务,并且可以和其它的CLDC设备通信。

 3.安全性,Java 本身的特点造就了这一特性。

 与 J2SE相比,CLDC缺少下列所说的特征:

 1.AWT(抽象窗口开发包),Swing或其它图形库;

 2.用户定义类装载器;

 3.类实例的最终化;

 4.弱的引用;

 5.RMI;

 6.Reflection(映射)。

 CLDC有四个包:java.lang、java.util、java.io和javax.microedition。除了javax.microedition包以外,其它的几个包都是J2SE包的核心子集。CLDC采用这些J2SE类库,但是把其中一些在微型设备中用不到类、属性和方法去掉了。

 J2ME定义两个配置:Connected Device Configuration(连接设备配置,CDC)和限制性更强的Connected Limited Device Configuration(有限连接设备配置,CLDC)。

J2SE技术的应用

 Java 2标准版是一种开发和部署平台,提供了编写桌面、工作站应用程序所有必需的功能。J2SE软件是快速开发、部署关键任务和企业应用程序的首选解决方案。J2SE 1.4版本是基于Java跨平台技术和强有力的安全模块而开发的,其最新的特征和功能极大地提高了Java语言的伸缩性、灵活性、适用性,以及可靠性。

 J2SE 1.4 特点:

 1.良好的计算性能和缩放能力。

 J2SE 1.4版是一个快速开发和配置跨平台的企业级应用与服务的综合性平台。它提升了Java计算的性能与缩放能力,代表了Java技术的大跨步进展。有了J2SE 1.4版,企业就可以通过更简易的步骤、花费更少的时间,采用Java技术开发与配置要求更高的应用了。J2SE 1.4版在Java客户机应用方面得到了重大性能提升。基于Swing的Java小程序和应用程序在图形用户界面(GUI)的响应速度上也大有提高。

 2.跨平台

 J2SE 1.4版是一个具有综合性能的平台,能使一个完整的、可缩放的高性能应用配置在任何种类的平台上。

 3.支持Web服务

 J2SE 1.4版与以前各J2SE版全面兼容。J2SE 1.4版对SSL、LDAP和CORBA等业界标准技术也给予支持,因此保证了在不同平台、系统和环境间的互操作能力。J2SE 1.4版支持XML技术和一整套安全服务,因此为基于各类标准的可互操作应用与服务的创建奠定了重要基础。有了J2SE 1.4版与Java Web Services Developer Pack的结合,开发商就能创建、测试和配置Web服务了。

 4.完整性

 J2SE 1.4版还是一个完整的开发环境。开发商可基于这一环境创建功能丰富的交互式应用。这些应用可以配置在任何平台上。J2SE 1.4具有新的GUI控制功能、快速的Java 2DT图形功能、支持国际化与本地化扩展和新的配置选项,并对Windows XP提供扩展支持。

 总之,J2SE 1.4版是多种不同风格软件的开发基础,包括客户端Java小程序和应用程序,以及独立的服务器应用程序等。J2SE 1.4版还是J2ME的基础,是J2EE执行程序的推动力。

 Java之所以能够发展得很快,是因为互联网的发展非常快。Java可以和浏览器结合在一起,因而很自然地在桌面系统得到广泛应用。从计算的结构来看,Java主要分三大类:第一是服务器端,这里就有了J2EE企业版;第二是桌面PC,这一类用的是J2SE标准版;第三就是掌上电脑、移动设备,用的都是J2ME。但是,大部分非企业级软件还是在J2SE上开发的比较多。首先,这是因为很多的应用软件都是在J2SE上开发的;其次,J2SE是和J2EE兼容的,企业版是在标准版上的扩充,在J2SE的版本上开发的软件,拿到企业的平台上是一样可以运行的;再次,一般开发还是在J2SE的环境上,只是说J2ME提供微型版的一个环境。在J2SE上虚拟出一个环境,开发出来的应用软件是可以拿到微型版上运行的。

posted @ 2007-11-22 13:57 代林 阅读(1403) | 评论 (0)编辑 收藏

ArgoUML

使用java编写的开源UML产品,功能比较全。最受欢迎的UML建模工具。

Alma

Alma是一个软件建模分析的工作平台,它读取几种不同的源代码,帮你设计面向对像的模型,修改结构和源代码,输出新的源代码、文档和图表。

UMLet

UMLet是一个开放源代码轻量级UML建模工具。UMLet能够让你快速建模,并且能够导出各种格式SVG, JPG, PDF and LaTeX-friendly EPS。

UML/Dot

UML/Dot这个项目从Java源代码或字节码中生成UML类。使用GraphViz Dot生成图表。用户可以完全控制处理过程,可以隐藏或显示任意提取的元素。需要:JAVA v1.4 或更高版本,GraphViz。

JUG

Java UML Generator 是用于从Java类文件自动生成UML类图的工具。最初设计为一个命令行工具,将.class/.jar文件转换到.emf/.eps文件,现在它提供了一个可视化环境。

Violet

Violet是一种轻量级的UML建模工具。易学易用 可以快速绘制类图、对象图、时序图和状态图 跨平台 支持中文 源码开放

UMLGraph

UMLGraph支持说明性规约(Declarative Specification),类图(Class Diagram) ,顺序图(Sequence Diagrams).

Fujaba Tool Suite

Fujaba Tool Suite结合UML类图与UML行为视图来提供一个强大,易于使用,而且是整齐均称的系统设计与规范语言. 而且Fujaba Tool Suite还支持从整个系统设计生成Java源代码从完美地实现了一个可执行的模型.同样也支持相反操作,因此源代码可以被解析并被表现在UML中.

UniMod

UniMod是Executable UML思想的实现。UniMod是以Eclipse插件形式存在。可以通过UniMod提供的一个在线Demo了解更多的详细资料。

Taylor MDA

Taylor MDA是一个基于Eclipse的UML建模工具。它专注于EJB3企业应用程序的生成。Taylor MDA当前支持生成:

  • EJB3 Entity Beans
  • EJB3 Stateless Session Beans
  • 利用JBoss内置容器的JUnit Tests
  • Maven Project
  • 以后将支持生成:
  • 用于CRUD Portlets的Seam代码
  • 用于商业处理与页面流(page flows)的jBPM/Seam代码

StarUML

StarUML是一个运行在Win32上快速,灵活,可扩展,功能强大的UML/MDA平台。开源项目StarUML的目的是提供一个可以用来代替知名商业UML工具比如Rational Rose,Together等的建模工具和平台。

Quick Sequence Diagram Editor

这个简单的工具能够利用对像与信息的描述文本来生成UML时序图。它采用Java5开发并打包成一个可执行的Jar文件。

TinyUML

TinyUML是一个能够帮助你快速和轻松地绘制UML2图的开源工具。采用Java5开发。

Papyrus

Papyrus是一个基于Eclipse平台UML2建模工具。遵从Eclipse UML2、支持由OMG规定的UML2标准和DI2 (Diagram Interchange)标准、Papyrus的整个架构是可扩展的允许用户增加新的图样(diagram)和新的代码生成器等、支持UML2 Profile开发、嵌套Profile支持等。

 

posted @ 2007-11-14 10:17 代林 阅读(2869) | 评论 (2)编辑 收藏

Struts 运行环境

1.1 Struts 1.0 和1.1版本

当前主要有两个版本,struts 1.0 release 和 struts 1.1 beta 3。Struts 1.0 和1.1差别很大,主要有两点:

  • Struts 1.1 中引用了很多 apache其他项目的类包,如:xml 解析、日志、验证等,因此struts1.1 的包结构与1.0 完全不同。在struts 1.1环境下,一个webapp 要成功运行,除了struts.jar 外,还需要引用12个包。
  • Struts 1.1 增加了很多新功能,例如,支持sub-applications, 动态FormBean,异常处理,验证,支持Tile templating等。

尽管struts 1.0 是正式发布版,但是结构已经老化,功能也已经固化。所以我们的Framework不选用struts 1.0, 而选用 struts 1.1。

1.2支持struts的应用服务器

根据apache官方网站的说法,struts几乎支持所有的servlet containers, 下面是几种主要的servlet containers

Servlet Container

版本

iPlanet Application Server 6.0sp2 or higher, 6.5
Tomcat 3.2.x, 4.0 or higher
Weblogic 6.0 or higher
Websphere 3.5 or higher
Orion 1.0 or higher
Resin 1.2 or higher
JRun 3.0 or higher

1.3配置说明

我们公司目前项目中使用较多的应用服务器是iPlanet Application Server, Tomcat。Struts 1.1 在这两个应用服务器下已经配置通过。

Tomcat 与struts结合的很好,只需要将xxx.war 放到 webapp 目录下,启动Tomcat 即可,不需要其他额外的配置。

iPlanet 配置复杂一些,主要原因是xml parser 版本不一致,和struts 相关类不能加载。具体的配置说明请见《如何在 iAS 6.x 中配置Struts 1.1 beta x》。

在其他的应用服务器上,还没有尝试struts, 今后根据项目需要会作进一步的研究。

struts框架

2.1 struts 体系结构

struts framework是MVC 模式的体现,下面分别从模型、视图、控制来看看struts的体系结构(Architecture)。下图显示了struts framework的体系结构响应客户请求时,各个部分工作的原理。


Struts体系结构


 

2.1.1 从视图角度(View)

主要由JSP建立,struts自身包含了一组可扩展的自定义标签库(TagLib),可以简化创建用户界面的过程。目前包括:Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags。

2.1.2从模型角度(Model)

模型主要是表示一个系统的状态(有时候,改变系统状态的业务逻辑操作也也划分到模型中)。在Struts中,系统的状态主要有ActiomForm Bean体现,一般情况下,这些状态是非持久性的。如果需要将这些状态转化为持久性数据存储,Struts本身也提供了Utitle包,可以方便的与数据库操作。

2.1.3 从控制器角度(Controller)

在Struts framework中, Controller主要是ActionServlet,但是对于业务逻辑的操作则主要由Action、ActionMapping、ActionForward这几个组件协调完成。其中,Action扮演了真正的业务逻辑的实现者,而ActionMapping和ActionForward则指定了不同业务逻辑或流程的运行方向。

2.2 struts 的组件

框架中所使用的组件:

ActionServlet 控制器
ActionClass 包含事务逻辑
ActionForm 显示模块数据
ActionMapping 帮助控制器将请求映射到操作
ActionForward 用来指示操作转移的对象
ActionError 用来存储和回收错误
Struts标记库 可以减轻开发显示层次的工作

2.3 struts 配置文件

Struts-config.xml集中了所有页面的导航定义。对于WEB项目,通过配置文件可迅速把握其脉络,这不管是对于前期的开发,还是后期的维护或升级都是方便的。掌握Struts-config.xml是掌握Struts的关键所在。

在struts的早先版本中,只有一个struts配置文件struts-config.xml。但是,对大型项目来说,使用和修改这个配置文件,会成为瓶颈。在struts1.1中,支持sub-Application ,可以定义多个配置文件协同工作。

通过struts配置文件struts-config.xml 将struts各个组件联系在一起。在struts-config.xml 中可以定义下面内容:

  • 全局转发
  • ActionMapping类
  • ActionForm bean
  • JDBC数据源

2.3.1 配置全局转发

全局转发用来在JSP页之间创建逻辑名称映射。全局转发的例子:

<global-forwards>

<forwardname="logoff"path="/logoff.do"/>

<forwardname="logon"path="/logon.jsp"/>

<forwardname="registration"path="/registration.jsp"/>

<forwardname="success"path="/mainMenu.jsp"/>

</global-forwards>

属性 描述
Name 全局转发的名字
Path 与目标URL的相对路径

2.3.2 配置ActionMapping

ActionMapping对象帮助进行框架内部的流程控制,它们可将请求URI映射到Action类,并且将Action类与ActionForm bean相关联。ActionServlet在内部使用这些映射,并将控制转移到特定Action类的实例。所有Action类使用perform()或者execute()方法实现特定应用程序代码,返回一个ActionForward对象,其中包括响应转发的目标页面名称。例如:

<action-mappings>

<actionpath="/logon"

type="org.apache.struts.webapp.example.LogonAction"

name="logonForm"

scope="session"

input="logon">

</action>

<forward name="failure" path="/error.jsp"/>

<forward name="success" path="/index.jsp"/>

</ action-mappings>

属性

描述

Path

Action类的相对路径

Name

与本操作关联的Action bean的名称

Type

连接到本映射的Action类的全称(可有包名)

Scope

ActionForm bean的作用域(请求或会话)

Prefix

用来匹配请求参数与bean属性的前缀

Suffix

用来匹配请求参数与bean属性的后缀

attribute

作用域名称。

className

ActionMapping对象的类的完全限定名默认的类是org.apache.struts.action.ActionMapping

input

输入表单的路径,指向bean发生输入错误必须返回的控制

unknown

设为true,操作将被作为所有没有定义的ActionMapping的URI的默认操作

validate

设置为true,则在调用Action对象上的perform()方法前,ActionServlet将调用ActionForm bean的validate()方法来进行输入检查

通过<forward>元素,可以定义资源的逻辑名称,该资源是Action类的响应要转发的目标。

属性 描述
Id ID
ClassName ActionForward类的完全限定名,默认是org.apache.struts.action.ActionForward
Name 操作类访问ActionForward时所用的逻辑名
Path 响应转发的目标资源的路径
redirect 若设置为true,则ActionServlet使用sendRedirect()方法来转发资源

2.3.3 配置ActionForm Bean

ActionServlet使用ActionForm来保存请求的参数,这些bean的属性名称与HTTP请求参数中的名称相对应,控制器将请求参数传递到ActionForm bean的实例,然后将这个实例传送到Action类。例子:

<form

beans >

<form

bean name="bookForm" type="BookForm"/>

</form

beans>

属性

描述

Id

ID

className

ActionForm bean的完全限定名,默认值是org.apache.struts.action.ActionFormBean

Name

表单bean在相关作用域的名称,这个属性用来将bean与ActionMapping进行关联

Type

类的完全限定名

2.3.4 配置JDBC数据源

例子:

<data-sources>

<data-source>

<set-property property="autoCommit"

value="false"/>

<set-property property="description"

value="Example Data Source Configuration"/>

<set-property property="driverClass"

value="org.postgresql.Driver"/>

<set-property property="maxCount"

value="4"/>

<set-property property="minCount"

value="2"/>

<set-property property="password"

value="mypassword"/>

<set-property property="url"

value="jdbc:postgresql://localhost/mydatabase"/>

<set-property property="user"

value="myusername"/>

</data-source>

</data-sources>

属性 描述
description 数据源的描述
autoCommit 数据源创建的连接所使用的默认自动更新数据库模式
driverClass 数据源所使用的类,用来显示JDBC驱动程序接口
loginTimeout 数据库登陆时间的限制,以秒为单位
maxCount 最多能建立的连接数目
minCount 要创建的最少连接数目
password 数据库访问的密码
readOnly 创建只读的连接
User 访问数据库的用户名
url JDBC的URL

通过指定关键字名称,Action类可以访问数据源,比如:

javax.sql.DataSource ds = servlet.findDataSource(“conPool”);

javax.sql.Connection con = ds.getConnection();

struts标记库

struts 标记库包含4种类型的标记,分别是:

  • struts-bean taglib:在访问bean和bean属性时使用的tag,也包含一些消息显示的tag。
  • struts-html taglib:用来生成动态HTML用户界面和窗体的tag。
  • struts-logic taglib :用来管理根据条件生成输出文本,和其它一些用来控制的信息。
  • struts-template taglib:用来定义模板机制。

Struts提供了功能强大的Taglib,充分使用这些Tag,能最大限度的发挥Struts的作用。

由于标记库功能强大,所以掌握它需要花费一定的时间。目前我们可以先从 struts-html taglib 学起,主要精力还是要先放在理解掌握struts导航功能上。

文档《struts 标记库》可以帮助学习掌握struts taglib.

可视化设计工具和代码生成器Camino

Camino 是基于 struts framework的可视化建模工具。使用camino 可以实现快速设计和开发,主要特点有:

  • 支持struts 1.0 和 struts 1.1
  • 通过storyboard , 可视化定义页面导航流程,配置struts-config.xml 文件。
  • Jsp converter wizard 功能可以将普通jsp 转换成带struts-html taglib 的jsp
  • Code Generator wizard 功能可以自动生成 Action 和 FormBean 类的框架。
  • Camin 3.0 还提供了验证器和Preview Jsp 的功能。

目前Camino的版本有2.05 和 3.0, 可以下载试用版。Camino 自带了帮助文档,可以方便学习Camino。

Struts example

Struts 1.1 beta 3 的包中包含了几个example, 可以帮助学习struts。

Web应用程序 描述
Struts-blank.war 一个简单的web应用程序
Struts-documentation.war 包含struts站点上所有struts文档
Struts-example.war Struts很多特性的示范
Struts-exercisetaglib.war 主要用于对自定义标签库进行增加而使用的测试页,但也可以示范如何使用struts标记
Struts-template.war 包含struts模板标记的介绍和范例
Struts-upload.war 一个简单的例子,示范如何使用struts框架上传文件

在Tomcat 4.1.18运行环境下,只需要将 xxx.war 文件放到webapps 目录下,启动Tomcat 即可。

建议从struts-example 开始学习,熟读struts-config.xml, jsp, 和 java 源码。

6、统一的IDE工具: eclipse

Eclipse 是由IBM支持的开发源码的IDE, 目前的最新版本是2.1。与Netbeans, JBuilder相比,由以下特点:

  • 界面设计精细,布局合理,秉承了IBM的风格。
  • 功能齐全,具备了Netbeans, JBuilder(Enterprice fetature 除外)大部分功能,还有一些特有的功能,如:代码历史记录比较、替换,代码重构,自动生成get,set方法, 小组协作方式的版本控制和权限控制。
  • 速度快,执行一个代码格式化(14,000行)的操作,要比Netbeans快百倍以上。
  • 功能强大的plug-in,可以与Ant, JUnit, Tomcat集成。将来我们也可以编写自己的插件,有增强功能的潜力。

目前,每个项目使用的开发工具都不同,有JBuilder, Netbeans等。从长远考虑应该采用开发源码的IDE, 不存在盗版问题。现在开发源码的IDE有Netbeans, Eclipse两大阵营,分别由Sun 和 IBM支持。综合上面的Eclipse特性,我推荐统一使用Eclipse。

7、参考资料

  • 网站:

    struts 官方网站:http://jakarta.apache.org/struts

    struts resource : http://jakarta.apache.org/struts/resources/index.html

    Camino 网站:http://www.scioworks.com/index.html

    其他网站:http://husted.com/struts/

    http://struts.application-servers.com/main.html

    http://www.synthis.com/products/architectures/struts/index.jsp

  • 文章:

    《struts框架详细介绍》 - ppt 文档,描述了struts 框架

    《struts-intro》- ppt 文档,其中的struts 导航流程图非常好。

    《Using Struts》 - ppt 文档,概述了struts 框架和组成

    《如何在 iAS 6.x 中配置Struts 1.1 beta x》- 讲述在iPlanet 6.x 如何配置 struts 1.1

    《Struts标记库》 - 详细介绍了struts taglib的使用

    《struts turorial》 - 一个网上购书的示例,详细讲解了struts使用步骤

posted @ 2007-11-10 17:25 代林 阅读(2136) | 评论 (2)编辑 收藏

2005 年的时候帮人收集整理修改的一份脚本级联菜单, 没用到 AJAX, 写死的数据. 效果自己试试就知道了. 支持主流浏览器. 自己现在看看这代码就觉得头大... 呵呵 脚本就是脚本啊. 一段时间放下就看不懂了.

<HTML>
<HEAD>
<TITLE>合同申请</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<SCRIPT LANGUAGE = JavaScript>
/** Define object Dsy 构造器
fieldValues - 三个表单域的名称, 可以通过 request.getParameter(xxx) 取值
defalutOptions - 默认选项
*/
function Dsy(fieldValues, defalutOptions){
  this.Items = {};
  this.defalutOptions = defalutOptions;// 默认选项 
  this.fieldValues = fieldValues;// 三个表单域的名称
}

Dsy.prototype.add = function(id, iArray){
  this.Items[id] = iArray;
}

Dsy.prototype.Exists = function(id){
  if (typeof(this.Items[id]) == "undefined")
    return false;
  return true;
};

Dsy.prototype.setup = function() {
    this.bean_change(0);
}

// This prototype method added by BeanSoft Studio
Dsy.prototype.bean_change = function(v){
  var str = "0";
  for (i = 0; i < v; i++){
    str += ("_" + (document.getElementById(this.fieldValues[i]).selectedIndex - 1));
  };

  var ss = document.getElementById(this.fieldValues[v]);
  // Avoid a null exception
  if(ss == null) return;

    with(ss){
      length = 0;
      options[0] = new Option(this.defalutOptions[v], this.defalutOptions[v]);
      if (v && document.getElementById(this.fieldValues[v - 1]).selectedIndex > 0 || !v){
        if (this.Exists(str)){
          array = this.Items[str];
          for (i = 0; i < array.length; i++)
            options[length] = new Option(array[i], array[i]);
          if (v)
            options[1].selected = true;
        }
      }

      if (++v < s.length){
        this.bean_change(v);
      }
    }
}

  function change(v){   
    dsy.bean_change(v);// Call test prototype
  }

  // Write form data string, 输出表单脚本代码
  // dsy, object name
  // varName, 变量名
  function toString(dsy, varName) {
    var str = "";
    for(i = 0; i < dsy.fieldValues.length; i++) {
        str += "<select id=\"" + dsy.fieldValues[i] + "\" onChange=\"" + varName + ".bean_change(" + (i + 1)
            + ");\"></select>\r\n";
    }
    str += "<br/>";
    return str;
  }

// 第一个对象
  var dsy = new Dsy(["s1", "s2", "s3"], ["销售方名称", "销售方联系人", "联系电话"]);
  var dsy1 = new Dsy(["s4", "s5", "s6"],  ["最终用户名称", "最终用户联系人", "联系电话"]);
  var dsy2 = new Dsy(s = ["s7", "s8", "s9"], ["厂商", "厂商销售", "联系电话"]);

// 填入数据, 重复的代码
  dsy.add("0", ["单位1", "单位2"]);

  dsy.add("0_0", ["单位1联系人_1", "单位1联系人_2"]);
  dsy.add("0_0_0", ["单位1联系人_1联系电话"]);
  dsy.add("0_0_1", ["单位1联系人_2联系电话"]);

  dsy.add("0_1", ["单位2联系人_1", "单位2联系人_2"]);
  dsy.add("0_1_0", ["单位2联系人_1联系电话"]);
  dsy.add("0_1_1", ["单位2联系人_2联系电话"]);

  dsy1.add("0", ["最终用户1", "最终用户2"]);

  dsy1.add("0_0", ["最终用户1_联系人1", "最终用户1_联系人2"]);
  dsy1.add("0_0_0", ["最终用户1_联系人1_电话"]);
  dsy1.add("0_0_1", ["最终用户1_联系人2_电话"]);

  dsy1.add("0_1", ["最终用户2_联系人1", "最终用户2_联系人2"]);
  dsy1.add("0_1_0", ["最终用户2_联系人1_电话"]);
  dsy1.add("0_1_1", ["最终用户2_联系人2_电话"]);

  dsy2.add("0", ["BEA", "Horizon"]);

  dsy2.add("0_0", ["张学友", "BeanSoft"]);
  dsy2.add("0_0_0", ["1234567890"]);
  dsy2.add("0_0_1", ["beansoft@126.com"]);

  dsy2.add("0_1", ["AAA", "BBB"]);
  dsy2.add("0_1_0", ["AAA_99999"]);
  dsy2.add("0_1_1", ["bbb_88888"]);

  function setup(){  // Initialize the object
    dsy.setup(); //依次调用 setup
    dsy1.setup();
    dsy2.setup();
  }

function prints1(){
    alert(document.frm.s1.value + " " + document.frm.s2.value + " " + document.frm.s3.value +"\r\n");
}

//isNaN()检查运算结果  http://tech.ccidnet.com/pub/article/c1115_a120997_p1.html

</SCRIPT>

</head>
<body bgcolor="#E0E0E0" onload="setup()">
多级关联菜单:
<form name="frm">

<!-- 方式1: 手工输出 HTML 代码, 便于排版
<select id="s1" onChange="dsy.bean_change(1);"></select>
<select id="s2" onChange="dsy.bean_change(2);"></select>
<select id="s3" onChange="dsy.bean_change(3);"></select>
<br>
<br>
<br>
<select id="s4" onChange="dsy1.bean_change(1);"></select>
<select id="s5" onChange="dsy1.bean_change(2);"></select>
<select id="s6" onChange="dsy1.bean_change(3);"></select>
<br>
<br>
<br>
<select id="s7" onChange="dsy2.bean_change(1);"></select>
<select id="s8" onChange="dsy2.bean_change(2);"></select>
<select id="s9" onChange="dsy2.bean_change(3);"></select>
-->
<SCRIPT LANGUAGE="JavaScript">
<!--
// 方式2: 脚本输出表单 HTML 代码, 代码和上面注释掉的类似
document.write(toString(dsy, "dsy"));
document.write(toString(dsy1, "dsy1"));
document.write(toString(dsy2, "dsy2"));
//-->
</SCRIPT>

<input type=button name=b1 value="监测" onclick="prints1()">

</form>

</body>
</html>



BeanSoft 2007-10-22 10:43 发表评论

文章来源:http://www.blogjava.net/beansoft/archive/2007/10/22/154898.html

posted @ 2007-11-10 17:21 代林 阅读(301) | 评论 (0)编辑 收藏

						/*
						 * WebFXCookie class
						 */
						function WebFXCookie() {
    if (document.cookie.length) { this.cookies = ' ' + document.cookie; }
}

WebFXCookie.prototype.setCookie = function (key, value) {
    document.cookie = key + "=" + escape(value);
}

WebFXCookie.prototype.getCookie = function (key) {
    if (this.cookies) {
        var start = this.cookies.indexOf(' ' + key + '=');
        if (start == -1) { returnnull; }
        var end = this.cookies.indexOf(";", start);
        if (end == -1) { end = this.cookies.length; }
        end -= start;
        var cookie = this.cookies.substr(start,end);
        return unescape(cookie.substr(cookie.indexOf('=') + 1, cookie.length - cookie.indexOf('=') + 1));
    }
    else { returnnull; }
}



function getCookieVal (offset) 
{
    var endstr=document.cookie.indexOf (";",offset);if (endstr==-1) 
    endstr=document.cookie.length;return unescape(document.cookie.substring(offset, endstr));
}


function GetCookie (name)
{
    var arg=name+"=";var alen=arg.length;var clen=document.cookie.length;var i = 0;while (i<clen)
    {
        var 
        j=i+alen;if (document.cookie.substring(i,j)==arg) return getCookieVal (j);i = document.cookie.indexOf(" ",i)+1;if (i==0) 
        break;
    } 
    returnnull;
} 
function DeleteCookie (name) 
{
    var exp=new Date(); exp.setTime (exp.getTime()-1); var cval=GetCookie (name); 
    document.cookie=name+"="+cval+"; expires="+exp.toGMTString();
}



BeanSoft 2007-10-26 10:52 发表评论

文章来源:http://www.blogjava.net/beansoft/archive/2007/10/26/156057.html

posted @ 2007-11-10 17:21 代林 阅读(279) | 评论 (0)编辑 收藏

     摘要:   阅读全文

BeanSoft 2007-11-03 18:35 发表评论

文章来源:http://www.blogjava.net/beansoft/archive/2007/11/03/157955.html

posted @ 2007-11-10 17:21 代林 阅读(337) | 评论 (0)编辑 收藏

原创讲解JSP过滤器和监听器

BeanSoft(刘长炯) 2007年11月

关于这个问题, 比较复杂的说. 不过我希望通过例子来解释会方便理解一些.

假设有一个非常危险的任务, 是九死一生. 需要你揣着炸药包从北平开车走高速路过保定去石家庄把鬼子的碉堡给炸了. 注意: 这个任务十分艰巨, 有可能半路炸药爆炸. 所以出发前你需要苦练10元一本的<<铁布衫>>, 还需要立遗嘱交代一下后事. 下面是路线图:
去时路线: 北平 ==> 高速路收费站入口(都有警察和警犬) A  ==> 保定收费站 B ==> 石家庄收费站 C ==> 炸碉堡 D ==> 转车(刚才的车已经炸没了) E =>
回来路线: 石家庄收费站 ==> 保定收费站 ==> 高速路收费站出口(都有警察和警犬) A ==> 安全回到北平 G

那么我们先简介可能发生的情况.  A 点有可能被警察和警犬发现, 所以你只能被扭送回北平.  即使不被发现, 还可能出现收费时发现10个现大洋一个路口的买路钱没带!! 哎, 只能又回去了. 还有最惨的: 高速路入口写着: 对不起, 到石家庄的路线因为施工不通! 只好回家等着吧.
到了B和C你可能还会被人发现带了炸药包, 或者发现买路费少带了! 极有可能又被扭送回北平, 注意已经在半道了, 是不会让你继续到石家庄的, 所以你会被从车上逮下来, 然后转到警车上带回来!  也就是从 B 或者 C 直接返回.
好了, 最佳情况就是你炸了碉堡, 也成功的返回了. 然后你可以开心的把<<铁布衫>>扔了, 然后宣告遗嘱作废.

OK, 以上过程, 就是过滤器和监听器的真实案例.

那么炸碉堡这个任务, 就相当于要调用 JSP 或者 Servlet 来获得执行结果(炸碉堡 D ).  在执行之前你需要做一些准备工作, 相当于要写一个
监听器 com.allanlxf.ums.web.ServiceListener
在里面你可以做一些事情例如初始化资源, 例如上文的苦练<<铁布衫>>, 立遗嘱, 这个相当于代码中的
public void contextInitialized(ServletContextEvent sce) 这样一个初始化事件.
那么在整个任务完成之后, 这些事情你就要考虑应该作废了, 所以需要
public void contextDestroyed(ServletContextEvent sce) 这样一个销毁事件, 例如把<<铁布衫>>扔了, 然后宣告遗嘱作废, 也就是收回资源.

那么过滤器在哪里呢? 它位于任务的 A B C 点. 注意是双向路程都会经过的. 也就是请求和响应都会经过. 但是过滤器也会检查不同的情况, 例如 A 点实际上有两个过滤功能: 查炸药包和收买路钱. 这就相当于配置了:
  
       sessionFilter
     * *.do
     * REQUEST
     * FORWARD
  
 
两个过滤功能都要检查. 如果成功了怎么办呢? 会继续让你走下一个路口, 注意不是让你直接成功. 也就是代码:
        if(session.getAttribute("user") != null || path.equals("/login"))//若用户已经登录并且当前路径仍然停留在登录页面      {           
           chain.doFilter(request, response);//继续走下面的过滤器或者任务(不保证最终任务, 因为下个过滤器也可能让你回来)
           只有当走到 C 点的时候, 下一步才是执行了最终的任务: 执行JSP或者Servlet.
       }
反过来怎么办? 把你扭送上警车, 强行返回! 这样你连路口 B C 和最终任务都无法访问了. 也就是不会让你访问下一个过滤器和执行最终的 JSP 或者 Serlvet, 可以选择直接返回, 或者放警车上带回去.
       {
           return;// 直接返回
           或者 response.sendRedirect(request.getContextPath() + "/login.jsp");//则扭送上警车, 强行返回到警察局
       }

那么在 E 点发生了什么? 也就是你可能替换掉了原来的 response 对象,  也就是换车. 这意味着你可以在过滤器里私下修改请求和响应对象.

虽然已经不那么抽象了, 但是要理解可能还是需要耐心体会的.

=====================================================================
注: 原始问题

    1.请看下面一段代码和其注释:
import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

public class SessionFilter extends HttpFilter

{

   public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)

               throws ServletException, IOException

   {

       String path = request.getServletPath();//取得该servlet的路径名称

       path = path.substring(0, path.indexOf("."));   //获得路径中.之前的部分

       HttpSession session = request.getSession();//从请求中取得session为得是从session中读取用户是否登录的标志值

       if(session.getAttribute("user") != null || path.equals("/login"))//若用户已经登录并且当前路径仍然停留在登录页面

       {           

         *  chain.doFilter(request, response);//则将当前滤镜加入到滤镜链条当中

       }else//若用户尚未成功登录

       {

           response.sendRedirect(request.getContextPath() + "/login.jsp");//则使用请求重定向转到登录页面

       }       

   }

}

/*

* 该Filter滤镜类所过滤的是用户在浏览器中输入的

* 当前web application的访问路径,通过判断用户是

* 否成功登录而决定是否对访问路径加以限止

* 在该web application的web.xml配置文件中为

* 该filte滤镜做了相应配置

*/

请问: 上面代码FilterChain对象盛装的是Filter对象, 可它是怎么工作的啊?
加*号的语句是何用意啊,不是过滤路径吗, 为什么要将请求与响应加入呢?

2.请看下面一段代码:

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

public abstract class HttpFilter implements Filter

{

   private FilterConfig config;

   public void init(FilterConfig config) throws ServletException

   {

       this.config = config;

       init();

   }

   public void init() throws ServletException

   {

   }

   public String getInitParameter(String name)

   {

       return config.getInitParameter(name);

   }

   public ServletContext getServletContext()

   {

       return config.getServletContext();

   }

   public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

               throws ServletException, IOException

   {

       doFilter((HttpServletRequest)request, (HttpServletResponse)response, chain);

   }

   public abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)

               throws ServletException, IOException;

   public void destroy()

   {

   }

}

请问: 该类就这样写了一下,没有包含任何行为,它如何完成过滤工作啊?

3.请看下面代码:
package com.allanlxf.ums.web;

import javax.servlet.*;

//import javax.servlet.http.*;

import com.allanlxf.ums.service.SystemService;

import com.allanlxf.ums.service.StudentService;

public class ServiceListener implements ServletContextListener

{

   public void contextInitialized(ServletContextEvent sce)

   {

       ServletContext application = sce.getServletContext();

       StudentService service = new StudentService();

       application.setAttribute("studentService", service);

       SystemService systemService = new SystemService();

       application.setAttribute("systemService", systemService);

   }

   public void contextDestroyed(ServletContextEvent sce)

   {

   }

}

/*

*本类是该web application的监听器类,在该类中,

*将两个无为本系统提供服务的两个对象写入到了

*application隐含对象中(这样保证在该系统的任何

*地方都能够取得这两个服务类对象的引用)

*在本系统的web.xml文件中对该监听器做了配置

*/

请问: 为什么要将服务类对象写入到程序上下文中呢,直接创建不也一样吗?
     监听器只有这样的功能吗,是否还有其它功能呢?

3.请看下面的配置文件内容:

  
       sessionFilter
       com.allanlxf.ums.web.SessionFilter
  
   
  
       sessionFilter
     * *.do
     * REQUEST
     * FORWARD
  
       
  
       com.allanlxf.ums.web.ServiceListener
   

请问: 加*号的三项是什么意思?

当初老师讲的时候,许多基本的原则原理尚不清楚,这些根本没有听明白,当然,老师也未细讲,只说会用即可, 可是若不能明白其本质,用也只能用这一点儿, 怎么成呢, 希望您能够比较详悉的讲一下. thank you very much!



BeanSoft 2007-11-09 15:05 发表评论

文章来源:http://www.blogjava.net/beansoft/archive/2007/11/09/159374.html

posted @ 2007-11-10 17:21 代林 阅读(1145) | 评论 (0)编辑 收藏

出处:javaresearch 作者:mandyhou
    基于Web的MVC framework在J2EE的世界内已是空前繁荣。TTS网站上几乎每隔一两个星期就会有新的MVC框架发布。目前比较好的MVC,老牌的有Struts、Webwork。新兴的MVC 框架有Spring MVC、Tapestry、JSF等。这些大多是著名团队的作品,另外还有一些边缘团队的作品,也相当出色,如Dinamica、VRaptor等。这些框架都提供了较好的层次分隔能力。在实现良好的MVC 分隔的基础上,通过提供一些现成的辅助类库,同时也促进了生产效率的提高。

  如何选择一个好的框架应用在你的项目中,将会对你的项目的效率和可重用是至关重要的。本文将对目前最流行、最常用的两种framework进行介绍。

  一)Struts

  Struts是Apache软件基金下Jakarta项目的一部分。Struts框架的主要架构设计和开发者是Craig R.McClanahan。Struts 是目前Java Web MVC框架中不争的王者。经过长达五年的发展,Struts已经逐渐成长为一个稳定、成熟的框架,并且占有了MVC框架中最大的市场份额。但是Struts某些技术特性上已经落后于新兴的MVC框架。面对Spring MVC、Webwork2 这些设计更精密,扩展性更强的框架,Struts受到了前所未有的挑战。但站在产品开发的角度而言,Struts仍然是最稳妥的选择。

  Struts有一组相互协作的类(组件)、Serlvet以及jsp tag lib组成。基于struts构架的web应用程序基本上符合JSP Model2的设计标准,可以说是MVC设计模式的一种变化类型。根据上面对framework的描述,我们很容易理解为什么说Struts是一个web framwork,而不仅仅是一些标记库的组合。但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。Struts有其自己的控制器(Controller),同时整合了其他的一些技术去实现模型层(Model)和视图层(View)。在模型层,Struts可以很容易的与数据访问技术相结合,包括EJB,JDBC和Object Relation Bridge。在视图层,Struts能够与JSP, Velocity Templates,XSL等等这些表示层组件想结合。

  Struts的体系结构

  struts framework是MVC 模式的体现,下面我们就从分别从模型、视图、控制来看看struts的体系结构(Architecture)。

  从视图角度(View)

  主要由JSP建立,struts自身包含了一组可扩展的自定义标签库(TagLib),可以简化创建用户界面的过程。目前包括:Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags 这几个Taglib。有关它们的详细资料请参考struts用户手册

  从模型角度(Model)

  模型主要是表示一个系统的状态(有时候,改变系统状态的业务逻辑操作也也划分到模型中)。在Struts中,系统的状态主要有ActiomForm Bean体现,一般情况下,这些状态是非持久性的。如果需要将这些状态转化为持久性数据存储,Struts本身也提供了Utitle包,可以方便的与数据库操作

  从控制器角度(Controller)

  在Struts framework中, Controller主要是ActionServlet,但是对于业务逻辑的操作则主要由Action、ActionMapping、ActionForward这几个组件协调完成(也许这几个组件,应该划分到模型中的业务逻辑一块)。其中,Action扮演了真正的业务逻辑的实现者,而ActionMapping和ActionForward则指定了不同业务逻辑或流程的运行方向。

  对于Struts 如何控制、处理客户请求,让我们通过对struts的四个核心组件介绍来具体说明。这几个组件就是:ActionServlet。Action Classes,Action Mapping(此处包括ActionForward),ActionFrom Bean。

  二)Spring

  Spring 实际上是Expert One-on-One J2EE Design and Development 一书中所阐述的设计思想的具体实现。在One-on-One 一书中,Rod Johnson 倡导J2EE 实用主义的设计思想,并随书提供了一个初步的开发框架实现(interface21 开发包)。而Spring 正是这一思想的更全面和具体的体现。Rod Johnson 在interface21 开发包的基础之上,进行了进一步的改造和扩充,使其发展为一个更加开放、清晰、全面、高效的开发框架。

  Spring是一个开源框架,由Rod Johnson创建并且在他的著作《J2EE设计开发编程指南》里进行了描述。它是为了解决企业应用开发的复杂性而创建的。Spring使使用基本的JavaBeans来完成以前只可能由EJB完成的事情变得可能了。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

  简单来说,Spring是一个轻量的控制反转和面向切面的容器框架。当然,这个描述有点过于简单。但它的确概括出了Spring是做什么的。为了更好地理解Spring,让我们分析一下这个描述:

  1、轻量;从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于轻量;从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

  2、控制反转;Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,对象被动地传递它们的依赖而不是自己创建或者查找依赖对象。你可以认为IoC与JNDI相反;不是对象从容器中查找依赖,而是容器在对象初始化时不等被请求就将依赖传递给它。

  3、面向切面;Spring包含对面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统服务(例如审计与事物管理)进行内聚性的开发。应用对象只做它们应该做的;完成业务逻辑;仅此而已。它们并不负责(甚至是意识)其它的系统关注点,例如日志或事物支持。

  4、容器;Spring包含和管理应用对象的配置和生命周期,在这个意义上它是一种容器。你可以配置你的每个bean如何被创建;基于一个配置原形为你的bean创建一个单独的实例或者每次需要时都生成一个新的实例;以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量的EJB容器,它们经常是庞大与笨重的,难以使用。

  框架;Spring使由简单的组件配置和组合复杂的应用成为可能。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久性框架集成等等),将应用逻辑的开发留给了你。

  所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种子框架提供了基础。

posted @ 2007-11-10 16:58 代林 阅读(1509) | 评论 (1)编辑 收藏

以下所说的struts-config.xml和ApplicationResources.properties等文件名是缺省时使用的,如果你使用了多模块,或指定了不同的资源文件名称,这些名字要做相应的修改。

1、“No bean found under attribute key XXX”
 在struts-config.xml里定义了一个ActionForm,但type属性指定的类不存在,type属性的值应该是Form类的全名。或者是,在Action的定义中,name或attribute属性指定的ActionForm不存在。

2、“Cannot find bean XXX in any scope”
 在Action里一般会request.setAttribute()一些对象,然后在转向的jsp文件里(用tag或request.getAttribute()方法)得到这些对象并显示出来。这个异常是说jsp要得到一个对象,但前面的Action里并没有将对象设置到request(也可以是session、servletContext)里。

 可能是名字错了,请检查jsp里的tag的一般是name属性,或getAttribute()方法的参数值;或者是Action逻辑有问题没有执行setAttribute()方法就先转向了。

 还有另外一个可能,纯粹是jsp文件的问题,例如会指定一个id值,然后在循环里使用这个值作为name的值,如果这两个值不同,也会出现此异常。(都是一个道理,request里没有对应的对象。)

3、“Missing message for key "XXX"”
 缺少所需的资源,检查ApplicationResources.properties文件里是否有jsp文件里需要的资源,例如:
  
 这行代码会找msg.name.prompt资源,如果AppliationResources.properties里没有这个资源就会出现本异常。在使用多模块时,要注意在模块的struts-config-xxx.xml里指定要使用的资源文件名称,否则当然什么资源也找不到,这也是一个很容易犯的错误。

4、“No getter method for property XXX of bean teacher”
 这条异常信息说得很明白,jsp里要取一个bean的属性出来,但这个bean并没有这个属性。你应该检查jsp中某个标签的property属性的值。例如下面代码中的cade应该改为code才对:  

5、“Cannot find ActionMappings or ActionFormBeans collection”
 待解决。

6、“Cannot retrieve mapping for action XXX”
 在.jsp的标签里指定action='/XXX',但这个Action并未在struts-config.xml里设置过。

7、HTTP Status 404 - /xxx/xxx.jsp
 Forward的path属性指向的jsp页面不存在,请检查路径和模块,对于同一模块中的Action转向,path中不应包含模块名;模块间转向,记住使用contextRelative="true"。

8、没有任何异常信息,显示空白页面
 可能是Action里使用的forward与struts-config.xml里定义的forward名称不匹配。

9、“The element type "XXX" must be terminated by the matching end-tag "XXX".”
 这个是struts-config.xml文件的格式错误,仔细检查它是否是良构的xml文件,关于xml文件的格式这里就不赘述了。

10、“Servlet.init() for servlet action threw exception”
 一般出现这种异常在后面会显示一个关于ActionServlet的异常堆栈信息,其中指出了异常具体出现在代码的哪一行。我曾经遇到的一次提示如下:

  java.lang.NullPointerException
   at org.apache.struts.action.ActionServlet.parseModuleConfigFile(ActionServlet.java:1003)
   at org.apache.struts.action.ActionServlet.initModuleConfig(ActionServlet.java:955)

为解决问题,先下载struts的源码包,然后在ActionServlet.java的第1003行插入断点,并对各变量进行监视。很丢人,我竟然把struts-config.xml文件弄丢了,因此出现了上面的异常,应该是和CVS同步时不小心删除的。

11、“Resources not defined for Validator”
 这个是利用Validator插件做验证时可能出现的异常,这时你要检查validation.xml文件,看里面使用的资源是否确实有定义,form的名称是否正确,等等。

posted @ 2007-11-10 16:43 代林 阅读(220) | 评论 (0)编辑 收藏