显示标签为“opensip”的博文。显示所有博文
显示标签为“opensip”的博文。显示所有博文

2012年8月17日星期五

OpenSIPS features

  • robust and performant SIP (RFC3261) Registrar server, Location server, Proxy server and Redirect server
  • small footprint - the binary file is small size, functionality can be stripped/added via modules
  • plug&play module interface - ability to add new extensions, without touching the core, therefore assuring a great stability of core components
  • stateless and transactional statefull SIP Proxy processing
  • support for UDP/TCP/TLS/SCTP transport layers
  • IPv4 and IPv6
  • support for SRV and NAPTR DNS
  • SRV DNS failover
  • IP Blacklists
  • multi-homed (mhomed) and multi-domain support
  • flexible and powerful scripting language for routing logic
  • variables support in script - script variables, pseudo-variables (access to the SIP messages), AVPs (values persistent per SIP transactions)
  • management interface via FIFO file and unix sockets
  • authentication, authorization and accounting (AAA) via database (MySQL, Postgress, text files), RADIUS and DIAMETER
  • digest and IP authentication
  • Presence Agent support (many additional integration features)
  • XCAP support for Presence Agent
  • CPL - Call Processing Language (RFC3880)
  • SNMP - interface to Simple Network Management Protocol
  • management interface (for external integration) via FIFO file, XMLRPC or Datagram (UDP or unixsockets)
  • NAT traversal support for SIP and RTP traffic
  • ENUM support
  • PERL Programming Interface - embed your extensions written in Perl
  • Java SIP Servlet Application Interface - write Java SIP Servlets to extent your VoIP services and integrate with web services
  • load balancing with failover
  • least cost routing
  • support for replication - REGISTER offer new functions for replicating client information (real source and received socket).
  • logging capabilities - can log custom messages including any header or pseudo-variable and parts of SIP message structure.
  • modular architecture - plug-and-play module interface to extend the server's functionality
  • gateway to sms (AT based)
  • multiple database backends - MySQL, PostgreSQL, Oracle, Berkeley, flat files and other database types which have unixodbc drivers
  • straightforward interconnection with PSTN gateways
  • dialog support (call monitoring, call termination from proxy side, call profiling)
  • XMPP gateway-ing ( transparent server-to-server translation)
  • impressive extension repository - over 70 modules are included in OpenSIPS repository

Scalability:

  • OpenSIPS can run on embedded systems, with limited resources - the performances can be up to hundreds of call setups per second
  • used a load balancer in stateless mode, OpenSIPS can handle over 5000 call setups per second
  • on systems with 4GB memory, OpenSIPS can serve a population over 300 000 online subscribers
  • system can easily scale by adding more OpenSIPS servers
  • OpenSIPS can be used in geographic distributed VoIP platforms
  • straightforward failover and redundancy

opensip

1、引入

随着通信IP化的发展,IP传输的高带宽、低成本等优势使得越来越多的企业、电信运营商加快建设基于IP的各种通信应用。在通信协议IP化发展中,SIP协 议毫无争议地成为各大电信运营商构建其未来网络的基础协议,越来越多的SIP软件产品也不断出现在行业应用中。SIP协 议的标准化,同时也造就了一大批优秀的开源软件产品,包括Asterisk、SipXecs、FreeSWITCH、OpenSIPS等SIP服务端软 件,也包括X-lite、LinPhone、eyeBeam等SIP客户端软件。本文介绍了国外成熟的SIPServer开源项目OpenSIPS,并结 合其它通信方面的开源项目对其应用情况进行了一些介绍。

2、OpenSIPS介绍

OpenSIPS是一个成熟的开源SIP服务器,除了提供基本的SIP代理及SIP路由功能外,还提供了一些应用级的功能。OpenSIPS的结构非常 灵活,其核心路由功能完全通过脚本来实现,可灵活定制各种路由策略,可灵活应用于语音、视频通信、IM以 及Presence等多种应用。同时OpenSIPS性能上是目前最快的SIP服务器之一,可用于电信级产品构建。

2.1、功能特点

凭借其可扩展、模块化的系统架构,OpenSIPS提供了一个高度灵活的、用户可配置的路由引擎,可以为voice、video、IM和 presence等服务提供强大高效的路由、鉴权、NAT、网关协议转化等功能。由于其稳定高效等特点,OpenSIPS已经被诸多电信运营商应用在自己的网络体系中。其 主要功能如下:

SIP注册服务器/代理服务器(lcr、dynamic routing、dialplan)/重定向服务器
 SIP presence agent
 SIP B2BUA
 SIP IM Server
 SIP to SMS/XMPP网关
 SIP to XMPP网关
 SIP 负载均衡
 SIP NAT traversal

2.2、基本应用配置

OpenSIPS不但提供了丰富的功能,还具有操作简单的特点。所有OpenSIPS的应用功能都可以通过一个配置文件opensips.cfg来 实现的。该配置文件主要分为三个部分,第一部分主要是全局变量的设置;第二部分主要是加载模块,并设置模块的相应参数;第三部分主要是路由的策略和功能应 用。为了更清晰的呈现opensips.cfg配置文件带来的强大功能,接下来对这三个部分以简单的示例进一步说明。

第一部分全局变量的设置,通过一条语句就能指定用于侦听接收sip消息的端口和传输层协议。

第二部分负责模块的加载和参数配置。以之前的OpenSIPS的负载均衡功能配置为例,需要加载load_balancer模块,并进行配置。

第三部分是sip消息的路由和功能应用。还是以OpenSIPS的负载均衡功能为例。

从以上应用示例可以看到,通过在opensips.cfg中进行简单的配置,就能实现强大的功能。

2.3、系统结构

OpenSIPS的架构开放灵活,其核心功能控制均可通过脚本控制实现,各个功能也通过模块加载的方式来构建。采用lex和yacc工具构建的配置 文件分析器是其架构设计中的重要部分之一。通过这个分析器,opensips设计了自己的语法规则,使得我们可以适合SIP规 范的语言来进行配置文件中的脚本编写,从而达到简化程序以及方便代码阅读的目的。同时这样的设计也使opensips.cfg配置文件的执行速度达到了C 语言的级别。其体系结构大体如下图:

框架的最上层是用于实现sip消息路由逻辑的opensips.cfg脚本配置,在配置文件中,可以使用Core提供的Parameter和 Function,也可以使用众多Modules提供的Function。比如在之前的负载均衡示例中,is_method(“INVITE”)就属于 textops模块提供的功能,src_ip和src_port都属于Core提供的参数。下层,提供了网络传输、sip消息解析等基本功能。在左侧,通过相应的数据库适配器,可是使用多种数据库存取数据。在这样的 体系结构下,我们就可以方便地通过增加功能module来添加我们需要的功能,而不会对原有系统造成影响。

除了以上所述的OpenSIPS的优点,OpenSIPS还提供了一系列的管理维护命令的接口。我们可以通过Core和Module提供的MI管理 接口,方便的监控系统以及模块的状态。比如,通过Core的fifo ps命令,可以获取当前进程的状态;通过Core的fifo get_statistics命令,可以获得当前共享内存以及各进程私有内存的使用情况等等。通过MI管理接口,我们还可以方便地在运行时修改部分参数, 比如,对于load_balancer模块,我们可以通过fifo lb_reload命令,更新目标组的配置信息,可以通过fifo lb_status命令激活或关闭某个目标,这些命令在实际应用中都非常实用。如果希望通过WEB图形界面管理OpenSIPS,OpenSIPS社区还 提供了OpenSIPS Control Panel 4.0产品。

3、与其它开源项目共同搭建VOIP服务

OpenSIPS提供了以上那么多的功能,那OpenSIPS是不是已经实现了PBX的功能了?不是!OpenSIPS并不具备一个媒体服务器(Media Server)的功能。媒体服务器主要提供了类似VoiceMail、呼叫中语音交换、会议服务、视频服务等一系列和语音、视频相关的服务;而 OpenSIPS的主要功能主要在于代理、路由和网关。因此,单独的OpenSIPS并不能够提供VOIP服务,只有和Asterisk等具备媒体功能的软件整合,才能构建可靠的语音服务体系。

对于媒体服务器,开源世界也提供了很多选择,如老牌的Asterisk,以及功能全面的sipXecs以及专注于IVR功 能的FreeSwitch等,他们都是非常优秀的开源项目。其中Asterisk功能全面、灵活,但主要面向企业应用,在性能上稍差。但Asterisk 提供了完善的PBX功能,可以连接多种不同的电话终端,支持多种主流的IP电话协议和系统接口。FreeSwtich专注于IVR功能,性能、可靠性非常高。近期 FreeSwitch已被sipXecs采用作为其IVR部分功能。sipXecs则是一个功能比较全面的产品,包括IVR、VoiceMail、人工坐 席等等,更难得的是SipXecs提供了良好的配置、管理界面,易于使用。

只要将OpenSIPS作为前置接入,将多个Asterisk、FreeSwitch、sipXecs挂接在其后,由OpenSIPS实现SIP消 息的转发和负载均衡,就可以轻松地实现各种语音业务以及规模扩展。如下图所示。

4、小结

从文中介绍可以看出,OpenSIPS是一个成熟的电信级SIP Server平台,可广泛应用于SIP应用的路由分发、负载均衡,可用于搭建SIP代理,提供SIP注册服务等。而且目前OpenSIPS自身也提供 SIP Presence以及IM功能。同时,应该注意的是OpenSIPS本身并不提供媒体相关服务,如呼叫中心、VoiceMail等业务,该部分业务可通过 FreeSwtich、sipXecs等平台实现。

参考文献:
[1].OpenSIPS:  http://www.opensips.org/
[2] FreeSwitch wiki: http://wiki.freeswitch.org/wiki/Main_Page
[3] sipXecs: http://www.sipfoundry.org/


2012年8月11日星期六

Apache Struts 2 Documentation(source: http://struts.apache.org/2.2.3/docs/struts-2-blank-archetype.html)

The Struts 2 Blank Archetype ("blank-archetype") provides a minimal, but complete, Struts 2 application. It demonstrates some of the most basic Struts 2 concepts.

Features

  • XML-based configuration, demonstrates including additional config file
  • Example actions
  • Package-level resource bundle
  • XML-based validation
  • Unit-testing

Contents

Creating Our blank-archetype Project

We'll run the following command from our project's parent directory (this is shown using Unix-style commands).

$ mvn archetype:generate -B \                           -DgroupId=tutorial \                           -DartifactId=tutorial \                           -DarchetypeGroupId=org.apache.struts \                           -DarchetypeArtifactId=struts2-archetype-blank \                           -DarchetypeVersion=<version>  $ ls  tutorial/  $ cd tutorial  $ ls  pom.xml         src/  

Depending on the state of your local system you may see Maven downloading various libraries (known as "downloading the internet", which is what it seems Maven does sometimes). Be patient--Maven is basically setting up your required libraries automatically.
<version> - is the version of Struts 2 you want to use and archetype was released for, eg. 2.1.8.1 .

Staging repository

If the above command will fail because of missing archetypes in central repository, you can try to use staging repository like below

mvn archetype:generate -B \                         -DgroupId=tutorial \                         -DartifactId=tutorial \                         -DarchetypeGroupId=org.apache.struts \                         -DarchetypeArtifactId=struts2-archetype-blank \                         -DarchetypeVersion=<version>                         -DarchetypeCatalog=http://people.apache.org/builds/struts/<version>/m2-staging-repository/   

Project Structure

The source code structure follows the normal Maven directory structure. The blank-archetype does not include all of the directories listed in the Maven structure reference page.

Our project's structure looks like this:

DirectoryDescription
srcAll project source
¦- mainPrimary source directory
¦  ¦- java Java source code
¦  ¦  `- tutorialPackage defined by groupId parameter
¦  ¦     `- example The example actions from the archetype
¦  ¦- resourcesResources (config, property, and validation files, and so on
¦  ¦  `-tutorialPackage defined by groupId parameter
¦  ¦     `- example Example property and validation files from archetype
¦  `- webappWeb application files (HTML, JSP, etc.)
¦      `- WEB-INF Typical WEB-INF folder
¦         `- exampleFiles from archetype
`- test Test code (unit tests etc.)
   `- javaJava-based test code
      `- tutorial Package defined by groupId parameter
         `- exampleTest code from archetype

Structure Difference From Non-Maven Projects

One big change for folks not used to the Maven structure is the separation of Java source code and resource files. For example, in a non-Maven project our directory structure might look like this:

srcAll project source
¦- tutorial Tutorial package
¦  `- exampleExample package
¦     ¦- Login.javaLogin action source
¦     ¦- package.propertiesResource file
¦     `- Login-validation.xml Validation file
`- struts.xmlStruts 2 config file
webWeb app files
¦- WEB-INFTypical WEB-INF folder
`- index.htmlAn HTML file

It can take a little while to get used to, but ultimately it provides good separation of "types" of things, and becomes second-nature pretty quickly. Note that it's possible to use a non-Maven directory layout with Maven projects, but this can be challenging at some points.

Building The Project

There are several different ways we can go about building our project, from simple compilation up to actually running the web application--all from within Maven.

Compilation

$ mvn compile

will create a target directory containing the compiled classes. By itself this isn't terribly useful.

Testing

Running

$ mvn test

will compile the application and run the included unit tests. Blank-archetype's unit tests are not extensive, but provide a simple starting point for writing more complex, application-specific tests.

One we've run the Maven test command we'll notice there's a target/surefire-reports directory. The Maven Surefire Plugin is how Maven runs our unit tests. By default it will create test results in XML and text formats in the target/surefire-reports directory. These files can be examined to get further information regarding the failed tests.

Assembling (Creating a WAR)

Running

We can run blank-archetype using the Jetty server via the Maven Jetty Plugin by executing the Jetty plugin's run command:

$ mvn jetty:run

Once we've run the application we can see that it works by visiting localhost:8080/tutorial/example/Welcome.action as a sanity check.

Application Documentation

The application consists of a few test actions demonstrating simple validation and package-level property (resource) files. The most interesting URLs are as follows (assuming we used groupId=tutorial):

URLDescription
/tutorial/example/Welcome.action Handled by wildcard mapping
/tutorial/example/HelloWorld.actionHandled by explicit mapping, demonstrates package-level properties
/tutorial/example/Login.actionHandled by explicit mapping with method wilcard (see the Login.action documentation for information regarding how to access this URL)

Application Configuration

The default Struts 2 configuration file is contained in src/main/resources/struts.xml. It includes an additional configuration file, src/main/resources/example.xml. The application's mappings are contained in theexample.xml file. The struts.xml file sets some constants.

See the struts.xml page for more information about the struts.xml file. For more information regarding what's contained in typical struts.xml files start at the Configuration Elements page, which contains links to a bunch of information. See the Configuration Files page for more information regarding additional Struts 2 configuration files, including links to the files that set all the Struts 2 default configurations.

Welcome.action

The mapping for this action is handled by a "catch-all" mapping in example.xml:

<action name="*" class="tutorial2.example.ExampleSupport">    <result>/example/{1}.jsp</result>  </action>  

This mapping is the last mapping contained in example.xml--anything not handled by mappings appearing before it in example.xml will be caught by this mapping. This mapping will look for JSP files insrc/main/webapp/example/*.jsp. Since there's a Welcome.jsp in that directory, we're all set. See the Wildcard Mappings page for more information on how Struts 2 can use wildcard mappings.

HelloWorld.action

The mapping executes the HelloWorld action, contained in src/main/java/tutorial/example/HelloWorld.action. This action retrieves a message from a package-level properties file, contained insrc/main/resources/tutorial/package.properties. See the Localization page for more information about how Struts 2 handles message resources (it's pretty cool).

Login.action

This is another wildcard mapping:

    <action name="Login_*" method="{1}" class="tutorial2.example.Login">    <result name="input">/example/Login.jsp</result>    <result type="redirectAction">Menu</result>  </action>  

In the application the Login action is reached via a link, but not directly to /tutorial/example/Login.action. The link is actually /tutorial/example/Login_input.action. Reaching the Login action this way bypasses validation: if we hit the Login action directly we'll get a validation error.

The validation configuration is contained in /src/main/resources/tutorial/example/Login-validation.xml. It checks for the presence of the username and password properties (form values). It uses messages stored in the package.properties file (in the same directory). See the Validation page for more information regarding Struts 2 validation.



2012年8月10日星期五

开发最佳实践:在Web应用开发中优化Struts框架(转自http://www.uml.org.cn/j2ee/201005171.asp)

Struts是一种开源框架,可用来构建Web应用程序,它基于流行的Model-View-Controller (MVC2) 设计范型。该框架构建在一些标准的技术之上,比如Java Servlets、JavaBeans、ResourceBundles和XML,并且可提供灵活和可扩展的组件。

关于Struts更多内容,请参阅:Struts框架应用专题

Struts以ActionServlet的形式实现了Controller层,并建议使用JSP标记库构建View层。Struts 通过Action类提供了围绕Model层的包装器。图1展示了基于Model-View-Controller设计的Struts框架。

图1.Struts和MVC

Struts 组件概览

首先,我们在最佳实践上下文中解释 Struts 组件,以及它们在 Web 应用程序开发中所起的作用。

Action

应用程序的每个 Action 都会扩展 Struts 的 org.apache.struts.action.Action 类。这些 Action 类为应用程序的 Model 层提供了一个接口,充当围绕业务逻辑的包装器。每个 Action 类都必须向 perform() 方法提供其特定于用例的实现。perform() 方法经常返回类型 ActionForward 的一个值。

ActionForm

应用程序的 ActionForm 扩展了 Struts 的 org.apache.struts.action.ActionForm 类。ActionForm 是一些封装和验证请求参数的简单 JavaBean。要验证请求数据,ActionForm 的 validate() 方法必须给出一个特定于该情况的实现。ActionForm 作为运载工具,向 Action 类提供请求数据。一个 JSP 对象与各自的 ActionForm 对象相结合,构成应用程序的 View 层。在该层,几乎 JSP 对象的每个表单字段都映射到相应的 ActionForm 的属性。

JSP 定制标记库

JSP 定制标记库是用标记表示的一组行为的集合。这是 JSP Specification 1.1 的一个强大特性;它将其他应用程序层的表示区别了开来。这些库易于使用,而且可以以一种类似 XML 的方式来读取。只要尽量少地在其中使用 Java scriptlet,就可以轻松维护 JSP 组件。Struts 提供的 JSP 标记包括 HTML、逻辑和 bean 标记。

ActionErrors

可以使用 ActionError 来支持异常处理。ActionError 捕捉应用程序异常,并将其传送给 View 层。每个异常都是一个 ActionError 实例的集合。ActionError 可以封装错误消息,而 Presentation 层中的 </html:errors> 可以呈现 ActionError 集合内的所有错误消息。

最佳实践 1. 跨多个 ActionForm 重用数据

熟悉了 Struts 组件之后,就可以继续学习如何充分利用这一框架。首先,Struts 建议将每个 JSP 对象与一个 ActionForm 相关联,后者可以封装屏幕上显示的数据。可以通过 ActionForm 内的附加方法来访问 JSP 对象内的表单数据。清单 1 展示了 ActionForm 标记在 View 层中的传统方法。

清单 1. 使用 ActionForm

<html:form action="/bp1">

<html:text property="attrib1" />

</html:form >

这个ActionForm被称为 “BP1AForm”,它包括属性attrib1及其getter和setter方法。在配置文件struts-config.xml中,行为 “/bp1” 通过name属性映射到 bp1AForm。这有助于在JSP中显示数据。要实现这一最佳实践,Struts 建议您进行以下两个操作:

创建一个 JavaBean(BP1BForm),且其属性是 BP1AForm 属性的子集,还要创建这些属性的 getter 和 setter 方法。通过将这个 bean 与 BP1AForm 关联,用 bean BP1BForm 的属性替代 BP1AForm 中的属性。现在就可以通过 BP1BForm 访问 BP1AForm 中的属性子集了。清单2展示了访问的方式。

清单 2. 访问 JSP 中的表单属性

<html:form action="/bp1">

<bean:define name="bp1AForm" property="bp1BForm" id="bp1B" type="com.ibm.dw.webarch.struts.BP1BForm" />

<html:text name="bp1B" property="subsetAtt1" />

</html:form >

要点

这种实践的主要优势是可用于多个 ActionForm 访问一个属性集。在遵循这一最佳实践的同时,需要记住以下几点:

1.Struts 实现 <bean:define/> 标记。

2.当代码 <%@ taglib uri="struts-bean.tld" prefix="bean" %> 指向 struts-bean.tld 时,<bean:define/> 标记开始在 JSP 组件内工作。

3.由 ActionForm 扩展而来的 BP1AForm 验证框架必须验证 BP1BForm 的数据。

4.当在应用程序中创建 Action 类时,不需要直接扩展 org.apache.struts.action.Action,可以通过扩展 org.apache.struts.action.Action 创建一个 Action 类(IntermediateAction),用于处理应用程序中的常见事务。所有其他的 Action 类都扩展 IntermediateAction 类。

最佳实践 2. 使用 Action 类处理请求

通常,在使用这个 Struts 框架时,对于 JSP 组件请求应用程序执行的每个动作,应用程序都必须扩展Struts的org.apache.struts.action.Action以创建Action类。在处理请求时,单个的 Action 类与应用程序的 Model 层连接。要实现这一最佳实践,Struts 建议您遵循以下步骤:

1.通过扩展 org.apache.struts.action.Action 创建一个 Action 类,比如 BP2Action。

2.通过扩展 BP2Action 在 Web 应用程序中创建所有其他 Action 类。

3.在 BP2Action 类中创建一个方法 performTask(),就像在公共抽象类 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 中一样。

4.在BP2Action 类中向应用程序添加一个或多个泛型方法,比如 serverSideValidate()。考虑以下因素后决定方法的访问修饰符:

◆如果所有 Action 类都必须实现此方法,则让其为抽象。

◆如果某些 Action 类提供一个特定的实现,则将此方法声明为受保护,并给它一个默认实现。

5.在 BP2Action 类中,将方法 perform() 声明为 final。调用上述的泛型方法(通常在处理请求前调用该方法)。现在调用 步骤 3 中创建的方法 performTask()。 
在每个扩展 BP2Action 的 Action 类,添加具有特定实现的方法 performTask()。

优势

这一实践有两个主要优势。首先,它避免了 Web 应用程序中每个 Action 类的冗余代码。其次,通过将 Action 类的行为集中在一起,使应用程序能够更多地控制通用的任务。

最佳实践 3. 使用 ActionForm 处理会话数据

在一个基于 Struts 的 Web 应用程序中,每个 ActionForm 都扩展 org.apache.struts.action.ActionForm 类。这些 ActionForm 封装页面数据,并提供一个验证框架来验证请求参数。

大多数 Web 应用程序都在会话中保持数据,使其在整个应用程序过程中可用。这种最佳实践实现了这种 Web 应用程序特性。它允许方法 toSession() 和 fromSession() 将会话数据移动到表单数据或从表单数据移回。因此,它实现了在 Web 应用程序中保持会话数据。要遵循一最佳实践,执行以下步骤:

通过扩展 org.apache.struts.action.ActionForm 创建一个名为 BP3Form 的抽象类。在BP3Form类中,添加具有访问修饰语的方法,就像在公共抽象类 void toSession(SessionData sessionData) 和 void fromSession(SessionData sessionData) 中一样。

在每个 ActionForm 类中,扩展 BP3Form 并实现这些抽象方法(表单数据通过它们传递到会话或从会话传回)。 相应的 Action 类可以决定这些方法的调用顺序。例如,可以在决定 actionForward 之前调用 ActionForm 上的方法 toSession()。
何时使用这一实践,这一实践最适用于:会话数据是单一对象和/或每个页操作或使用会话数据。

最佳实践 4.有效处理异常

传统地,当在 Action 类中发生应用程序异常时,异常首先被写入日志。然后此类创建一个 ActionError 并在合适的作用域中存储它。然后 Action 类再将控制转交给合适的 ActionForward。清单 3 展示了 Action 类是如何处理异常的。

清单 3. Action 类中的异常处理

  1.    try {  
  2.    //Code in Action class  
  3.    }  
  4.    catch (ApplicationException e) {  
  5.    //log exception  
  6.    ActionErrors actionErrors = new ActionErrors();  
  7.    ActionError actionError = new ActionError(e.getErrorCode());  
  8.    actionErrors.add(ActionErrors.GLOBAL_ERROR, actionError);  
  9.    saveErrors(request, actionErrors);  
  10.    } 

传统的异常处理过程在每个 Action 类中保存异常信息,而最佳实践 4 则在处理异常时避免冗余代码。要使用这一最佳实践,Struts 建议您遵循以下步骤:

1.通过扩展 org.apache.struts.action.Action 创建一个 Action 类,比如 BP4Action。

2.通过扩展 BP4Action 在 Web 应用程序中创建所有其他 Action 类。

3.在 BP4Action 中声明变量 ActionErrors actionErrors = new ActionErrors();。

4.在 BP4Action 中创建方法 performTask(),就像在公共抽象类 ActionForward performTask(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ActionErrors actionErrors) throws IOException, ServletException 中一样。

6.在BP4Action中将方法perform()声明为final。然后调用泛型方法(这些方法总是在处理请求前调用)。现在调用在前一个步骤中创建的 performTask()。

7.在每个 Action 类中实现方法performTask()的同时(通过扩展 BP4Action),像清单 4 那样处理应用程序异常。

清单 4. 有效使用 ActionErrors

  1.    try   {  
  2.    //Code in Action class  
  3.    }  
  4.    catch(ApplicationException appException) {  
  5.    //Log exception  
  6.    //Add error to actionErrors  
  7.    actionErrors.add(ActionErrors.GLOBAL_ERROR,  
  8.       new ActionError(appException.getErrorCode()));  
  9.    }  

在BP4Action中,调用方法performTask()之后,通过saveErrors(request, errors)保存ActionErrors。

优势

这一实践主要的优势是:避免了每个处理 ActionErrors的Action类中的代码冗余。

结束语

对开发团队而言,构建易于维护的Web应用程序是一项非常具有挑战性的任务。使用Struts等成熟的框架有助于实现通常与构建应用程序相关的基础设施代码。Struts 框架提供了一组标准接口,用于将业务逻辑插入到应用程序中。此外,还提供了一种跨开发团队的一致机制,用于执行用户数据验证、屏幕导航等任务,以及用于简化开发屏幕的一组定制标记库。

本文给出的4种最佳实践对您充分利用这种框架的特性十分重要。它们不仅能够提高代码的模块化程度和应用程序的可重用性,还能减少代码冗余。对于构建可扩展的Web应用程序,这是至关重要的。