楼勇攀吧 关注:2贴子:146
标题
Struts 快速学习指南 (内部培训教材) 
-大部分素材来自于《Programming Jakarta Struts 》一书
lzasp800 (原作)
copy form www.CSDN.net 2004-05-05 
关键字Struts MVC 
1. Struts 简介
Struts 是一个技术框架,由Craig R. McClanahan 编写,并且在2000 年的时候捐献给了ASF ,目前,有很多组织和

个人参与Struts 框架的开发,使得Struts 保持高速成长,同时,利用Struts 开发的应用越来越多,使其成为web 应用

MVC 模式中VC 部分事实上的标准。

1.1 Web 技术历史
1.1.1 CGI 
web 应用开发中历史上,CGI(common gateway interface) 是最早使用的一种技术,通过为不同的平台,不同的
web server 编写插件编写应用接口,来满足通过web 方式编写应用的需求。当时流行的方式包含NSAPI/ISAPI ,使
用Perl 来编写CGI 程序。CGI 最大的问题就是线程并发的问题,当时给很多人的感觉是CGI 访问速度慢,其主要原
因是应用程序所编写的CGI 没有考虑多线程。

1.1.2 Servlet 
作为一种跨平台语言的服务器端技术,其一经产生就备受瞩目,采用Servlet 开发的应用,不用考虑平台,多
线程等让人头疼的问题,使得开发人员专注于业务逻辑的实现,大大解放了生产力。但是,在Servlet 中嵌入html 
无疑是开发人员的噩梦,与同时期微软的ASP 相比,Servlet 在开发效率方面让人不敢恭维。

1.1.3 Java Server Pages 
JSP 从很大程度上时参考了ASP 的想法,使得采用Java 语言开发服务器端应用非常容易,同时因为java 与生俱来的
跨平台、安全性、易用性优势,当然,还有开发人员的高工资J,使得JSP 逐渐在Web 服务器端应用开发中占据了主
流位置。



IP属地:浙江1楼2006-07-05 12:52回复
    2. Struts 安装
    Struts 作为一个J2EE 框架,很容易和你的web 应用结合起来,你仅仅需要作以下几个步骤:


    1、下在Struts1.1 二进制压缩包,将压缩包解压到%STRUTS_HOME% 目录,目录结构如下如示:

    2、建立你的标准web 应用程序,所谓标准应用程序是指在web 应用程序的根目录下有一个WEB-INFO 目录,WEB-INF 

    下有classes,lib 目录,classes 下面有个web.xml 文件。本文后续假设你的web 应用在%WEB_ROOT% 目录下。

    3、将%STRUTS_HOME%/lib 下所有文件copy 到%WEB_ROOT%/WEB-INF/lib 下。

    4、配置%WEB_ROOT%/WEB-INF/classes/web.xml 以满足Struts 需要,具体如下: 

    1、在配置文件中映射ActionServlet,ActionServlet 用于接受所有访问者的请求。在Struts 应用中,所有对

    应用程序的请求,都会被WEB SERVER 定向到ActionServlet 进行统一控制、分配处理,ActionServlet 可以

    看作是Struts 框架的核心,枢纽。

    <web-app>


    <servlet> 
    <servlet-name>controller</servlet-name> 
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 


    </servlet> 


    </web-app> 


    2、配置servlet 映射,通过servlet 映射可以将用户访问web 应用的扩展名映射到具体处理的servlet,例如, 

    将所有以.do 为扩展名的页面的请求交给ActionServlet 处理。

    <web-app>


    <servlet> 
    <servlet-name>controller</servlet-name> 
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 


    </servlet> 


    <servlet-mapping> 
    <servlet-name>controller</servlet-name> 
    <url-pattern>*.do</url-pattern> 


    </servlet-mapping>


    </web-app> 


    另外,也可以采用如下方式进行映射,该方式将所有对/action/ 目录下文件的访问请求交给ActionServlet 处
    理。

    <web-app>


    <servlet> 
    <servlet-name> controller </servlet-name> 
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 


    </servlet> 



    <servlet-mapping> 
    <servlet-name>controller</servlet-name> 
    <url-pattern>>/action/*</url-pattern> 


    </servlet-mapping> 


    </web-app> 


    3、配置ActionServlet 的初始化参数,Struts1.1 有一些指定的初始化参数,用于指明Struts 应用所需要的配

    置文件,debug 等级等。

    <web-app> 


    <servlet> 
    <servlet-name>controller</servlet-name> 
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>


    <init-param> 
    <param-name>config</param-name> 
    <param-value>/WEB-INF/struts-config.xml</param-value> 


    </init-param> 


    <init-param> 
    <param-name>host</param-name> 
    <param-value>localhost</param-value> 


    </init-param> 


    <init-param> 
    <param-name>port</param-name> 
    <param-value>7001</param-value> 


    </init-param> 


    </servlet> 


    <servlet-mapping> 
    <servlet-name> controller </servlet-name> 
    <url-pattern>*.do</url-pattern> 


    </servlet-mapping> 
    </web-app> 


    初始化参数利用<init-param> 进行配置,配置采用名称-值对的方式,一个<param-name> 对应一个<param-value>, 

    初始化参数可以任意定义,例如host,port,但是有一些在Struts1.1 中是具有特别意义的,列举如下: 

    表2-1. Struts1.1 中用到的初始化参数
    参数名含义/默认值
    config 
    以相对路径的方式指明Struts 应用程序的配置文件位置。如不设置,则默认值为

    /WEB-INF/struts-config.xml 。
    config/sub1 以相对路径的方式指明子应用程序的配置文件位置,一般来说,很少用到子应用程序,在此不多描述。
    


    IP属地:浙江2楼2006-07-05 12:53
    回复
      2025-08-26 11:12:01
      广告
      不感兴趣
      开通SVIP免广告
      debug 设置Servlet 的debug 级别,控制日志记录的详细程度。默认为0,记录相对最少的日志信息。


      设置Digester 的debug 级别,Digester 是Struts 框架所使用的用来解析xml 配置文件的一个框架,通过该

      detail 

      设置,可以查看不同详细等级的解析日志。默认为0,记录相对最少的日志信息。

      4、配置标签库,标签库是Struts 自带的一些组件库,采用JSP 规范中Tag-lib 的方式供大家使用,正

      是因为存在这么丰富的标签库,使得采用Struts 的开发才显得这么方便,高效。

      <web-app> 
      <servlet> 
      <servlet-name>controller</servlet-name> 
      <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 
      <init-param> 
      <param-name>config</param-name> 
      <param-value>/WEB-INF/struts-config.xml</param-value> 
      </init-param> 
      <init-param> 
      <param-name>host</param-name> 
      <param-value>localhost</param-value> 
      </init-param> 
      <init-param> 
      <param-name>port</param-name> 
      <param-value>7001</param-value> 
      </init-param> 
      </servlet> 


      <servlet-mapping> 
      <servlet-name>controller</servlet-name> 
      <url-pattern>*.do</url-pattern> 


      </servlet-mapping> 


      <taglib> 
      <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri> 
      <taglib-location>/WEB-INF/struts-html.tld</taglib-location> 


      </taglib> 


      <taglib> 
      <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri> 
      <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> 


      </taglib> 



      <taglib> 
      <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri> 
      <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> 


      </taglib>


      </web-app> 


      标签库采用<taglib> 定义,<taglib> 含有两个子元素,<taglib-uri> 和<taglib-location>,<taglib-uri> 
      用户定义标签库的唯一表示符,可以理解为名字,以后要在jsp 页面中使用这个标签库,靠的就是它。
      <taglib-location> 指明标签库存在的物理路径,当然,和配置文件一样,也是相对路径。

      5、设置welcome 文件列表(可选步骤) 

      <welcome-file-list> 
      <welcome-file>index.jsp</welcome-file> 
      </welcome-file-list> 


      6、设置错误处理(可选步骤),通常的http 访问异常包含404 Not Found 和500 Internal Error ,为了

      提供给用户更为友好的显示,可以做如下配置: 

      <web-app> 


      <error-page> 
      <error-code>404</error-code> 
      <location>/common/404.jsp</location> 


      </error-page> 


      <error-page> 
      <error-code>500</error-code> 
      <location>/common/500.jsp</location> 


      </error-page> 


      </web-app> 


      通过如上配置,当用户访问应用中不存在的页面时,将会将用户导向到/common/404.jsp 页面。同样地, 

      当出现异常错误时,将会把/common/500.jsp 显示给用户。

      7、最后,一个完整的web.xml 示例如下: 

      <?xml version="1.0" encoding="UTF-8"?> 


      <!DOCTYPE web-app 
      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
      "http://java.sun.com/dtd/web-app_2_3.dtd"> 


      <web-app>


      <servlet> 
      <servlet-name>storefront</servlet-name> 
      <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 
      <init-param> 


      <param-name>config</param-name> 
      <param-value>/WEB-INF/struts-config.xml</param-value> 



      </init-param>


      <init-param> 
      <param-name>debug</param-name> 
      <param-value>3</param-value> 


      </init-param> 


      <init-param> 
      <param-name>detail</param-name> 
      


      IP属地:浙江3楼2006-07-05 12:53
      回复
        J2EE 的前端控制器(Front Controller) 设计模式中利用一个前端控制器来接受所有客户请求,为应用提供一个中心控制点, 

        在该控制点上,可以很方便地添加一些全局性的,如加密、国际化、日志等通用操作。Controller 的实现机制正是建立在前端

        控制器的设计模式基础上。
        前面我们介绍过,Struts 的控制器拥有一些职责,其中最主要的是以下几个: 
        ?/SPAN> 接收客户请求。
        ?/SPAN> 映射请求到指定的业务操作。
        ?/SPAN> 获取业务操作的结果并以有效的方式提供给客户。
        ?/SPAN> 根据业务操作的结果和当前的状态把不同的UI推向给客户。
        在Struts 框架中,控制器中不同的组件负责不同的控制职责,下图是Struts 框架中关于控制器部分的一个组件图: 


        在上图中,很明显地可以看出,ActionServlet 
        处于核心位置,那么,我们就先来了解一下ActionServlet 。

        1.3.1.2 ActionServlet 类
        org.apache.struts.action.ActionServlet 在Struts 应用程序中扮演接收器的角色,所有客户端的请求在被其它类处理
        之前都得通过ActionServlet 的控制。

        当ActionServlet 的实例接收到一个HTTP 请求,不管是通过get 方法或post 方法,ActionServlet 的process( ) 方法被
        调用并用以处理客户请求。process( ) 方法实现显示如下: 

        protected void process(HttpServletRequest request,HttpServletResponse response)
        throws IOException, ServletException { 


        RequestUtils.selectApplication( request, getServletContext( ) ); 
        getApplicationConfig( request ).getProcessor( ).process( request, response ); 





        该方法的实现很简单,RequestUtils.selectApplication( request, getServletContext( ) ); 语句是
        用来根据用户访问的上下文路径来选择处理的应用,如果你只有一个Struts 配置文件,就表示你只有一个Struts 应用。
        关于如何建立多个Struts 应用,本教程不作详细讲解,请参考相应资料。
        getApplicationConfig( request ).getProcessor( ).process( request, response ); 语句用来获取一
        个处理器,并将客户请求提交给处理器处理。


        1.3.1.3 Struts 初始化处理流程
        根据在web.xml 中配置的初始化参数,Servlet 容器将决定在在容器的第一次启动,或第一次客户请求ActionServlet 的
        时机加载ActionServlet ,不管哪种方式加载,和其它Servlet 一样,ActionServlet 的init( ) 方法将被调用,开始初始化
        过程。让我们来看看在初始化过程中将发生些什么,理解了这些,对于我们debug 和扩展自己的应用更加得心应手。

        1 初始化框架的内部消息绑定,这些消息用来输出提示,警告,和错误信息到日志文件中。
        org.apache.struts.action.ActionResources 用来获取内部消息;
        2 加载web.xml 中定义的不同参数,用以控制ActionServlet 的不同行为,这些参数包括
        config, debug, detail, and convertNull ;
        3 加载并初始化web.xml 中定义的servlet 名称和servlet 映射信息。通过初始化,框架的各种DTD 被注册,DTD 用
        来在下一步校验配置文件的有效性; 
        4、为默认应用加载并初始化Struts 配置文件,配置文件即初始化参数config 指定的文件。默认配置文件被解析, 
        产生一个ApplicationConfig 对象存于ServletContext 中。可以通过关键字
        org.apache.struts.action.APPLICATION 从ServletContext 中获取ApplicationConfig; 

        5 Struts 配置文件中指定的每一个消息资源都被加载,初始化,并存在ServletContext 的合适区域(基于每个
        message-resources 元素的key 属性),如果key 属性没有设置,则为org.apache.struts.action.MESSAGE; 
        6 Struts 配置文件中声明的每一个数据源被加载并且初始化,如果没有配置数据源,这一步跳过; 
        7 加载并初始化Struts 配置文件中指定的插件。每一个插件的init() 方法被调用; 
        


        IP属地:浙江5楼2006-07-05 12:53
        回复
          8 当默认应用加载完成,init() 方法判断是否有应用模块需要加载,如果有,重复步骤4—7万成应用模块的加载。
          下图是对上面文字说明的图形化表示:

          RequestProcessor 类

          前面提到过,当ActionServlet 接收到客户请求后,会进行一连串的初始化操作,然后,就会将客户请求转交给合适的
          处理器进行处理,这个合适的处理器就是org.apache.struts.action.RequestProcessor 或其子类的一个实例(根据Struts 
          配置文件中的配置)。提供了默认实现,如果需要自定义这些行为,可以重载这个类定义自己的处理行为,当你想要自定义操
          作时,Struts 推荐你重载这个类而不是ActionServlet 。

          下面的代码片断提供了RequestProcessor 的默认行为实现代码: 

          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.isInfoEnabled( )) { 


          log.info("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; 



          // 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); 
          if (!processValidate(request, response, form, mapping)) { 


          return; 



          // 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 


          processActionForward(request, response, forward); 


          }


          IP属地:浙江6楼2006-07-05 12:53
          回复
            接下来,让我们一步一步地了解process() 方法到底做了什么。

            1、调用processMultipart( ) 方法。如果HttpServletRequest 是POST 方式,且请求为multipart/form-data , 
            Struts 框架将请求对象包装成处理multipart 请求专用的请求对象,否则,只是简单地返回原有的请求对象。一
            般来说,除非需要处理文件上传,否则不用关心multipart 功能的具体细节。

            2、调用processPath( ) 方法,该方法用来从请求URL 中获应用取路径部分。获取到的信息在稍后的步骤中用于
            选择合适的Struts Action 调用。

            3、调用processLocale( ) 方法处理一些国际化的事务。

            4、调用方法来决定processContent( ) 请求的content type 编码(encoding) 方式。content type 可以配合在配置
            文件中,也可以在jsp 文件中配置,默认为text/html 。

            5、根据noCache 属性的设置调用processNoCache( ) 方法,如果noCache 设置为true 。则添加合适的响应头到响
            应对象中,使得页面保留在浏览器的Cache 中。这些响应头包含Pragma, Cache-Control, 和Expires 。

            6、调用processPreprocess( )方法,这个方法在这儿设置一个钩子,方法的默认实现只是简单地返回true,这样
            给了自定义处理器的开发者提供了一个合适的地方让你添加自己的业务逻辑。因为这个方法在调用Action 之前
            被调用,如果你重载这个方法,只需要返回false,则Action 就不会被调用。例如,你可以重载这个方法用户检
            查客户session,如果不通过就返回false 。


            7、调用processMapping( ) 方法,根据客户请求信息中的path 信息来决定是否返回ActionMapping 对象实例。如
            果不能够找到path 的映射,则客户将会得到一个error 响应。
            8、通过调用processRoles( ) 方法检查是否为Action 配置了安全角色。如果配置了角色要求,则请求对象的
            isUserInRole( ) 方法被调用,如果用户属于这些角色,则客户会得到显示一个error 响应。
            9、调用processActionForm( ) 方法检查是否存在为ActionMapping 配置的ActionForm 。如果存在,则在有效区
            域内查找是否存在该ActionForm 的实例,存在,则复用,不存在,则创建一个实例。然后将实例保存与再配置
            文件中配置好的有效区域(request,session,application)内,并用Action 元素的name 属性作为该实例的关键字。
            10、调用processPopulate( ) 方法,如果存来存在为ActionMapping 配置的ActionForm,则封装请求对象中的数据
            到ActionForm 中,在进行封装之前,先调用ActionForm 的reset( ) 方法进行属性值的默认化。
            11、调用processValidate( ) 方法。如果ActionForm 被配置好,并且action 元素的属性validate 被设
            置为true ,则进一步调用validate( ) 方法进行规则校验。如果validate( ) 方法校验失败,就会保存一
            个ActionErrors 对象到请求区域中,请求将会自动重定向到action 映射的input 属性所指定的页面中。如
            果校验通过或在action 映射中没有配置ActionForm,则继续处理请求。
            12、根据action 映射是否配置了forward 属性或include 属性来决定下一步操作。如果配置了任意一个,则相应
            地调用RequestDispatcher 对象的forward( ) 方法或include( ) 方法,调用后,对客户请求的处理结束。否则, 
            继续处理请求。
            13、调用processActionCreate( ) 方法创建或获取一个Action 对象实例处理请求。processActionCreate( ) 方法会
            在缓存中查找是否存在已经创建好的Action 实例,如果存在,则复用,否则,则重新创建并将其村于缓存中。
            14、调用processActionPerform( ) 方法,该方法用于在一个try/catch 代码块中调用action 实例的execute( ) 方法, 
            这样确保action 的execute( ) 方法一旦发生执行异常能够被RequestProcessor 捕获。
            15、调用processActionForward( ) 方法,并传入action 的execute( ) 方法所返回的ActionForward 对象实例,方
            


            IP属地:浙江7楼2006-07-05 12:53
            回复
              法通过检查ActionForward 对象实例,决定采用redirect 或forword 方式进行重定向。究竟采用redirect 还是
              forword 取决于forward 元素的redirect 属性值。


              扩展RequestProcessor 

              如果不想利用Struts 提供的处理器,则可以扩展它。通过两个步骤即可实现: 

              1、创建一个新的类,该类必须是org.apache.struts.action.RequestProcessor 的子类;

              2、在Struts 配置文件中进行声明,例如:(粗体部分为你的自定义处理器类) 

              <controller
              contentType="text/html;charset=UTF-8" 
              debug="3" 
              locale="true" 
              nocache="true" 


              processorClass="com.struts.framework.CustomRequestProcessor"/>


              1.1.1.1 Action 类
              如果说ActionServlet 是Struts 框架的入口,RequestProcessor 是消化过滤系统,则

              org.apache.struts.action.Action 类可以说是整个框架的心脏。他是客户请求和业务操作的连接桥,也可以将其看

              作是业务操作的客户代理。

              在前面对ReqeustProcessor 类的学习中,我们了解到一旦确定并得到了一个action 实例,ReqeustProcessor 

              会调用action 的execute() 方法处理客户请求,你需要扩展action 类,并实现它的execute() 方法,在此方法中添

              加你自己的处理代码。下面给出是一个示例,这个action 用来处理用户的登录请求: 

              package com.oreilly.struts.storefront.security; 


              import java.util.Locale; 
              import javax.servlet.http.*; 
              import org.apache.struts.action.*; 
              import com.oreilly.struts.storefront.customer.view.UserView; 
              import com.oreilly.struts.storefront.framework.exceptions.BaseException; 
              import com.oreilly.struts.storefront.framework.UserContainer; 
              import com.oreilly.struts.storefront.framework.StorefrontBaseAction; 
              import com.oreilly.struts.storefront.framework.util.IConstants; 
              import com.oreilly.struts.storefront.service.IStorefrontService; 



              /** 

              * Implements the logic to authenticate a user for the Storefront application. 
              */ 
              public class LoginAction extends StorefrontBaseAction { 

              /** 

              * Called by the controller when the user attempts to log in to the 
              * Storefront application. 
              */ 
              public ActionForward execute( ActionMapping mapping, 
              ActionForm form, 
              HttpServletRequest request, 
              HttpServletResponse response ) 


               throws Exception{ 

              // The email and password should have already been validated by the ActionForm 

              String email = ((LoginForm)form).getEmail( ); 

              String password = ((LoginForm)form).getPassword( ); 

              // Log in through the security service 

              IStorefrontService serviceImpl = getStorefrontService( ); 
              UserView userView = serviceImpl.authenticate(email, password); 


              // Create a single container object to store user data 

              UserContainer existingContainer = null; 
              HttpSession session = request.getSession(false); 
              if ( session != null ){ 


               existingContainer = getUserContainer(request); 
              session.invalidate( ); 
              }else{ 



               existingContainer = new UserContainer( ); 



              // Create a new session for the user 

              session = request.getSession(true); 

              // Store the UserView in the container and store the container in the session 

              existingContainer.setUserView(userView); 
              session.setAttribute(IConstants.USER_CONTAINER_KEY, existingContainer); 

              // Return a Success forward 
              


              IP属地:浙江8楼2006-07-05 12:53
              回复

                return mapping.findForward(IConstants.SUCCESS_KEY); 



                1.1.1.1.1 Action 类缓冲
                Action 类被设计为线程安全的,在每个应用中每个Action 类只会被实例化一次,供所有线程共享。
                RequestProcessor 利用一个HashMap 用来保存Action 实例。

                思考题? 

                所有线程共享一个Action 类实例意味着什么?我们在编程中需要注意些什么呢?

                1.1.1.2 ActionForward 类
                从前面的介绍我们已经了解到,Action 的execute( ) 方法返回一个ActionForward 对象。ActionForward 对

                象是JSP 页面、Java servlet 等web 资源的抽象表现。

                ActionForward 的用途是为了减少应用和物理资源(JSP 页面,Java servlet) 的耦合,物理资源只需要在配置文件中指
                定(利用name,path 属性和forward 元素的redirect 属性),而不是在代码中指定。RequestDispatcher 利用
                ActionForward 来执行重定向操作。

                要在Action 中返回一个ActionForward 对象,你可以动态地创建一个ActionForward 对象,不过更为通用的解
                决方案是,通过在Struts 配置文件中进行action 映射,然后通过关键字去查找一个ActionForward 。下面是代码示例:


                return mapping.findForward( "Success" ); 


                上面的代码中,"Success" 作为参数被传递到ActionMapping 的findFoward( ) 方法中,findFoward( ) 方法在
                Struts 配置文件的global-forwards 区域,以及被调用的action 的forward 元素中查找名字和"Success" 相匹配的元
                素。下面是action 元素中的forward 示例:

                <action 
                input="/security/signin.jsp" 
                name="loginForm" 
                path="/signin" 
                scope="request" 
                type="com.oreilly.struts.storefront.security.LoginAction" 
                validate="true"> 


                <forward name="Success" path="/index.jsp" redirect="true"/>
                <forward name="Failure" path="/security/signin.jsp" redirect="true"/>


                </action> 


                1.1.1.1 Action 和业务逻辑
                思考题? 

                Action 属于MVC 中的Controller 还是Model?为什么? 

                1.1.1.2 使用Struts 内置的Action 
                Struts1.1 框架的org.apache.struts.actions 包中包含了5 个内置的Action ,用来执行一些通用的操作,你可以把
                它们用在你的项目中,以节省你的开发时间。接下来我们分别介绍这5 个内置的Action 。

                1.1.1.2.1 org.apache.struts.actions.ForwardAction 类
                很多情况下,你仅仅需要引导客户从一个JSP 页面跳转到另外一个JSP 页面,按照我们通常的做法,可以做一个链接让用户
                直接访问要跳转到的页面。但是MVC 模式不推荐你这么做,因为,Controller 的职责就是接收所有的客户请求,然后将
                客户请求提交给一个合适的模块进行处理,并将合适的UI 推给用户,如果直接方式JSP 页面,则跳过了Controller 的控
                制,则无法享受Controller 所提供的优点。为了解决这个问题,并且不用你去为了执行一个简单的重定向操作而创建一
                个Action 类,Struts 框架提供了ForwardAction 类,这个Action 只是简单地执行一个重定向操作,重定向的目的地
                通过parameter 属性配置。要使用ForwardAction 类,只需要在Struts 配置文件中将Action 的type 属性配置为
                org.apache.struts.actions.ForwardAction: 

                <action 
                input="/index.jsp" 
                name="loginForm" 
                path="/viewsignin" 


                parameter="/security/signin.jsp"


                scope="request" 


                type="org.apache.struts.actions.ForwardAction"



                validate="false"/> 
                </action> 


                当你访问/viewsignin 的时候,就会自动重定向到/security/signin.jsp 。

                1.1.1.2.2 org.apache.struts.actions.IncludeAction 类
                暂略

                1.1.1.2.3 org.apache.struts.actions.DispatchAction 类
                暂略

                1.1.1.2.4 org.apache.struts.actions.LookupDispatchAction 类
                


                IP属地:浙江9楼2006-07-05 12:53
                回复
                  2025-08-26 11:06:01
                  广告
                  不感兴趣
                  开通SVIP免广告
                  super( ); 
                  resetFields( ); 




                  /** 

                  * Called by the framework to validate the user has entered values in the 
                  * accessNumber and pinNumber fields. 
                  */ 
                  public ActionErrors validate(ActionMapping mapping, HttpServletRequest req ){ 
                  ActionErrors errors = new ActionErrors( ); 

                  // Get access to the message resources for this application. 


                  // There's no easy way to access the resources from an ActionForm. 

                  MessageResources resources = 
                  (MessageResources)req.getAttribute( Action.MESSAGES_KEY ); 


                  // Check and see if the access number is missing. 

                  if(accessNumber == null || accessNumber.length( ) == 0) { 
                  String accessNumberLabel = resources.getMessage( "label.accessnumber" ); 
                  ActionError newError = 

                  new ActionError("global.error.login.requiredfield", accessNumberLabel ); 
                  errors.add(ActionErrors.GLOBAL_ERROR, newError); 



                  // Check and see if the pin number is missing. 

                  if(pinNumber == null || pinNumber.length( ) == 0) { 
                  String pinNumberLabel = resources.getMessage( "label.pinnumber" ); 
                  ActionError newError = 


                  new ActionError("global.error.login.requiredfield", pinNumberLabel ); 
                  errors.add(ActionErrors.GLOBAL_ERROR, newError); 



                  // Return the ActionErrors, if any. 

                  return errors; 


                  /** 

                  * Called by the framework to reset the fields back to their default values. 
                  */ 
                  public void reset(ActionMapping mapping, HttpServletRequest request) { 
                  // Clear out the accessNumber and pinNumber fields. 
                  resetFields( ); 




                  /** 

                  * Reset the fields back to their defaults. 
                  */ 
                  protected void resetFields( ) { 
                  this.accessNumber = ""; 
                  this.pinNumber = ""; 




                  public void setAccessNumber(String nbr) { 
                  this.accessNumber = nbr; 


                  public String getAccessNumber( ) { 
                  return this.accessNumber; 



                  public String getPinNumber( ) { 

                  return this.pinNumber; 

                  public void setPinNumber(String nbr) { 


                  this.pinNumber = nbr; 




                  Struts 框架提供的ActionForm 实现了一些方法,到现在为止,最重要的两个方法是reset() 和

                  validator(): 

                  public void reset( ActionMapping mapping, HttpServletRequest request ); 
                  public ActionErrors validate( ActionMapping mapping, HttpServletRequest request ); 


                  ActionForm 对于这两个方法的默认实现是不执行任何操作,你可以重载这两个方法来执行具体的逻辑。

                  当写好了ActionForm 类之后,需要通知Struts 应用程序它的存在,以及action 和ActionForm 之间

                  的映射关系。在Struts 中,是通过配置文件来实现这一目的的。第一步,将应用所需要用到的所有ActionForm 

                  在配置文件的form-beans 这一段加以描述,下面的片断描述了如何通知Struts 应用程序这三个ActionForm 

                  的存在。

                  <form-beans> 
                  <form-bean


                  name="loginForm"


                  type="com.oreilly.struts.banking.form.LoginForm"/>
                  <form-bean


                  name="accountInformationForm"


                  type="org.apache.struts.action.DynaActionForm"> 


                  <form-property name="accounts" type="java.util.ArrayList"/> 


                  </form-bean>


                  <form-bean


                  name="accountDetailForm"


                  type="org.apache.struts.action.DynaActionForm"> 


                  <form-property


                  name="view"


                  type="com.oreilly.struts.banking.view.AccountDetailView"/> 
                  


                  IP属地:浙江11楼2006-07-05 12:53
                  回复


                    </form-bean>
                    </form-beans> 


                    每一个form bean 的name 属性必须唯一,type 属性定义了该form bean 的类,该类必须实现Struts 
                    ActionForm 类。下一步就是建立action 和form-bean 的联系,form-bean 可以和一到多个action 
                    建立联系,通过在action 元素的属性中引用form-bean 的name 即可完成映射,下面的片断显示
                    了LoginAction 和form-bean 的映射,我们之前已经看过这个片段: 

                    <action 


                    path="/login"


                    type="com.oreilly.struts.banking.action.LoginAction" 
                    scope="request" 


                    name="loginForm"


                    validate="true" 
                    input="/login.jsp"> 
                    <forward name="Success" path="/action/getaccountinformation" 
                    redirect="true"/> 
                    <forward name="Failure" path="/login.jsp" redirect="true"/> 
                    </action>



                    在Struts1.1 中,添加了一种新类型的action form ,叫做
                    org.apache.struts.action.DynaActionForm,这种类型的actionform 可以配置为action 的映射,它会
                    自动处理HTML form 中的数据并将其传递到Action 。DynaActionForm 如何做到自动处理HTML form 数据的
                    呢?DynaActionForm 内部使用一个Map 来存放HTML field 数据。

                    在接下来的一节中,我们详细了解一下DynaActionForm 。

                    1.1.1.1 使用DynaActionForm 
                    从上一节的介绍,我们可以看出,使用ActionForm 和我们自己来编写类获取HTML from 值,在进行处理相
                    比,有不少优势。ActionForm 所封装的数据和行为时几乎每一个web 应用程序都需要的,而且在一个应用中会
                    多次用到,例如一个信息实体的增加和修改,可能从不同的角度,不同的页面实现信息实体的增、改,通过
                    ActionForm 就可以复用,复用可以统一规则,减少开发时间和维护工作量。但是,现在对ActionForm 的使用越
                    来越少,为什么呢?

                    第一,也是一个最大的问题,会使得项目中存在很多ActionForm 类,增加了整个项目类的数目和维护复
                    杂度,有的开发人员为了避开这个问题,使用一个很大的,包含所有HTMLfrom 属性的ActionForm 
                    来和所有action 映射,这种方式我认为问题更多,完全失去了封装的味道。

                    第二, 当需要添加或者删除一个HTML from 属性时,如果ActionForm 需要用到这些属性,就得修改
                    ActionForm,并且要重新编译。

                    基于这些原因,在Struts1.1 框架中,添加了一种新类型的ActionForm,这种ActionForm 可以动态变化从而
                    避免创建具体的ActionForm 类。这种ActionForm 的基类是org.apache.struts.action.DynaActionForm,当
                    然,DynaActionForm 是从ActionForm 扩展而来的。对于应用来说,DynaActionForm 和ActionForm 在以下三个方面
                    会有些不同: 

                    . ActionForm 的属性定义
                    . validate() 方法
                    . reset() 方法
                    DynaActionForm 的属性不同于ActionForm,ActionForm 的属性是通过具体的类,具体的setter,getter 方法来
                    进行属性值的设置,获取,而DynaActionForm 是在Struts 的配置文件中定义的。

                    对reset() 方法调用的时机和ActionForm 并无不同,只是相对来说,在reset() 方法被调用的时候,你拥有比较
                    少的控制权。当然,可以通过扩展DynaActionForm,重载reset() 方法。


                    对于从UI 端输入的数据的校验,相对来说有些复杂,它是通过Struts Validator 组件来实现的,稍后会详细
                    介绍它。

                    1.1.1.1.1 配置DynaActionForm 
                    要使用DynaActionForm,首先得在Struts 配置文件中添加form-bean 元素。在配置文件中,DynaActionForm 和ActionForm 
                    的不同之处在于,DynaActionForm 需要添加一些form-property 元素,form-property 用来指定HTML form 中的field 名字,
                    Struts 框架会通过这些名字的匹配,自动将HTML form 各个field 的值封装到DynaActionForm 实例中。下面的片断是关于
                    


                    IP属地:浙江12楼2006-07-05 12:53
                    回复
                      下表详细介绍了validator 元素每个属性的具体含义:

                      序号属性解释
                      1. name 赋予校验规则一个唯一的名称,便于在validation-rules.xml 文件和应用指定的其
                      它校验文件中引用。
                      2. classname 指定含有具体校验规则Java Class 名, 
                      org.apache.struts.util.StrutsValidator 是Validator 框架自带
                      的一个Java Class,它实现了一些很常用的校验规则。


                      3. method 指定含有具体校验规则Java Class 的具体方法, 一个校验规则有实现校验的
                      Java Class 的一个方法来实现。
                      4. methodParams 声明method 属性所指定的方法的参数,参数之间用逗号分隔。
                      5. msg msg 是用来指定当校验不通过时,Validator 框架所给出的提示信息。它的值
                      是应用所配置的资源文件中的一个关键字,当校验失败时,Validator 框架利
                      用msg 所指定的值到应用配置的资源文件中去查找匹配记录。Validator 框架
                      默认使用以下提示信息:
                      errors.required={0} is required. 
                      errors.minlength={0} cannot be less than {1} characters. 
                      errors.maxlength={0} cannot be greater than {1} 
                      characters. 
                      errors.invalid={0} is invalid. 
                      errors.byte={0} must be a byte. 
                      errors.short={0} must be a short. 
                      errors.integer={0} must be an integer. 
                      errors.long={0} must be a long. 
                      errors.float={0} must be a float. 
                      errors.double={0} must be a double. 
                      errors.date={0} is not a date. 
                      errors.range={0} is not in the range {1} through {2}. 
                      errors.creditcard={0} is not a valid credit card number. 
                      errors.email={0} is an invalid email address 
                      可以将上面的这些信息添加到你的Struts 应用所配置的资源文件(例如:
                      ApplicationResources.properties)中,也可以修改这些值之后,将其添
                      加到配置文件中,示例如下: 
                      errors.required={0} 是必填项。
                      6. depends depends 指定在本校验规则的前置校验规则,下面的片断定义了一个最小长
                      度的校验规则,含义是在进行最小长度校验之前,会先调用required 校验
                      规则确保数据不为空: 
                      <validator 
                      name="minLength" 
                      classname="org.apache.struts.util.StrutsValidator" 
                      method="validateMinLength" 
                      methodParams="java.lang.Object, 
                      org.apache.commons.validator.ValidatorAction, 
                      org.apache.commons.validator.Field, 
                      org.apache.struts.action.ActionErrors, 
                      javax.servlet.http.HttpServletRequest" 
                      depends="required" 


                      msg="errors.minlength"> 
                      </validator> 


                      如果存在多个前置校验规则,则可以用以下的方式进行声明,各校验规则之间
                      用逗号分隔: 

                      depends="required,integer" 


                      如果前置校验规则失败,则后续的校验规则不会被执行。
                      可选属性。用来指定JavaScript 函数的名字。

                      7. 
                      jsFunctionName 

                      The final attribute supported by the validator element is the 
                      jsFunctionName attribute. This optional attribute allows you to 
                      specify the name of the JavaScript function. By default, the Validator 
                      action name is used. 

                      前面已经介绍了,org.apache.struts.util.StrutsValidator 是Validator 框架自带的一个校验规则类,其实现
                      了一些常用的校验规则,其包含的校验方法(method) 如下所列:

                      · validateByte 检查值能够安全地转换为byte 
                      · validateCreditCard 检查值是一个有效的信用卡号码
                      · validateDate 检查值是一个有效的日期
                      · validateDouble 检查值能够安全地转换为double 
                      · validateEmail 检查值是一个有效的Email 地址
                      · validateFloat 检查值能够安全地转换为double 
                      · validateInteger 检查值能够安全地转换为int 
                      


                      IP属地:浙江14楼2006-07-05 12:56
                      回复
                        · validateLong 检查值能够安全地转换为long 
                        · validateMask 检查值符合掩码规则,掩码采用规则表达式的方式
                        · validateMinLength 检查值的长度大于等于指定长度
                        · validateMaxLength 检查值的长度小于指定长度

                        · validateRange 检查值的有效范围在指定范围内
                        · validateRequired 检查值不为null 或长度>0 
                        · validateShort 检查值能够安全地转换为short 
                        .1.1.1.1.1 validation.xml 

                        Validator 框架所需要的第二个配置文件是validation.xml,这个配置文件是具体应用(项目)所特定的,可以根据你的应

                        用(项目)情况进行自定义配置。它描述了具体的ActionForm 使用validation-rules.xml 文件中的哪个校验规则进行校验。

                        validation_1_1.dtd 定义了validation.xml 的结构,根元素为form-validation ,其包含0 到多个global 元素和一到多个

                        formset 元素: 

                        <!ELEMENT form-validation (global*, formset+)> 

                        global 元素包含0 到多个constant 子元素: 

                        <!ELEMENT global (constant*)> 


                        constant 子元素和Java 里面常量的含义是一样的,下面的片断定义了两个常量: 

                        <global> 


                        <constant> 
                        <constant-name>phone</constant-name> 
                        <constant-value>^\(?(\d{3})\)?[-| ]?(\d{3})[-| ]?(\d{4})$</constant-value> 


                        </constant> 


                        <constant> 
                        <constant-name>zip</constant-name> 
                        <constant-value>^\d{5}(-\d{4})?$</constant-value> 


                        </constant> 
                        </global> 


                        上面的片断包含了两个常量,phone 和zip,这些常量在所有formset 元素中有效,在formset 中通过名称引用这些常

                        量。

                        下面的片断展示了一个简单的validation.xml 文件说明:


                        代码片断3.3.3.3.1.3.1 

                        <form-validation> 
                        <global> 
                        <constant> 


                        <constant-name>phone</constant-name>


                        <constant-value>^\(?(\d{3})\)?[-| ]?(\d{3})[-| ]?(\d{4})$</constant-value> 


                        </constant>
                        </global> 
                        <formset>


                        <form name="checkoutForm"> 
                        <field
                        property="phone" 


                        depends="required,mask">


                        <arg0 key="registrationForm.firstname.displayname"/> 
                        <var> 


                        <var-name>mask</var-name>
                        <var-value>${phone}</var-value>


                        </var>
                        </field>
                        </form>
                        </formset>


                        </form-validation> 

                        在上面的代码片断中,var 元素应用了在global 中定义了phone 常量,用来配合对phone 属性的校验。

                        formset 元素可以包含两个子元素,constant 和form 。constant 元素和global 区域定义的constant 元素格式和用途一样, 
                        只不过作用范围不同,在formset 中定义的constant 元素其作用范围只限于该formset 覆盖区域。Formset 元素中的form 元
                        素至少要出现一次。DTD 描述如下: 

                        <!ELEMENT formset (constant*, form+)> 


                        form 元素定义了需要进行校验的域,其name 属性对应应用中分配给form 的标识,在Struts 框架中,就是在Struts 配置
                        文件中form-beans 区域定义的ActionForm 的name 属性。

                        下面是form 元素的DTD 定义:

                        <!ELEMENT form (field+)> 


                        field 元素指明了JavaBean 中需要被校验的属性。在上面的代码片断中,在Struts 中,ActionForm 
                        就是这个需要被校验的JavaBean 。在代码片断3.3.3.3.1.3.1 中,定义了对Struts 配置文件中名称为


                        checkoutForm 的ActionForm 所拥有的名称为phone 的属性的校验说明,表示checkoutForm 的phone 
                        属性为必填项而且符合${phone} 所定义的正则表达式的掩码规则。field 元素的属性在下表中具体描
                        述:

                        属性描述
                        property JavaBean( 在Struts 为ActionForm)中需要被校验的属性的名称。
                        depends 应用于property 指定属性的校验规则列表, 多个校验规则之间用逗号分隔。
                        


                        IP属地:浙江15楼2006-07-05 12:56
                        回复
                          ValidatorPlugIn 实例将会依据这个值去加载配置文件。

                          1.1.1.2 使用带校验的ActionForm 
                          你不能使用标准的Struts ActionForm 去和Validator 配合使用。你必须使用专门为Validator 框架设计的ActionForm 
                          的子类。现在有两个子类可以选择,取决于你是否打算使用动态ActionForms。下面的图直观地显示了ActionForm 以及
                          它的后代: 

                          如果你打算使用动态ActionForm ,为了和Validator 框架配合使用,你可以使用DynaValidatorForm,否则,可以
                          使用ValidatorForm 。从图上看出, DynaValidatorForm 有个子类叫做DynaValidatorActionForm , 
                          ValidatorForm 有个子类叫做ValidatorActionForm,这两个子类在其父类的名字中间加了个“Action”,这两个类有什
                          么作用呢?


                          同样,根据你是否打算使用动态ActionForm ,你可以使用DynaValidatorActionForm 或
                          ValidatorActionForm ,来配合使用Validator 框架,当使用这两个类时,它们将action 的path 属性传递给Validator,Validator 
                          使用action 的名字去查找使用的校验规则。而使用DynaValidatorForm 和ValidatorForm,则是使用的ActionForm 的
                          name 属性去查找匹配校验规则。(???) 

                          1.1.1.1.1 示例
                          第一步,在Struts-config.xml 中配置一个ActionForm,示例如下: 

                          <form-bean 
                          name="checkoutForm" 
                          type="org.apache.struts.validator.DynaValidatorForm">


                          <form-property name="firstName" type="java.lang.String"/> 
                          <form-property name="lastName" type="java.lang.String"/> 
                          <form-property name="address" type="java.lang.String"/>
                          <form-property name="city" type="java.lang.String"/> 
                          <form-property name="state" type="java.lang.String"/> 
                          <form-property name="postalCode" type="java.lang.String"/> 
                          <form-property name="country" type="java.lang.String"/> 
                          <form-property name="phone" type="java.lang.String"/>


                          </form-bean> 
                          第二步,在Struts-config.xml 中配置一个Action,示例如下:


                          <action 
                          input="/checkout.jsp" 
                          name="checkoutForm" 
                          path="/checkout" 
                          scope="request" 
                          type="com.ort.struts.example.checkOutAction" 
                          validate="true"> 


                          </action> 


                          第三布,在validation.xml 文件中定义如下: 

                          <formset> 


                          <constant> 
                          <constant-name>phone</constant-name> 
                          <constant-value>^\(?(\d{3})\)?[-| ]?(\d{3})[-| ]?(\d{4})$</constant-value> 


                          </constant>


                          <constant> 
                          <constant-name>zip</constant-name> 
                          <constant-value>^\d{5}(-\d{4})?$</constant-value> 


                          </constant>



                          <form name="checkoutForm"> 


                          <field
                          property="firstName" 
                          depends="required,mask"> 
                          <arg0 key="label.firstName"/>
                          <var> 


                          <var-name>mask</var-name> 
                          <var-value>^[a-zA-Z]*$</var-value> 


                          </var>
                          </field> 
                          <field


                          property="postalCode" 
                          depends="required,mask"> 
                          <arg0 key="registrationForm.zip"/> 
                          <var> 


                          <var-name>mask</var-name> 
                          <var-value>${zip}</var-value> 


                          </var> 
                          </field> 
                          <field


                          property="phone" 
                          depends="required,mask"> 
                          <arg0 key="registrationForm.phone"/> 
                          <var> 


                          <var-name>mask</var-name> 
                          <var-value>${phone}</var-value> 
                          </var> 
                          </field>
                          </form>
                          </formset>
                          </form-validation> 


                          第四部,编写HTML 页面如下: 
                          暂略

                          1. JSP 自定义标签库
                          1.1 概述
                          在JSP 开发中会遇到一些重复的工作。而使用自定义标签库是一种方法,可以用来将这些功能封装起来并在多个项目中

                          重新用到它。此外,应用逻辑还可以包含在基于服务器的资源中,比如JavaBeans 。这种架构显示出使用自定义标签库可以
                          


                          IP属地:浙江17楼2006-07-05 12:56
                          回复
                            接起来的功能。

                            HTML form 中的每一个域对应ActionForm 的一个属性,当提交HTML from 后,Struts 根据匹配关系,将HTML from 
                            域的值赋给ActionForm 的同名属性。下表列举了form 标签的属性,并且针对每一个属性加以详细说明:

                            Struts form 标签属性列表

                            Name Description 

                            form 提交的目标地址,action 用来选择一个Struts Action 对提交后的客户请求进行处理。通过和action 的

                            path 属性进行匹配来选择Struts Action 。

                            如果在web.xml 中设置的servlet 映射是扩展名映射,则可以用以下方式进行Action 匹

                            action 

                            配(扩展名可以不作为匹配内容): 

                            <html:form action="login.do" focus="accessNumber"> 


                            上面的语句表示form 提交后,交给path 属性值为login 的Action 进行处理

                            如果在web.xml 中设置的servlet 映射是路径映射,则action 的值必须完全匹配Struts Action 的path 属性值, 
                            例如:

                            <html:form action="login" focus="accessNumber"> 

                            enctype 提交form 使用的编码方式

                            focus 页面初始化时光标定位的输入控件名

                            method 提交请求的HTTP 方式(‘POST’ or ‘GET’) 

                            name 对应的ActionForm 的名字,如果不指定,则使用Struts Action 在配置文件中name 属性所指定的ActionForm 。

                            onreset 当form 重置时执行的Javascript 

                            onsubmit 当form 提交时执行的javascript 

                            scope 与form 对应的ActionForm 的有效区域,可以为request 或session 

                            style CSS 样式表The CSS styles to be applied to this HTML element. 

                            styleClassCSS 样式类别

                            styleId HTML 元素的ID 

                            target form 提交的目标frame 

                            type form 对应的ActionForm 的类名

                            1.2 Struts Logic 标签库
                            Struts Logic 标签库中包含的标签列表

                            Tag name Description 

                            empty 如果标签parameter,propertie 等属性所指定的变量值为null 或空字符串,则处理标签包含的内容
                            如果标签parameter,propertie 等属性所指定的变量的值等于标签value 属性所指定的值,则处理标签
                            所包含的内容,如:

                            equal 

                            <logic:equal value="modify" property="action" name="projectForm"> 
                            <bean:message key="project.project_modify"/> 


                            </logic:equal> 

                            上面的示例表示,如果projectForm 的action 属性等于modify,则处理<bean:message 
                            key="project.project_modify"/> 语句。
                            forward Forward control to the page specified by the ActionForward entry. 
                            greaterEqual 
                            Evaluate the nested body content of this tag if the requested variable is greater than or equal to the 
                            specified value. 
                            greaterThan 
                            Evaluate the nested body content of this tag if the requested variable is greater than the specified 
                            value. 
                            iterate Repeat the nested body content of this tag over a specified collection. 
                            lessEqual 
                            Evaluate the nested body content of this tag if the requested variable is less than or equal to the 
                            specified value. 
                            lessThan Evaluate the nested body content of this tag if the requested variable is less than the specified value. 
                            match 
                            Evaluate the nested body content of this tag if the specified value is an appropriate substring of the 
                            requested variable. 

                            messagesNotPresentGenerate the nested body content of this tag if the specified message is not present in this request. 
                            messagesPresent Generate the nested body content of this tag if the specified message is present in this request. 
                            Evaluate the nested body content of this tag if the requested variable is neither null nor an empty 
                            


                            IP属地:浙江19楼2006-07-05 12:56
                            回复
                              2025-08-26 11:00:01
                              广告
                              不感兴趣
                              开通SVIP免广告
                              --添加主键索引

                              ALTER TABLE PROJECTS 
                              ADD ( CONSTRAINT PROJECTS_PKPROJECTCODE PRIMARY KEY (PROJECTCODE) 
                              USING INDEX ); 

                              --添加外键索引

                              CREATE INDEX FK_PROJECTSSITECODE ON PROJECTS 

                              SITECODE ASC 
                              ); 

                              --添加外键约束

                              ALTER TABLE PROJECTS 
                              ADD ( CONSTRAINT FK_PROJECTSSITECODE 
                              FOREIGN KEY (SITECODE) 
                              REFERENCES SITES ) ; 


                              --创建区域表

                              CREATE TABLE SITES ( 
                              SITECODE VARCHAR2(10) NOT NULL, 
                              SITENAME VARCHAR2(30) NOT NULL 

                              ); 


                              --添加主键

                              ALTER TABLE SITES 
                              ADD ( CONSTRAINT SITES_PKSITECODE PRIMARY KEY (SITECODE) 
                              USING INDEX ); 

                              --创建项目信息表

                              CREATE TABLE PROJECTS( 
                              PROJECTCODE VARCHAR2(10) NOT NULL, 
                              PROJECTNAME VARCHAR2(30) NOT NULL, 
                              SITECODE VARCHAR2(10) NOT NULL, 
                              DISCOUNT NUMBER NULL 

                              ); 

                              --添加主键索引

                              ALTER TABLE PROJECTS 
                              ADD ( CONSTRAINT PROJECTS_PKPROJECTCODE PRIMARY KEY (PROJECTCODE) 
                              USING INDEX ); 

                              --添加外键索引

                              CREATE INDEX FK_PROJECTSSITECODE ON PROJECTS 

                              SITECODE ASC 
                              ); 

                              --添加外键约束

                              ALTER TABLE PROJECTS 
                              ADD ( CONSTRAINT FK_PROJECTSSITECODE 
                              FOREIGN KEY (SITECODE) 
                              REFERENCES SITES ) ; 


                              1.1 命名规范
                              1、所有jsp,action 映射路径均为小写字母,如有需要可以使用小写字母+数字:例如:
                              /projectlist,/projetlist.jsp 


                              2、所有<html:form> 中的元素(如文本框,列表框等)名称都使用java 规范的变量命名方式(变量由一个或多个单词组成,
                              第一个单词小写,第一个单词后的单词首字母大写),例如:

                              <html:text styleClass="input" maxlength="10" property="projectCode" size="30"/> 
                              3、其它方面均遵守SUN 推荐的编码规范。

                              1.2 文件
                              1.2.1 projectlist.jsp 
                              该jsp 页面用来显示项目信息列表,并提供查询功能。同时,提供按钮将用户导向到添加、修改、删除功能。

                              1.2.2 projectform.jsp 
                              在执行添加、修改操作之前,需要提供一个form 供用户输入数据,在执行删除操作之前,需要提供一个form 将被删除
                              数据显示出来,供用户确认。该jsp 页面就是用来满足这些需要,提供对单条项目信息的显示,根据具体的操作类型(创建、
                              修改、删除),数据被显示在可编辑的输入控件中或不可编辑的label( 文本标签)上。

                              1.2.3 success.jsp 
                              添加、修改、删除等操作正常完成后,提供一个页面显示“恭喜”信息,使得用户能够清楚知道自己的行为已经生效J。

                              1.2.4 failed.jsp 
                              添加、修改、删除等操作异常失败,提供一个页面显示“失败”信息,使得用户能够清楚知道自己的行为已经失败L。

                              1.2.5 ProjectListSearchAction.java 
                              “Project”+”List”+”Search”+”Action”,组成了这个Action 的名字,这是我个人的命名风格,表示这个Action 会处理项
                              目列表和查询事务。在projectlist.jsp 被装载之前,ProjectListSearchAction 需要将数据加载到scope 指定的地方,供
                              projectlist.jsp 显示,当用户从projectlist.jsp 中提交查询请求,该Action 需要处理查询,并加载数据,供
                              projectlist.jsp 显示。

                              1.2.6 ProjectFormLoadAction 
                              这个Action 用来处理在显示projectform.jsp 之前,将所需要的数据加载到scope 指定的范围中,供projectform 使用。

                              1.2.7 ProjectFormSaveAction.java 
                              这个Action 用来处理用户在projectform.jsp 中提交的数据,根据用户的操作类型,完成具体的操作,并将合适的提示
                              页面(success.jsp or failed.jsp) 显示给用户。


                              1.2.8 web.xml 
                              在Struts 安装那一节,我们已经知道web.xml 文件的作用,通过这个文件,我们可以将ActionServlet 配置好,用
                              


                              IP属地:浙江21楼2006-07-05 12:56
                              回复