2008年12月17日

 

 

     容器类可以大大提高编程效率和编程能力,在Java2中,所有之容器都由SUN公司之JoshuaBloch进行了重新设计,丰富了容器类库之功能。

 

Java2容器类类库之用途是“保存对象”,它分为两类:

 

 

Collection----一组独立之元素,通常这些元素都服从某种规则。List必须保持元素特定之顺序,而Set不能有重复元素。

 

 

Map----一组成对之“键值对”对象,即其元素是成对之对象,最典型之应用就是数据字典,并且还有其它广泛之应用。另外,Map可以返回其所有键组成之Set和其所有值组成之Collection,或其键值对组成之Set,并且还可以像数组一样扩展多维Map,只要让Map中键值对之每个“值”是一个Map即可。

1.迭代器

 

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中之对象,而开发人员不需要了解该序列之底层结构。迭代器通常被称为“轻量级”对象,因为创建它之代价小。

Java中之Iterator功能比较简单,并且只能单向移动:

 

(1)使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator之next()方法时,它返回序列之第一个元素。

 

 

(2)使用next()获得序列中之下一个元素。

 

(3)使用hasNext()检查序列中是否还有元素。

 

(4)使用remove()将迭代器新返回之元素删除。

 

Iterator是Java迭代器最简单之实现,为List设计之ListIterator具有更多之功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

2.List之功能方法

 

List(interface):次序是List最重要之特点;它确保维护元素特定之顺序。List为Collection添加了许多方法,使得能够向List中间插入与移除元素(只推荐LinkedList使用)。一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插入和删除元素。

 

 

ArrayList:由数组实现之List。它允许对元素进行快速随机访问,但是向List中间插入与移除元素之速度很慢。ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。

 

LinkedList:对顺序访问进行了优化,向List中间插入与删除得开销不大,随机访问则相对较慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。

 

 

3.Set之功能方法

 

 

Set(interface):存入Set之每个元素必须是唯一之,因为Set不保存重复元素。加入Set之Object必须定义equals()方法以确保对象之唯一性。Set与Collection有完全一样之接口。Set接口不保证维护元素之次序。

HashSet:为快速查找而设计之Set。存入HashSet之对象必须定义hashCode()。

TreeSet:保持次序之Set,底层为树结构。使用它可以从Set中提取有序之序列。

 

 

LinkedHashSet:具有HashSet之查询速度,且内部使用链表维护元素之顺序(插入之次序)。于是在使用迭代器遍历Set时,结果会按元素插入之次序显示。

HashSet采用散列函数对元素进行排序,这是专门为快速查询而设计之;TreeSet采用红黑树之数据结构进行排序元素;LinkedHashSet内部使用散列以加快查询速度,同时使用链表维护元素之次序,使得看起来元素是以插入之顺序保存之。需要注意之是,生成自己之类时,Set需要维护元素之存储顺序,因此要实现Comparable接口并定义compareTo()方法。

posted @ 2008-12-17 11:06 angelspider 阅读(884) | 评论 (0)编辑 收藏

 
Struts框架只允许应用中存在一个ActionServlet类,但是可以存在多个客户化的RequestProcessor类,每个子应用模块都可以有单独的RequestProcessor类,

ActionServlet主要负责初始化,以及介绍请求并找到合适的RequestRrocessor,之后真正干活的是RequestProecssor和Action.
上回说到ActionServlet的process方法最终会调用RequestProcessor类的process方法.下面介绍这个方法.
一.RequestProcessor的process方法
 Java代码
public void process(HttpServletRequest request,
                        HttpServletResponse response)
        throws IOException, ServletException {
      // Wrap multipart requests with a special wrapper   
        request = processMultipart(request);
        // Identify the path component we will use to select a mapping
        String path = processPath(request, response);
        if (path == null) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("Processing a '" + request.getMethod() +
                      "' for path '" + path + "'");
        }
        // Select a Locale for the current user if requested
        processLocale(request, response);
        // Set the content type and no-caching headers if requested
        processContent(request, response);
        processNoCache(request, response);
        // General purpose preprocessing hook
        if (!processPreprocess(request, response)) {
            return;
        }
        this.processCachedMessages(request, response);
        // Identify the mapping for this request
        ActionMapping mapping = processMapping(request, response, path);
        if (mapping == null) {
            return;
        }
        // Check for any role required to perform this action
        if (!processRoles(request, response, mapping)) {
            return;
        }
        // Process any ActionForm bean related to this request
        ActionForm form = processActionForm(request, response, mapping);
        processPopulate(request, response, form, mapping);
        // Validate any fields of the ActionForm bean, if applicable
        try {
            if (!processValidate(request, response, form, mapping)) {
                return;
            }
        } catch (InvalidCancelException e) {
            ActionForward forward = processException(request, response, e, form, mapping);
            processForwardConfig(request, response, forward);
            return;
        } catch (IOException e) {
            throw e;
        } catch (ServletException e) {
            throw e;
        }
           
        // Process a forward or include specified by this mapping
        if (!processForward(request, response, mapping)) {
            return;
        }
        if (!processInclude(request, response, mapping)) {
            return;
        }
        // Create or acquire the Action instance to process this request
        Action action = processActionCreate(request, response, mapping);
        if (action == null) {
            return;
        }
        // Call the Action instance itself
        ActionForward forward =
            processActionPerform(request, response,
                                 action, form, mapping);
        // Process the returned ActionForward instance
        processForwardConfig(request, response, forward);
    }
1) 调用processMultipart()方法
如果HTTP请求方式为post,并且contentType为”multipart/form-data”开头,标准的HttpServletRequest对象将被重新包装,以方便处理”multipart”类型的HTTP请求.如果请求方式为get,或正congtentType属性不是”mulitipart”,就直接返回原始的HttpServletRequest对象.

2) 调用processPath()方法
获得请求的URI的路径,这一信息可用于选择合适的Struts Action组件.

3) 调用processLocale方法
当ControllerConfig对象的locale属性为true,将读取用户请求中包含的Locale信息,然后把Locale实例保存在session范围内.

4) 调用processContendType(contentType)方法
读取ControllerConfig对象的conttentType属性,然后调用response.setContentType(contentType)方法,设置响应结果的文档类型和字符编码
processContent()方法如下
 protected void processContent(HttpServletRequest request,
                                  HttpServletResponse response) {
        String contentType = moduleConfig.getControllerConfig().getContentType();
        if (contentType != null) {
            response.setContentType(contentType);
        }
    }
5) 调用processNoCache()方法
读取ControllerConfig对象的nocache属性,如果nocache属性为true,在响应结果中将加入特定的头参数:Pragma,Cache-Control和Expires,
防止页面被存储在客户的浏览器的缓存中,processNoCache方法的代码如下:
protected void processNoCache(HttpServletRequest request,
                                  HttpServletResponse response) {
        if (moduleConfig.getControllerConfig().getNocache()) {
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
            response.setDateHeader("Expires", 1);
        }
    }
 
6)调用processPreprocess()方法
该方法不执行任何操作.直接返回true.子类可以覆盖这个方法.
执行客户化的预处理请求操作.

7)调用processMapping()方法
寻找和用户请求的URI匹配的ActionMapping,如果不存在这样的ActionMapping,则向用户返回恰当的错误信息.

8)调用processRoles()方法
先判断是否为Action配置了安全角色,如果配置了安全角色,就调用isUserInRole()方法判断当前用户是否具备必需的角色,如果不具备,就结束请求处理流程.,向用户返回恰当的错误消息.

9)调用processActionForm()方法
先判断是否为ActionMapping配置了ActionForm,如果配置了ActionForm,就先从ActionForm的存在范围内(request或session)寻找改ActionForm实例,如果不存在,就创建一个实例,接下来把它保存在合适的范围内,保存时使用的属性key为ActionMapping的name属性。

10)调用processPopulate()方法
如果为ActionMapping配置了ActionForm,就先调用ActionForm的reset()方法,再把请求中的表单数据组装到ActionForm中。

11)调用processValidate()方法
如果为ActionMapping配置了ActionForm,并且ActionMapping的validate属性为true,就调用ActionForm的validate()方法,如果validate方法返回的ActionErrors对象中包含ActionMessage对象,说明表单验证失败。就把ActionErrors对象放在request范围内,再把请求转发到ActionMapping的input属性指定的Web组件。如果ActionForm的validate方法执行表单验证成功,就继续执行下面的处理流程。

12)调用processForward()方法
判断是否在ActionMapping中配置了forward属性。如果配置了这个属性,就调用RequestDispatcher的forward方法,请求处理流程结束。否则进行下一步。

13)调用processInclude()方法
判断是否在ActionMapping中配置了include属性。如果配置了这个属性,就调用RequestDispatcher的include方法,请求处理流程结束。否则进行下一步。

14)调用processActionCreate()方法
先判断是否在Action缓存中存在这个Action实例,如果没有就新建一个Action实例,把它放在Action缓存中。可以看出Action也是只有一个实例在运行的。

15)调用processActionPerform
该方法调用Action实例的execute方法,该方法位于try/catch中,以及捕获异常。processActionPerform()方放代码如下。

 protected ActionForward
        processActionPerform(HttpServletRequest request,
                             HttpServletResponse response,
                             Action action,
                             ActionForm form,
                             ActionMapping mapping)
        throws IOException, ServletException {
        try {
            return (action.execute(mapping, form, request, response));
        } catch (Exception e) {
            return (processException(request, response,
                                     e, form, mapping));
        }
}

16)调用processActionForward方法
把你的Action的excute方法返回的ActionFoward对象作为参数传给它,processActionForward对象包的请求转发信息来执行请求转发或重定向。

在RequestProcessor类的process方法中,会访问ControllerConfig、ActionMappig和ActionForward实力的属性,ControllerConfig类和struts配置文件的<controlle>r元素对应,ActionMapping类和<action>元素对应,ActionForward和<forward>元素对应,process方法通过访问这三个类实例的属性来获得相关的配置信息。
写了这么多,RequestProcessor干得事够多的吧。
二.扩展RequestProcessor类
如果想修改RequestProcessor的一些默认功能,改易覆盖RequestProcessor基类中的相关方法.
Public class CustomRequestProcessor extends RequestProcessor{
  protected void processPreprocess (HttpServletRequest request,
                                 HttpServletResponse response) {
………………….
}
}
在struts配置文件中,<controller>元素的processorClass属性用于配置你自己的RequestProcessor类
</controller
contentType=“text/html:charset=”GB2312”
locale=”true” nocache=”true” processorCalss=”com.test.CustomRequestProcessor”/>



[广告] 金秋最关注楼盘-房不胜房

posted @ 2008-12-17 11:04 angelspider 阅读(341) | 评论 (0)编辑 收藏

 
 
 
 
 
Action类是用户请求和业务逻辑之间的桥梁,每个Action充当客户的一项业务代理。在RequestProcessor类预处理请求时,在创建了Action的实例后,就调用自身的processActionPerform()方法,该方法在调用Action类的execute()。
Action的excute()方法调用模型的业务方法,完成用户请求,然后根据执行结果把请求转发给其他合适的WEB组件。

一、Action类缓存

struts应用的生命周期中RequestProcessor只保证一个Action实例,所有的客户请求都共享这个实例.所有请求可以同时执行它的excute()方法。RequestProcessor类包含一个HashMap,作为存放所有Action实例的缓存。每个Action实例在缓存中存放的key为Action类名。在RequestProcessor类的processActionCreate()方法中,首先检查在HashMap中是否存在Action实例,如果有直接使用,否则创建一个新的。创建Action实力的代码位于同步代码块中,以保证只有一个线程创建Action实例,然后放在HashMap中。供其他线程使用。
如下代码
Java代码 复制代码
  1. protected Action processActionCreate(HttpServletRequest request,   
  2.                                        HttpServletResponse response,   
  3.                                        ActionMapping mapping)   
  4.       throws IOException {   
  5.   
  6.       // Acquire the Action instance we will be using (if there is one)   
  7.       String className = mapping.getType();   
  8.       if (log.isDebugEnabled()) {   
  9.           log.debug(" Looking for Action instance for class " + className);   
  10.       }   
  11.   
  12.       // :TODO: If there were a mapping property indicating whether   
  13.       // an Action were a singleton or not ([true]),   
  14.       // could we just instantiate and return a new instance here?   
  15.   
  16.       Action instance = null;   
  17.       synchronized (actions) {   
  18.   
  19.           // Return any existing Action instance of this class   
  20.           instance = (Action) actions.get(className);   
  21.           if (instance != null) {   
  22.               if (log.isTraceEnabled()) {   
  23.                   log.trace("  Returning existing Action instance");   
  24.               }   
  25.               return (instance);   
  26.           }   
  27.   
  28.           // Create and return a new Action instance   
  29.           if (log.isTraceEnabled()) {   
  30.               log.trace("  Creating new Action instance");   
  31.           }   
  32.              
  33.           try {   
  34.               instance = (Action) RequestUtils.applicationInstance(className);   
  35.               // :TODO: Maybe we should propagate this exception   
  36.               // instead of returning null.   
  37.           } catch (Exception e) {   
  38.               log.error(   
  39.                   getInternal().getMessage("actionCreate", mapping.getPath()),   
  40.                   e);   
  41.                      
  42.               response.sendError(   
  43.                   HttpServletResponse.SC_INTERNAL_SERVER_ERROR,   
  44.                   getInternal().getMessage("actionCreate", mapping.getPath()));   
  45.                      
  46.               return (null);   
  47.           }   
  48.              
  49.           instance.setServlet(this.servlet);   
  50.           actions.put(className, instance);   
  51.       }   
  52.   
  53.       return (instance);   
  54.   
  55.   }  


二.创建支持多线程的Action
1.什么是线程安全的代码
在多线程环境下能正确执行的代码就是线程安全的。
安全的意思是能正确执行,否则后果是程序执行错误,可能出现各种异常情况。

2.如何编写线程安全的代码
很多书籍里都详细讲解了如何这方面的问题,他们主要讲解的是如何同步线程对共享资源的使用的问题。主要是对synchronized关键字的各种用法,以及锁的概念。
Java1.5中也提供了如读写锁这类的工具类。这些都需要较高的技巧,而且相对难于调试。

但是,线程同步是不得以的方法,是比较复杂的,而且会带来性能的损失。等效的代码中,不需要同步在编写容易度和性能上会更好些。
我这里强调的是什么代码是始终为线程安全的、是不需要同步的。如下:
1)常量始终是线程安全的,因为只存在读操作。
2)对构造器的访问(new 操作)是线程安全的,因为每次都新建一个实例,不会访问共享的资源。
3)最重要的是:局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量。

Servlet是在多线程环境下的。即可能有多个请求发给一个servelt实例,每个请求是一个线程。 struts下的action也类似,同样在多线程环境下,你也必须编写线程安全的Action类。
保证线程安全的原则就是仅仅使用局部变量,谨慎使用实例变量(拥有状态的实例,尤其是拥有业务对象状态的实例). 如果要用到那些有状态的实例,唯一和最好的办法是在Action类中,仅仅在Action类的execute()方法中使用局部变量,对于每个调用execute()方法的线程,JVM会在每个线程的堆栈中创建局部变量,因此每个线程拥有独立的局部变量,不会被其他线程共享.当线程执行完execute()方法后,它的局部变量就会被销毁.
如果Action类的实例变量是必须的话,需要采用JAVA同步机制(synchronized)对访问共享资源的代码块进行同步


三、Struts的几种Action
Struts提供了一些现成的Action类,直接使用可以大大节省时间,如下
ForwardAction
可以转发到其他web组件,仅仅提供一个转发功能,不作处理。
IncludeAction
包含其他web组件。
DiapatchAction
通常一个Action只完成一个操作,用这个Action可以完成一组相关的操作。
LookupDispatchAction
他是DiapatchAction的子类,也可以定义多个方法,但主要用于一个表单里有多个按钮,而这些按钮又有一个共同的名字的场合。
SwitchAction
用于子模块之间的切换。


四.ActionForward类
Action类的excute()方法返回一个ActionForward对象,它代表了web资源的逻辑抽象,这里的web资源可以是jsp页面、Java servlet、或Action。
从excute返回ActionForward可以有两种方法。
1) 动态创建一个ActionForward实例
return new ActionForward(”Failure”,”login.jsp”,true);
2) 调用ActionMappin实例的findForward方法
这个方法先从action级别找,然后在<global-forwards />级别找
return mapping.findForward(“Failure”);
2007-08-03 16:58
 
 
struts 的几个action

除了基本的Action 之外, Struts 还提供了几个其他类型的Action ,这些Action 大大
丰富了Struts 的功能。下面介绍如下儿个常用的Action 。
• DispatchAction: 能同时完成多个Action 功能的Action 。
• ForwardActon: 该类用来整合Struts 和其他业务逻辑组件,通常只对请求作有效
性检查。
• IncludeAction: 用于引入其他的资源和页面。
• LookupDispatchAction: DispatchAction 的子类,根据按钮的key ,控制转发给action
的方法。
• MappingDispatchAction: DispatchAction 的子类,一个action 可映射出多个Action
地址。
• SwitchAction: 用于从一个模块转换至另一个模块,如果应用分成多个模块时,

就可以使用SwitchAction 完成模块之间的切换。
下面对常用的Action 进行介绍。
3.11.1 DispatchAction 及其子类
DispatchAction 是仅次于Action,使用最频繁的Action。用于同一个表单中有两个提
交按钮时,但提交需要的逻辑处理完全不同的情况。如图3.28 所示为登录页面。
图3.28 两个提交按钮的表单页
该页面包含了两个提交按钮,但提交按钮需要执行的逻辑却不一样。最容易想到的
解决方法是,为每个按钮增加JavaScipt脚本,提交两个按钮时候分别提交给不同的Action
处理。这是最容易想到,也最麻烦的方式。
Struts 提供了DispatchAction,可支持多个逻辑处理。对于上面的示例,表单需要两
个逻辑处理:增加和修改。下面是示例所使用的Action 类的源代码:
public class LoginAction extends DispatchAction
{
II 第一个处理逻辑
public ActionForward add(ActionMapp工ng mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse response)
throws Exception
System.out.println( "增加") ;
request. setAt tribute ("method" , "增加") ;
return mapping.findForward("success");
II第二个处理逻辑
public ActionForward modify(ActionMapping mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse response)
throws Exception
System.out.println(" 修改") ;
request. setAttribute ("method“,
"修改") ;
return mapping.findForward("success"};
上面的Action 非常简单,其两个逻辑处理也非常简单。该Action 并没有重写execute
方法,而是书写了两个自定义的方法:add 和modi句。这两个方法除了方法名与execute

方法不同之外,其他的参数列表及异常的处理完全相同。这两个方法正是execute 方法
的替代,用于完成业务逻辑的处理。
问题的关键是: Struts 如何区别不同表单提交与方法之间的对应关系?因为当使用
DispatchAction 要求表单提交时,会额外多传递一个参数,该参数用于区分到底调用
Action 中的哪个方法。
这个参数名在struts-config.xml 文件中指定。注意下面action 的配置代码:
<action path="/login" type="lee.LoginAct工on ll name="1og inForm"
scope="request" validate="true" input="/login.jsp" parameter="method">
<forward name="success" path="/welcome.jsp"/>
<fact工on>
在该action 的配置中,增加了parameter属性,该属性用于指定参数名,即Struts 将
根据该参数的值调用对应的方法。为了让请求增加method 的参数,对上面的JSP 页面代
码进行简单修改,可在JSP 页面中增加一个隐藏域,使该隐藏域的名字为method。下面
是JSP 页面的表单代码:
<html:form action="login.do">
<table border="O" width="100">
<tr>
<th align="left"><bean:message key="username"/></th>
<td align="left"><html:text property="username" size="15"/></td>
</tr>
<tr>
<th align="left"><bean:message key="pass"/></th>
<td align="left"><html:text property="pass" s ize="15"/></td>
</tr>
<tr>
<td>
<input type="hidden" name="method" value="add"/>
<input type="submit" value='<bean:message key="button.add"/>' onClick=
method.value='add'''/>
<input type="submit" value='<bean:message key="button.modify"/>'
onClick="method.value='modify'''/>
<input type="reset" value='<bean:message key="button.reset"/>'/>
<ltd>
</tr>
</table>
</html:form>
从上面的代码中可以看到,页面中增加了method 的隐藏域,该隐藏域的默认值为
add,当单击页面中的【修改】按钮时,该隐藏域的值将变成modify,单击【添加】按
钮时,该隐藏域的值变成add。这个隐藏域就是额外传递的参数值,用于告诉Dispatch
调用哪个方法来处理请求。
如果method 参数的值为add,将调用add 方法;如果method 参数的值为modify,
则调用modify 方法。因此在单击不同按钮时,DispatchAction将可自动调用对应的方法
来完成处理。
1. 使用MappingDispatchAction
MappingDispatchAction可将同一个Action 的不同方法映射成多个Action URI ,这种

Action 的写法与DispatchAction 非常相似,同样不需要重写execute 方法,而是将书写多
个自定义的方法。这些方法除了方法名与execute 方法不同外,其他的参数列表及异常
处理完全一样。
下面是本示例所使用的Action 的源代码:
public class LoginAct工on extends MappingDispatchAction
II 第一个处理逻辑
public ActionForward add(ActionMapping mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse respo口se)
throws Exception
System.out.println("增加") ;
request.setAttribute( method" , "增加") ;
return mapping.findForward("success");
}
II 第二个处理逻辑
public ActionForward modify(ActionMapping mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse response)
throws Exception
System.out.println("修改") ;
request.setAttribute( mnethod" "修改") ;
return mapping.findForward("success");
该Action 与前面的DispatchAction 没有太大的区别,仅仅改变它的父类:
MappingDispatchAction,但变化在于该Action 的配置,看下面关于该Action 的配置代码:
<1- 配置第一个Action. 实现类是lee.LoginAction , parameter 为add-->
<action path="/add" type="lee.LoginAction" name="loginForm"
scope="request" val idate="true" input="login.jsp" parameter="add">
<forward name="success" path="/welcome.jsp"l>
</action>
<! 配置第二个Action. 实现类是lee.LoginAction , parameter 为modify-->
<action path="/modify" type="lee.LoginAction" name="loginForm"
scope工"request" validate="true" input="login.jsp阴parameter="modify">
<forward name="success" path="/welcome.jsp"l>
</action>
在这种情况下,两个action 使用的是同一个Action 处理类,只是调用的方法不同,同
样也可达到上面的效果。当然也需要为页面中的两个按钮增加相应的JavaScript脚本,当
单击不同按钮时,表单可提交到不同的action,下面是JSP 页面三个按钮的源代码:
<td>
<input type="submit" value='<bean:message key="button.add"/>'
onClick="document.loginForm.action='add.do'''/>
<input type="submit" value='<bean:message key="button.modify"I>'
onClick="document.loginForm.action='modify.do'''I>
<input type="reset" value='<bean:message key="button.reset"I>'I>
<ltd>
其中,前面两个提交按钮都增加了onClick 方法,即单击该按钮时,会改变表单的提
交地址。

注意:使用MappingDispatchAction 并没有带来太大的优势,系统完全可以书写两个
Action ,分别定义两个不同的action 映射,而其他部分没有区别。
2. f吏用LookupDispatchAction
LookupDispatchAction也是DispatchAction 的一种,但它的处理更加简单。该Action
也可包含多个处理方法,它可让处理方法与按钮直接关联,无须使用任何的JavaScript
脚本。
使用LookupDispatchAction时,提交按钮必须使用Struts 的html 标签,下面是该示
例按钮部分的源代码:
<td>
<html:submit property="method">
<bean:message key="button.add"l>
</html:submit>
<html:submit property="method">
<bean:message key="button.modify"l>
</html:submit>
<input type="reset" value='<bean:message key="button.reset"I>'I>
<ltd>
代码中两个提交按钮分别增加了property 属性,该属性的值为method。而在action
的配置中,也使用parameter作为参数,看下面的action 配置代码:
<action path="/login" type="lee.LoginAction" name="loginForm"
scope="request" validate="true" input="/login.jsp" parameter="method">
<forward name="success" path="/welcome.jsp"l>
</action>
这段配置代码表明:该action 也根据method 参数来区分请求分别调用哪个方法,此
时无须使用method 的隐藏域,而是将按钮的property 设为method。通过这种方式可以
避免书写JavaScript脚本。
因此可通过重写getKeyMethodMap方法完成按钮与Action 中方法的关联,下面是
该Action 的源代码:
public class LoginAction extends LookupDispatchAction
{
II 用于关联按钮和方法
protected Map getKeyMethodMap()
Map map = new HashMap();
II如果按钮标题的key 为button.add. 则提交该按钮时对应add 方法
map .put ("button. add" , "add");
II如果按钮标题的key 为button.modify. 则提交该按钮时对应modify 方法
map.put ("button.modify" , "modify") ;
return map;
}
II 第一个处理逻辑
public ActionForward add(ActionMapping mapping, ActionForm form ,
HttpServletRequest request , HttpServletResponse response)
throws Exception
System.out.println(" 增加II) i
request.setAttribute("method" , "增加") ;
return mapping.findForward(" success") ;
}
第二个处理逻辑
public ActionForward modify(ActionMapping mapping , ActionForm form ,
HttpServletRequest request , HttpServletResponse response)
throws Exception
System.out.println("修改II) ;
request.setAttribute(" method" , " 修改") ;
return mapping.findForward("success");
LookupDispatchAction必须重写getKeyMethodMap方法,该方法返回一个Map 对象,
并在该对象内保存了按钮标题与方法之间的对应。
3.11.2 使用ForwardAction
如果需要从一个页面或资源转换到另一个资源时,直接使用页面或资源路径的超级
链接定位并不是好的做法,这使得控制器没有机会处理相关的请求事直。
使用ForwardAction可以完成请求的转发,当控制器调用ForwardAction的performO
方法时,它会使用属性parameter 所设定的路径进行forward 的动作。下面是一个设定
ForwardAction的例子:
<actlon-mapplngs>
<action path="/welcome"
type="org.apache.struts.actions.ForwardAction"
parameter="/welcome.jsp"/>
</action-mappings>
该action 仅仅完成转发,并没有执行其他的额外动作。
页面控制转发的代码如下:
<a href="welcome.do">转入</a>
当单击转入超级链接时,将可以转向ForwardAction parameter指向的资源。
3.11.3 使用IncludeAction
IncludeAction的用法与ForwardAction的用法比较相似,区别在于ForwardAction将
跳转到action 定义的资源,而IncludeAction用于引入该action 对应的资源。
下面是IncludeAction定义的源代码:
<actio口-mapplngs>
<action path="/welcome"
type="org.apache. struts.actions. IncludeAction"
parameter="/welcome.jsp"/>
</action-mappings>

该action 用于经welcome.jsp 作为资源导入。
页面中负责加载该action 所导入资源的代码如下:
<jsp:include page="welcome.do"/><br>
上面的代码将会把welcome action 定义的资源导入该页面。
3.11.4 使用SwitchAction
SwitchAction 主要用于模块之间的切换。当一个应用之中存在多个模块时,使用
SwitchAction在不同模块之间的action 之间切换还是相当方便的。
在下面的web.xml 中,力日载了Struts 的两个配置文件,其中一个作为系统的一个模
块加载,该web.xml 的配置代码如下:
<servlet>
<! 定义Struts 的核心控制器-->
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<'一指定Struts 的第一个配置文件-->
<lnlt-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-con工fg.xml</param-value>
</inlt-param>
<!一指定Struts 的第二个配置文件,作为wawa 模块配置一〉
<lnlt-param>
<param-name>config/wawa</param-name>
<param-value>/WEB-INF/struts-configl.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
该应用包括了一个wawa 的模块,并在struts-config1.xml 文件中配置一个action,该
action 的配置代码如下:
<action-mapp工ngs>
<action path="/welcome" forward="/welcome.jsp"/>
</action-mappings>
该action 的定义非常简单,仅完成页面的转向。如果现在需要从应用的页面请求该
action,可以使用如下SwitchAction。
定义SwitchAction也相当简单,只需要定义path、type 属性即可。下面是SwitchAction
的定义代码:
<action-mappings>
<action path="/moduleSwitch" type="org.apache.struts.actions.SwithcActio丑"/>
</action-mappings>
在使用SwitchAction 时,必须在请求中带两个参数:第一个是prefix,用来指定模
块宅称:另一个是page,用来指定相模块中的资源路径。下面是页面中超级链接对wawa
模块的welcome action 请求,页面的超级链接代码如下:
<a href=doduleSwitch.do?prefix=/wawa&page=/welcome.do转">入另一个模块</a>
上面的超级链接地址中,/wawa是模块名,而page对应wawa模块下的welcome的actiono

 
 





posted @ 2008-12-17 11:01 angelspider 阅读(3668) | 评论 (0)编辑 收藏