⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 building_controller.html

📁 Struts中文文档
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html><head><META http-equiv="Content-Type" content="text/html; charset=GB2312"><meta content="Craig R. McClanahan" name="author"><meta content="Xiaogang Cao" name="translator"><title>Struts 用户指南 - 构造 Controller(控制器) 部件</title></head><body vlink="#023264" alink="#023264" link="#023264" text="#000000" bgcolor="#ffffff"><table cellspacing="5" width="100%" border="0"><tr><td colspan="2"><a href="http://jakarta.apache.org"><img border="0" align="left" src="../images/jakarta-logo.gif"></a><img border="0" align="right" src="../images/struts.gif"></td></tr><tr><td colspan="2"><hr></td></tr><tr><td valign="top" width="120">

    <title>Struts 用户指南</title>

    <table cellspacing="5" border="0"><tr><th align="left" colspan="2"><font color="#023264"><strong>快速连接</strong></font></th></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="../index.html">Home</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="index.html">目录</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="introduction.html">简介</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="building_model.html">Model 部件</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="building_view.html">View 部件</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="building_controller.html">Controller 部件</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="resources.html">资源</a></font></td></tr>
      <tr><td width="15" align="center"></td><td><font size="-1"><a href="volunteers.html">我们是谁</a></font></td></tr>
    </table>

</td><td valign="top"><body>  
  <a name="building_controller"></a><table width="100%" cellpadding="5" cellspacing="5" border="0"><tr><td bgcolor="#023264"><font size="+1" face="arial,helvetica,sanserif" color="#ffffff"><strong>4. 构造 Controller (控制器)部件</strong></font></td></tr></table><a name="overview"></a><table width="100%" cellpadding="5" cellspacing="5" border="0"><tr><td bgcolor="#023264"><font size="+1" face="arial,helvetica,sanserif" color="#ffffff"><strong>4.1 纵览</strong></font></td></tr><tr><td><blockquote>
        
        <p>
        现在我们已经理解如何构造你的程序的Model(模型)和View(视图)部件,现在是时候来关注<code>Controllder</code>部件了。Struts包含一个主要功能是映射一个请求URI到一个<code>Action</code>类的servlet。因此,对于Controller你的主要责任是关于:
      </p>
      
      <ul>
        <li>为每一个可能接收的逻辑请求编写一个<code>Action</code>类(扩展自<code>org.apache.action.Action</code>)。</li>
        <li>为每一个可能提交的逻辑请求在XML中配置一个ActionMapping。这个XML配置文件通常命名为<code>struts-config.xml</code>。</li>
        <li>更新你的web程序的部署描述文件(在XML里)来包含需要的Struts部件。</li>
        <li>在你的程序里增加恰当的Struts部件。</li>
      </ul>
    </blockquote></td></tr></table><a name="action_classes"></a><table width="100%" cellpadding="5" cellspacing="5" border="0"><tr><td bgcolor="#023264"><font size="+1" face="arial,helvetica,sanserif" color="#ffffff"><strong>4.2 Action 类</strong></font></td></tr><tr><td><blockquote>
      
      <p><code>Action</code>类提供了两个可以被继承的方法,适应你的servlet环境:
      </p>

<pre>
public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             ServletRequest request,
                             ServletResponse response)
  throws IOException, ServletException;

public ActionForward perform(ActionMapping mapping,
                             ActionForm form,
                             HttpServletRequest request,
                             HttpServletResponse response)
  throws IOException, ServletException;
</pre>
      
      <p>
      大部分工程可能只需要用到"HttpServletRequest"版本。
      </p>
      <p>
      <code>Action</code>类的目标是通过它的<code>perform()</code>方法处理一个请求,返回一个<code>ActinForward</code>对象表明控制权应该被转移到哪里(例如一个JSP)作为合适的相应。在<i>MVC/Model 2</i>设计模式中,一个典型的<code>Action</code>类会在<code>perform()</code>中执行如下逻辑:
      </p>
      <ul>
        <li>检查当前用户session的状态(比如,检查用户是否已经成功登录)。如果<code>Action</code>类发现尚未登录,请求可以被转移到一个JSP页面提示让用户输入用户名和密码。当用户试图访问一个程序的“中间部分”(可能是从一个书签)的时候,或者是session已经超时,servlet容器创建了一个新的session的时候者都可能发生。</li>
        <li>如果检查还未完成的话,继续检查form bean的属性。如果发现了问题,把相应的错误的信息关键字放在request的属性里,然后把控制权重新转到输入页面来让用户改正。</li>
        <li>进行请求需要的操作(比如在数据库中保存一行数据)。这可能由<code>Action</code>内部的逻辑代码自己来完成,但是一般应该调用一个商业逻辑bean的合适的方法。</li>
        <li>更新服务器端的对象,来创建下一步用户面对的界面(典型的是request范围或者session范围的bean,取决于你需要这些条目保存多长时间)。</li>
        <li>返回一个合适的<code>ActionForward</code>对象来挑选JSP页面根据刚刚更新的bean来生成回应。典型的,你需要通过你接收到的<code>ActionMapping</code>的<code>findForward()</code>方法或者从controller servlet自身(如果你使用一个全局的逻辑名字)来得到这样的一个引用。</li>
      </ul>
        
      <p>
      在编写<code>Action</code>类代码时请记住以下几个设计要点:
      </p>
      
      <ul>
        <li>Controller servlet只创建你的<code>Action</code>类的一个实例,用来对对付所有的请求。所以,你需要处理好你的代码,在一个多线程环境下你的<code>Action</code>应该运作良好,就象你编写一个servlet的<code>service()</code>方法一样。</li>
        <li>最有助于编写线程安全的程序的原则是在你的<code>Action</code>类中只使用本地变量(local variable),而非实例变量(instance variable)。本地变量在堆栈中创建并依附于每一个独立的请求线程(由你的JVM处理),所以你不用担心共享它们。</li>
        <li>你系统中表示Model(模型)的bean由可能因为访问数据库或者其他资源而抛出异常。你应该在你的<code>perform()</code>逻辑中捕获所有的异常,把它们记录到程序的log文件中去(同时给出对应的stack trace)。可以这样做:<br>
            <code>servlet.log("Error message text", exception);</code></li>
        <li>作为一项基本的规则,分配稀少的资源并且为每一个用户在它们的session里分配一个会导致规模问题。你应该在把你的控制转移到View(视图)部件之前就释放它们(比如数据库连接)——就算你调用的bean的方法抛出了异常也要这样。</li>
      </ul>
        
      <p>
      除此之外,你还需要警惕你的<code>Action</code>类们变得太大。出现这种情况最容易的可能就是把功能逻辑放在<code>Action</code>本身,而不是在独立的商业逻辑bean。除了让<code>Action</code>类变得难以阅读和维护,这种方法还会让重用商业逻辑变得困难,因为它们被嵌入在部件内部(那个<code>Action</code>类),从而被限制在一个web程序环境中运行。
      </p>

      <p>
      只要需要的所有属性都是在方法签名中传递的(指的是通过函数调用传递?——译者注),一个<code>Action</code>可以被分散在几个本地方法中。JVM把这些属性在堆栈中处理,所以它们就是是线程安全的。
      </p>
        
      <p>
      Struts附带的例子程序只是设计用于展示某些原理,因为它自己的商业逻辑是被嵌入在<code>Action</code>类中的。这应该被理解为设计中的某种bug,而非Struts体系本身的特性,或者应该被模仿的方法。
      </p>
    </blockquote></td></tr></table><a name="actionmapping"></a><table width="100%" cellpadding="5" cellspacing="5" border="0"><tr><td bgcolor="#023264"><font size="+1" face="arial,helvetica,sanserif" color="#ffffff"><strong>4.3  ActionMapping 的实现</strong></font></td></tr><tr><td><blockquote>
      
      <p>
      为了能成功的操作,关于如何把每一个请求URI映射到恰当的<code>Action</code>类,Struts controller servlet需要知道几件事情。这些需要的知识被封装在一个叫做<code>ActionMapping</code>的Java接口中,下列是最重要的几个属性:
      </p>
      
      <ul>
        <li><b>type</b> - 在这个映射中<code>Action</code>实现的完整java类名。</li>
        <li><b>name</b> - 这个action会用到的form bean在配置文件中使用的名字</li>
        <li><b>path</b> - 请求的URL用以选择(触发)这个映射。下面会有关于匹配如何工作的例子。</li>
        <li><b>unknown</b> - 当无法找到合适的其他action来处理请求时,某个action可以被配置为默认处理这个请求,这时候把这一项置为<code>true</code>。一个程序中只能有一个action作为默认处理action。</li>
        <li><b>validate</b> - 如果这个映射中涉及的action需要在调用前先调用<code>validate()</code>方法,把这一项置为<code>true</code>。</li>
        <li><b>forward</b> - 当这个映射被调用的时候,转向一个请求URI。这是<b>type</b>属性的一个替代品。</li>

      </ul>
               
    </blockquote></td></tr></table><a name="config"></a><table width="100%" cellpadding="5" cellspacing="5" border="0"><tr><td bgcolor="#023264"><font size="+1" face="arial,helvetica,sanserif" color="#ffffff"><strong>4.4 Action Mappings 配置文件</strong></font></td></tr><tr><td><blockquote>
      
      <p>
      controller servlet是如何知道你希望的映射的?写一个小java类来创建新的<code>ActionMapping</code>的实例,并且调用每一个setter方法来赋值是可行的,但是非常繁琐。为了简化这个步骤,Struts包含一个Digester模块,它能够读取一段基于XML的关于需要的映射的描述,并创建合适的对象。参阅<a href="../api/index.html">API 文档</a>得到关于Digester的更多信息。
      </p>
        
      <p>
      开发者的责任是编写一个命名为<code>struts-config.xml</code>的XML文件,并把它放在你的程序的WEB-INF目录下。文档的格式由"struts-config_1_0.dtd"中的描述指定。最外层的XML元素必须是<code>&lt;struts-config&gt;</code>。
      </p>
      
      <p>
      在&lt;struts-config&gt;元素之内,有两个重要的元素被用于描述你的action:
        
        <blockquote>
          <b>&lt;form-beans&gt;</b><br>
          这一段包含你的form bean的定义。你为每一个form bean使用一个&lt;form-bean&gt; 元素,包含下列属性:
            <ul>
              <li>
                <b>name</b>: 这个bean的一个唯一的标识名,它将会被用来在action映射中引用来指定这个bean.通常,这也是把这个对象存放在request或者session中的属性的关键字。
              </li>
              <li>
                <b>type</b>: 你的form bean的完整的Java类名。
              </li>
            </ul>
        </blockquote>
        <blockquote>
          <b>&lt;action-mappings&gt;</b><br>
          这一段包含你的action的定义。你为你的每一个需要定义的action使用一个&lt;action&gt; 元素。每一个action元素需要定义下列的属性:
            
            <ul>
              <li>
                <b>path</b>: 这个action的程序上下文相关的路径
              </li>
              <li>
                <b>type</b>: 这个Action类的完整类名
              </li>
              <li>
                <b>name</b>: Action中所用到的&lt;form bean&gt;元素的名字
              </li>
            </ul>
          </blockquote>
        
      </p>
        

      <p>
      示例程序中的<code>struts-config.xml</code>文件包含了下列的映射元素,它们是用来实现“登录”功能的,我们用它来说明需求。注意其它的Action的条目都被剔除了:
      </p>

<pre>
&lt;struts-config&gt;
  &lt;form-beans&gt;
    &lt;form-bean
      name="logonForm"
      type="org.apache.struts.example.LogonForm" /&gt;
  &lt;/form-beans&gt;      
  &lt;global-forwards
      type="org.apache.struts.action.ActionForward" /&gt;
    &lt;forward name="logon" path="/logon.jsp"
         redirect="false" /&gt; 
  &lt;/global-forwards&gt;      
  &lt;action-mappings&gt;     
    &lt;action
        path="/logon" 
        type="org.apache.struts.example.LogonAction"
        name="logonForm"
       scope="request"
       input="/logon.jsp"
     unknown="false"
    validate="true" /&gt;          
  &lt;/action-mappings&gt;
&lt;/struts-config&gt;
</pre>      

      <p>
      首先定义的是form bean .一个基础的"<code>org.apache.struts.example.LogonForm</code>"类被映射为逻辑名"<code>logonForm</code>"。这个名字也被用在session或者request作为这个form bean的属性名。
      </p>
      <p>
      "<code>global-forwards</code>"部分用来创建全局可用的逻辑名映射。这儿的任何一个转移都可以通过调用你的action mapping的实例实现,比如<code>actionMappingInstace.findForward("logicalName")</code>。
      </p>
      <p>
      你可以看到,这个映射匹配<code>/logon</code>路径(实际上,因为实例程序用了后缀名映射,你指定的URI请求会是由<code>/logon.do</code>结尾的)。当收到一个匹配这个路径的请求时,会创建一个<code>LogonAction</code>的实例(仅当第一次),并且使用它。controller serverl会寻找一个session范围的名为<code>logonForm</code>的bean,如果需要的话,创建并保存这样的一个bean。
      </p>
      <p>
      局部的"<code>forward</code>" 元素是可选的但是非常实用。在实例程序中,很多action包含一个局部的"success"和/或"failure"转移作为Action mapping的一部分。
      </p>
<pre>
&lt;!-- Edit mail subscription --&gt;
&lt;action    path="/editSubscription"
  type="org.apache.struts.example.EditSubscriptionAction"
  name="subscriptionForm"
  scope="request"
  validate="false"&gt;
  &lt;forward name="failure" path="/mainMenu.jsp"/&gt;
  &lt;forward name="success" path="/subscription.jsp"/&gt;
  &lt;/action&gt;
</pre>   

      <p>只用了两个额外的属性,示例程序中的<code>Action</code>类变得几乎和页面设计者用的实际JSP页面的名字无关了。页面可以在重新设计的时候被改名(举个例子),只会给<code>Action</code>类带来微不足道的冲击。如果“下一个”JSP页面的名字是被硬编码在<code>Action</code>里面的话,所有的类就必须做出改动。当然,你可以决定在你的程序中使用怎样的局部转移属性。
      </p>
        
      <p>
      另一个很有用的部分是<code>&lt;data-sources&gt;</code>,它定义了你的程序可以使用的数据源。下面是你如何在你的程序的struts-config.xml中指定一个基本的数据源:
      </p>

<pre>
&lt;struts-config&gt;
  &lt;data-sources&gt;
    &lt;data-source
      autoCommit="false"
     description="Example Data Source Description"
     driverClass="org.postgresql.Driver"
        maxCount="4"
        minCount="2"
        password="mypassword"
             url="jdbc:postgresql://localhost/mydatabase"
            user="myusername"/&gt;
  &lt;/data-sources&gt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -