iLeichun

当前位置:首页Struts

struts2中s:action,s:param参数的传递与获取方法

分类:Struts  来源:网络  时间:Jun 28, 2017 11:59:31 PM
struts2中<s:action><s:param>参数怎么传递与获取?网上找了很多方法,似乎都不行,不过也可能是有什么东西漏掉了吧。后来通过几次测试,找到了一种可行的方式,特发出来分享下。代码如下:

index.jsp
<s:action name="myAction" executeResult="true" >
        <s:param name="count" value="5" />
</s:action>
备注:上述的<s:param name="count" value="5" />
也可以写成
<s:param name="count" value="5" ></s:param>
或者
<s:param name="count" >5</s:param>   <!-- 当参数值为动态时需要用这种写法 -->


struts.xml
<package name="me" extends="struts-default" namespace="">
        <action name="myAction" class="com.web.MyAction">
                   <result name="success">hello.jsp</result>
        </action>
</package>

 
MyAction.java
网上很多文章介绍说用request的getAttribute()方法去获取,但发现获取的参数是null,代码如下:
......
public String execute() {
        System.out.println(ServletActionContext.getRequest().getAttribute("count"));

       return "success";
}
......


后来经过改进,发现正确的方法是:给MyAction新增一个count属性并设置set、get方法
......
private int count;

public int getCount() {
        return count;
}

public void setCount(int count) {
        this.count = count;
}

public String execute() {
        System.out.println(count);

       return "success";
}
......

struts1和struts2有什么区别

分类:Struts  来源:网络  时间:Feb 16, 2012 10:22:39 PM

1.都是MVC的WEB框架,

2 struts1的老牌框架,应用很广泛,有很好的群众基础,使用它开发风险很小,成本更低!struts2虽然基于这个框架,但是应用群众并多,相对不成熟,未知的风险和变化很多,开发人员相对不好招,使用它开发项目的风险系数更大,用人成本更高!

3.struts2毕竟是站在前辈的基础设计出来,它会改善和完善struts1中的一些缺陷,struts1中一些悬而未决问题在struts2得到了解决。

4.struts1的前端控制器是一个Servlet,名称为ActionServlet,struts2的前端控制器是一个filter,在struts2.0中叫FilterDispatcher,在struts2.1中叫StrutsPrepareAndExecuteFilter。

5.struts1的action需要继承Action类,struts2的action可以不继承任何类;struts1对同一个路径的所有请求共享一个Action实例,struts2对同一个路径的每个请求分别使用一个独立Action实例对象,所有对于struts2的Action不用考虑线程安全问题。

6.在struts1使用formbean封装请求参数,在struts2直接使用action的属性来封装请求参数。

7.struts1中的多个业务方法放在一个Action中时(即继承DispatchAction时),要么都校验,要么都不校验;对于struts2,可以指定只对某个方法进行校验,当一个Action继承了ActionSupport且在这个类中只编写了validateXxx()方法,那么则只对Xxx()方法进行校验。

(一个请求来了的执行流程进行分析,struts2是自动支持分模块开发,并可以不同模块设置不同的url前缀,这是通过package的namespace来实现的;struts2是支持多种类型的视图;struts2的视图地址可以是动态的,即视图的名称是支持变量方式的,举例,论坛发帖失败后回来还要传递boardid。视图内容显示方面:它的标签用ognl,要el强大很多,在国际化方面支持分模块管理,两个模块用到同样的key,对应不同的消息;)

与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以Struts2中的Action是线程安全的。

struts1配置文件中的redirect视图的url不能接受参数,而struts2配置文件中的redirect视图可以接受参数。

(摘自:张孝祥老师java面试宝典)

使用ActionForward优化Struts应用程序

分类:Struts  来源:网络  时间:Oct 21, 2010 11:13:11 PM

  从一个servlet内部,通过运用javax.servlet.RequestDispatcher类的forward方法你就可以将控制流程引导到一个目的资源。在login应用程序的action类中,该代码形式如下:


  RequestDispatcher rd = request.getRequestDispatcher(destination);
  rd.forward(request, response);

  其中destination就是到一个目的资源的路径。

  但是在一个典型的Struts应用程序中,你可以用ActionForward类作为替代。运用这个类的好处就是你不再需要创建一个RequestDispatcher对象并调用它的forward方法了。

  你可以将ActionForward类用于一个Action类的execute方法中。注意,其中一个重载的execute方法有如下的定义,它返回一个ActionForward对象:


  public ActionForward execute(
  ActionMapping mapping,
  ActionForm form, HttpServletRequest request,
  HttpServletResponse response)
  throws Exception

  因为当时我们还没有讲到ActionForward类,所以在本系列的第一部分和第二部分中所有Action类的execute方法都只返回了空值。现在,在一个Action类的execute方法中,你就可以用ActionForward类来代替下面这个RequestDispatcher对象实例了:


 RequestDispatcher rd = request.getRequestDispatcher(destination);
  rd.forward(request, response);

  新的代码变成:return (new ActionForward(destination));

  构建ActionForward对象

  ActionForward类提供了下面五种构造器:


    public ActionForward()
  public ActionForward(String path)
  public ActionForward(String path, boolean redirect)
  public ActionForward(String name, String path, boolean redirect)
  public ActionForward(String name, String path, boolean redirect, boolean contextRelative)

  虽然这些构造器是不需要说明的,但我们应该注意下面几点。在这些构造器中,第二种可能是最常用的。后四种构造器中的path参数表示的是到目的资源的路径。后三种构造器中的redirect布尔值表示的是是否执行了一个重定向(redirect)。(缺省情况下,这个值设置为false,因为redirect比forward慢。)最后,第五个构造器中的contextRelative布尔值表示该路径是否应该是context-relative的,而不是module-relative的。

  同样,一个ActionForward实例也可以有一个逻辑名称,你可以用这个名称来查找与一个特殊的ActionMapping对象相关的实例。(参见本系列第四部分关于ActionMapping的讲述。)

  学习ActionForward类的方法

  ActionForward类定义了三个保护字段——name、path和redirect——它们构成了ActionForward的三个属性。ActionForward类提供getter和setter方法来从这些字段读值、给这些字段赋值。这些方法是不需要说明的,定义如下:


 public boolean getContextRelative()
  public void setContextRelative(boolean contextRelative)
  public String getName()
  public void setName(String name)
  public String getPath()
  public void setPath(String path)
  public boolean getRedirect()
  public void setRedirect(boolean redirect)

  除此之外,ActionForward类还重载了toString方法并返回:"ActionForward[" + name + "]"其中name是名称字段。

  最后,还有一个freeze方法,它固定了一个组件的配置。

  再次运用Login应用程序

  要完全了解ActionForward类,我们需要再次运用在本系列第一部分和第二部分构建的login应用程序。你可以下载完整的应用程序,把它重命名为myStrutsApp2。它的web.xml和struts-config.xml文件同myStrutsApp1中的文件是一样的,JSP页面也没有改变。只有action类同以前不同。

  注意下面这行代码是新的:return (new ActionForward("/mainMenu.jsp"));

  它替代了下面这些代码,现在它们都被注释出来了:


 RequestDispatcher rd = request.getRequestDispatcher("/mainMenu.jsp");
  rd.forward(request, response);

  同样,下面这些代码也都被重写了:


 // RequestDispatcher rd = request.getRequestDispatcher("/login.jsp");
  // rd.forward(request, response);

  新的代码变成:return (new ActionForward("/login.jsp"));

  ViewSecretAction类

  ViewSecretAction也变得更好了。execute方法最后的这三行代码现在由一行来处理了,返回(new ActionForward (“/viewSecret.jsp”)):


 //RequestDispatcher rd =request.getRequestDispatcher("/viewSecret.jsp");
  //rd.forward(request, response);
  //  return null;

  接下来,我们来重新查看LogoutAction类(见列表3)。注意execute方法中下面这些代码已经被替代了:


 // RequestDispatcher rd = request.getRequestDispatcher("/login.jsp");
  // rd.forward(request, response);
  // return null;

  你只需要用下面这一行代码来取代它就行了:return (new ActionForward("/login.jsp"));

  ActionForward是个很有用、功能很多的类,它可以让你更简单、更快、更直接地完成许多事情,这可能就是它很受欢迎的原因。在本系列的第四部分,你可以了解另一个重要的类org.apache.struts.action.ActionMapping,它可以使你的代码更有效、更漂亮。

Struts 查看文件内容功能的方法

分类:Struts  来源:网络  时间:Oct 21, 2010 11:11:14 PM

  1.Action 代码

 


 /*
  * $Id: ShowFileAction.java 471754 2006-11-06 14:55:09Z husted $
  *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership. The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License. You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
  package org.apache.struts.webapp.validator;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import org.apache.struts.action.Action;
  import org.apache.struts.action.ActionForm;
  import org.apache.struts.action.ActionForward;
  import org.apache.struts.action.ActionMapping;
  import org.apache.commons.logging.LogFactory;
  import org.apache.commons.logging.Log;
  /**
  * Action which retrieves a file specified in the parameter
  * and stores its contents in the request, so that they
  * can be displayed.
  */
  public class ShowFileAction extends Action {
  /** Logging Instance. */
  private static final Log log = LogFactory.getLog(ShowFileAction.class);
  public ActionForward execute(ActionMapping mapping,
  ActionForm form,
  HttpServletRequest request,
  HttpServletResponse response)
  throws Exception {
  // Get the file name
  String fileName = mapping.getParameter();
  StringBuffer fileContents = new StringBuffer();
  if(fileName != null) {
  InputStream input = servlet.getServletContext().getResourceAsStream(fileName);
  if (input == null) {
  log.warn("File Not Found: "+fileName);
  } else {
  InputStreamReader inputReader = new InputStreamReader(input);
  char[] buffer = new char[1000];
  while (true) {
  int lth = inputReader.read(buffer);
  if (lth < 0) {
  break;
  } else {
  fileContents.append(buffer, 0, lth);
  }
  }
  }
  } else {
  log.error("No file name specified.");
  }
  // Store the File contents and name in the Request
  request.setAttribute("fileName", fileName);
  request.setAttribute("fileContents", fileContents.toString());
  return mapping.findForward("success");
  }
  }

  分析:


 String fileName = mapping.getParameter();

  其中mapping 是ActionMapping 对象,是ActionConfig的子对象。 其中ActionConfig封装了Struts-config.xml 中的配置信息。

  inputStream input = servlet.getServletContext().getResourceAsStream(fileName);

  每个Web应用程序都是一个独立的Servlet容器,每个Web应用程序分别用一个ServletContext对象。ServletContext对象包含在ServletConfig对象中,

  调用ServletConfig.getServletContext()方法获取ServletContext对象。

  1、 getResourcePath 返回一个包含该目录和文件路径名称的Set集合

  2、 getResource 返回映射到资源上的URL对象。

  3、 getResourceAsStream 返回连接到某资源上的InputStream对象

  InputStreamReader inputReader = new InputStreamReader(input);

  需要重新包装成字符处理。

  【2】配置文件


    <!-- Show validations.xml --> 
        <action path="/showValidation"    
                        type="org.apache.struts.webapp.validator.ShowFileAction"    
                        scope="request"    
                        parameter="/WEB-INF/validator/validation.xml"> 
                <forward name="success" path="/showFile.jsp" /> 
        </action>

  通过传递不同的parameter,读取不同的文件。

  【3】在JSP页面 读取信息


    <!-- Show validations.xml --> 
        <action path="/showValidation"    
                        type="org.apache.struts.webapp.validator.ShowFileAction"    
                        scope="request"    
                        parameter="/WEB-INF/validator/validation.xml"> 
                <forward name="success" path="/showFile.jsp" /> 
        </action>

  bean:write 标签 有个filter属性。如果为true 的话,则表示

  将把输出内容中的特殊HTML符号作为普通字符串来显示;如果filter属性为false,则不会把输出内容中的HTML符号转化为普通字符串.

Struts2拦截器execAndWait简介

分类:Struts  来源:网络  时间:Oct 21, 2010 11:09:35 PM
  1、在struts.xml
 

<action name="registerclass="com.abc">
<interceptor-ref name="defaultStack"></interceptor-ref>
      <interceptor-ref name="execAndWait">
      <param name="excludeMethods">input</param>
      <!-- 等待时间,执行时间没有超过此值,将不显示等待画面 (毫秒)
      <param name="delay">1000</param>-->
      <!-- 间隔检查时间,检查后台进程有没有执行完毕,如果完成了它就立刻返回,不用等到等待,用户不会看到等待画面 
      <param name="delaySleepInterval">50</param>-->
      </interceptor-ref>
</action>
 
@Override
 public String execute() throws Exception
 {
  while(process<total){
  process++;
  Thread.sleep(900);
  System.out.println(process);
  }
  return SUCCESS;
 }
  
2、增加result

    <result name="wait">wait.jsp</result>
  3、

<%@page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>  
<%@taglib prefix="s"uri="/struts-tags"%>  
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">  
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">  
<meta http-equiv="refresh" content="1;url=<s:url includeParams="none" />"/>  
<title>
</title>
</head>
<body>
<h1>数据处理中,请稍等......</h1>
process:${process }  total:${total }
<br>
如果没有自动跳转请<a href="<s:url includeParams="all" />">点这里</a>.
其中的includeParams参数取值为:<br>
none,不把参数加入到url参数中<br>
all,是把get和post中的参数加入到url参数中<br>
get,是只把get中的参数加入到url参数中
</body>
</html>
  4、Action实现SessionAware接口
  因为这个action将会以单独的线程执行,所以你不能用ActionContext,因为它是ThreadLocal.这也就是说如果你要访问session数据,你必须实现 SessionAware结构而不是调用ActionContext.getSesion() 。

 public interface SessionAware{
  public void setSession(Map map);
  }
  public abstract class AbsBasicAction extends ActionSupport implements SessionAware{
  /** 当前 Session */
  protected Map session ;
  public void setSession(Map session) {
  this.session = session ;
  }
  }
 

struts 实例

分类:Struts  来源:网络  时间:Aug 22, 2010 12:38:07 PM

作为基于MVC模式的Web应用最经典框架,Struts已经正式推出了1.1版本,该版本在以往版本的基础上,提供了许多激动人心的新功能。本文就将带你走进Struts1.1去深入地了解这些功能。
  
  说明:希望本文的读者能有一定的Struts使用基础。
  
  1、Model 2 Struts是基于Model 2之上的,而Model 2是经典的MVC(模型-视图-控制器)模型的Web应用变体,这个改变主要是由于网络应用的特性--HTTP协议的无状态性引起的。
  
  Model 2的目的和MVC一样,也是利用控制器来分离模型和视图,达到一种层间松散耦合的效果,提高系统灵活性、复用性和可维护性。在多数情况下,你可以将Model 2与MVC等同起来。
  
  在利用Model 2之前,我们是把所有的表示逻辑和业务逻辑都集中在一起(比如大杂烩似的JSP),有时也称这种应用模式为Model 1,Model 1的主要缺点就是紧耦合,复用性差以及维护成本高。
  
  2、Struts 1.1 和Model 2
  
  既然Struts 1.1是基于Model 2之上,那它的底层机制也就是MVC,首先,控制器(ActionServlet)进行初始化工作,读取配置文件(struts-config.xml),为不同的Struts模块初始化相应的ModuleConfig对象。比如配置文件中的Action映射定义都保存在ActionConfig集合中。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和MessageResourcesConfig集合等。
  
  提示:模块是在Struts1.1中新提出的概念,在稍后的内容中我们将详细介绍,你现在可以简单地把模块看作是一个子系统,它们共同组成整个应用,同时又各自独立。Struts1.1中所有的处理都是在特定模块环境中进行的。模块的提出主要是为了解决Struts1.0中单配置文件的问题。
  
  控制器接收HTTP请求,并从ActionConfig中找出对应于该请求的Action子类,如果没有对应的Action,控制器直接将请求转发给JSP或者静态页面。否则控制器将请求分发至具体Action类进行处理。
  
  在控制器调用具体Action的execute方法之前,ActionForm对象将利用HTTP请求中的参数来填充自己(可选步骤,需要在配置文件中指定)。具体的ActionForm对象应该是ActionForm的子类对象,它其实就是一个JavaBean。
  
  此外,还可以在ActionForm类中调用validate方法来检查请求参数的合法性,并且可以返回一个包含所有错误信息的ActionErrors对象。如果执行成功,ActionForm自动将这些参数信息以JavaBean(一般称之为form bean)的方式保存在Servlet Context中,这样它们就可以被其它Action对象或者JSP调用。
  
  Struts将这些ActionForm的配置信息都放在FormBeanConfig集合中,通过它们Struts能够知道针对某个客户请求是否需要创建相应的ActionForm实例。
  
  Action很简单,一般只包含一个execute方法,它负责执行相应的业务逻辑,如果需要,它也进行相应的数据检查。执行完成之后,返回一个ActionForward对象,控制器通过该ActionForward对象来进行转发工作。
  
  我们主张将获取数据和执行业务逻辑的功能放到具体的JavaBean当中,而Action只负责完成与控制有关的功能。遵循该原则,所以在上图中我将Action对象归为控制器部分。
  
  提示:其实在Struts1.1中,ActionMapping的作用完全可以由ActionConfig来替代,只不过由于它是公共API的一部分以及兼容性的问题得以保留。ActionMapping通过继承ActionConfig来获得与其一致的功能,你可以等同地看待它们。同理,其它例如ActionForward与ForwardConfig的关系也是如此。
  
  3、模块
  
  我们知道,在Struts1.0中,我们只能在web.xml中为ActionServlet指定一个配置文件,这对于我们这些网上的教学例子来说当然没什么问题,但是在实际的应用开发过程中,可能会有些麻烦。因为许多开发人员都可能同时需要修改配置文件,但是配置文件只能同时被一个人修改,这样肯定会造成一定程度上的资源争夺,势必会影响开发效率和引起开发人员的抱怨。Struts 1.1 在Struts 1.1中,为了解决这个并行开发的问题,提出了两种解决方案:
  
  1. 多个配置文件的支持
  
  2. 模块的支持
  
  支持多个配置文件,是指你能够为ActionServlet同时指定多个xml配置文件,文件之间以逗号分隔,比如Struts提供的MailReader演示例子中就采用该种方法。
  
  
  
  action
  org.apache.struts.action.
  ActionServlet
  
   config
   /WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml
  
  
  1
  
  
  这种方法可以很好地解决修改冲突的问题,不同的开发人员可以在不同的配置文件中设置自己的Action、ActionForm等等(当然不是说每个开发人员都需要自己的配置文件,可以按照系统的功能模块进行划分)。
  
  但是,这里还是存在一个潜在的问题,就是可能不同的配置文件之间会产生冲突,因为在ActionServlet初始化的时候这几个文件最终还是需要合并到一起的。比如,在struts-config.xml中配置了一个名为success的,而在struts-config-registration.xml中也配置了一个同样的,那么执行起来就会产生冲突。
  
  为了彻底解决这种冲突,Struts 1.1中引进了模块(Module)的概念。一个模块就是一个独立的子系统,你可以在其中进行任意所需的配置,同时又不必担心和其它的配置文件产生冲突。因为前面我们讲过,ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能,需要进行以下的准备工作:
  
  1.为每个模块准备一个配置文件
  
  2.配置web.xml文件,通知控制器
  
  决定采用多个模块以后,你需要将这些信息告诉控制器,这需要在web.xml文件进行配置。下面是一个典型的多模块配置:
  
  
   config
   /WEB-INF/struts-config.xml
  
  
  
   config/customer
   /WEB-INF/struts-config-customer.xml
  
  
  
   config/order
   /WEB-INF/struts-config-order.xml
  
  
  
  要配置多个模块,你需要在原有的一个(在Struts1.1中将其对应的模块称为缺省模块)的基础之上,增加模块对应的。其中表示为config/XXX的形式,其中XXX为对应的模块名,中还是指定模块对应的配置文件。上面这个例子说明该应用有三个模块,分别是缺省模块、customer和order,它们分别对应不同的配置文件。
  
  3、准备各个模块所需的ActionForm、Action和JSP等资源
  
  但是要注意的是,模块的出现也同时带来了一个问题,即如何在不同模块间进行转发?有两种方法可以实现模块间的转发,一种就是在(全局或者本地)中定义,另外一种就是利用org.apache.struts.actions.SwitchAction。
  
  下面就是一个全局的例子:
  ...
  
  ...
  
     contextRelative="true"
  path="/moduleB/index.do"
  redirect="true"/>
  ...
  
  ...
  
  
  可以看出,只需要在原有的path属性前加上模块名,同时将contextRelative属性置为true即可。此外,你也可以在中定义一个类似的本地。
  
  
  
     type="com.ncu.test.LoginAction"
  name="loginForm"
  scope="request"
  input="tile.userLogin"
  validate="true">
     contextRelative="true"
  path="/moduleA/login.do"/>
  
  
  
  如果你已经处在其他模块,需要转回到缺省模块,那应该类似下面这样定义,即模块名为空。
  
     contextRelative="true"
  path="/login.do"/>
  
  此外,你也可以使用org.apache.struts.actions.SwitchAction,例如:
  
  ...
  
     type="org.apache.struts.actions.SwitchAction"/>
  ...
  
  ...
  
  4、ActionServlet
  
  我们首先来了解MVC中的控制器。在Struts1.1中缺省采用ActionServlet类来充当控制器。当然如果ActionServlet不能满足你的需求,你也可以通过继承它来实现自己的类。这可以在/WEB-INF/web.xml中来具体指定。
  
  要掌握ActionServlet,就必须了解它所扮演的角色。首先,ActionServlet表示MVC结构中的控制器部分,它需要完成控制器所需的前端控制及转发请求等职责。其次,ActionServlet被实现为一个专门处理HTTP请求的Servlet,它同时具有servlet的特点

 

Struts中的MVC

分类:Struts  来源:网络  时间:Aug 22, 2010 12:37:18 PM

大家都知道,Struts是基于MVC模式的Web应用框架。Struts的优点之一就是将Web应用分成控制,模型和视图。模型中仅包含业务逻辑,视图中仅包含了显示逻辑。当我经过3次基于Struts开发web应用之后,对这一点有了一点感性的认识。

一、模型与视图的独立
  所谓模型与视图的独立。实际上,就是要求我们在开发过程中,应该将模型组件和与视图有关的组件(一般是一些javabean)放在两个不同的包里。并且这两个包应该相互之间没有任何依赖关系。具体地讲就是这两个包相互都不能有导入。在视图组件这个包中除了包含javabean(通常用作DTO使用,将数据传向jsp),还应该包含一些键值的常量。因为DTO都是要存放在request范围里的,需要定义一些键值。由于这些键值是与视图密切相关的,所以不能够到处乱放,而是一定要放在视图组件包内。而模型组件包在开发过程中,你要完全抛开Struts和jsp,就当这些完全不存在,这样开发出来的模型组件即使将来换一个界面(例如:Swing)时,就可以很容易的重用。

二、控制的独立
  首先,控制部分是由Struts软件提供的。Struts软件当然无法与你开发的视图和模型有依赖关系,因为Struts在开发的时候,你的模型和视图还没有开发出来呢。Strutst提供了Action这个父类,相当于提供了一个接口,所有具体的执行细节都由Action扩展类来实现。这样Struts框架将控制和控制的内容进行类分离,保证了控制与控制的内容(模型和视图)的独立性。 当然,你在开发模型和视图部分时也不要依赖控制部分,即,不要在你的软件包中导入org.apache.struts包及其子包中的类。只有这样才能真正保持MVC之间的独立性。

三、扩展Action类
  前两点主要都在谈独立性。但是,一旦讲到扩展Action类,可以说所有的依赖关系都发生在这里。大家都知道,Action扩展类,负责调用模型和选择视图,那么当你在开发这些Action扩展类的时候,就需要导入模型组件包和视图组件包。也有是说Action依赖模型和视图。由于Action扩展类还有继承Action自类。Action类是控制的一部分,因为它位于org.apache.struts.action包中。所以Action扩展类还依赖控制组件。这样看来,Action扩展类仿佛是Struts这个框架中胶水,它依赖模型、视图和控制部分的组件,MVC这三个部分都是通过它来紧密联系在一起的。

四、总结
  Struts框架强调MVC的独立,所以在开发时,视图组件、模型组件最好放在一个单独的包中,Action扩展类也放在一个单独的包里。Struts软件包、模型组件包和视图组件包应该相互隔离,彼此没有导入关系。而Action扩展类却依赖所有这三者。Action扩展类仿佛是胶水将MVC联系到了一起。