Struts 培训教程
1       概述
在这份教程中,将介绍struts框架和与struts框架有关的技术。该教程主要分为以下几部分:
§          MVC模式
§          Struts的概念和体系结构
§          Struts中主要技术的介绍
§          用jBuilder8开发struts应用程序
 
2       MVC模式
所谓的MVC模式,即 模型—视图—控制器(model—view--controller)模式。其结构图如下:
 
 
 
 
 
 
 
 
 
 
§          Model端
在MVC中,模型是执行某些任务的代码,而这部分代码并没有任何逻辑决定它对用户端的表示方法。Model只有纯粹的功能性接口,也就是一系列的公开方法,通过这些公开方法,便可以取得模型端的所有功能。在struts框架中,Model端是用Action和EJB技术实现的。
§          View端
在MVC模式里,一个Model可以有几个View端,而实际上复数的View端是使用MVC的原始动机。使用MVC模式可以允许多于一个的View端存在,并可以在需要的时候动态的登记上所需要的View.
§          Controller端
MVC模式的视图端是与MVC的控制器结合使用的。当用户端与相应的视图发生交互时,用户可以通过视窗更新模型的状态,而这种更新是通过控制器端进行的。控制器端通过调用模型端的方法更改其状态值。与此同时,控制器端会通知所有的登记了的视图刷新显示给用户的表示。
 
在现在的j2ee应用中,我们在开发web server时基本上都是采用MVC模式来开发的,j2ee规范也相应的为我们提供了技术支持,请看下图:
 
 
 
 
                         1                     2
                                                                  3
                                               5                  4
                         7
 
 
 
   1 浏览器用户执行servlet的doGet方法;
   2 servlet根据不同的请求,将他们分发到不同的Action中。在这里,servlet的作用就好比是controller;
   3 Action调用EJB层的商务逻辑程序处理用户的请求;
   4 EJB层返回给Action处理结果;
   5 Action 对将处理结果返回给servlet。在这里,可以将Action 和 EJB共同看成是model
   6 servlet将信息发送给JSP页面。这里的JSP就相当于view;
   7 browser用户浏览JSP页面;
大家可以看到,JSP、servlet和EJB各自在MVC模式中所起到的作用。
使用MVC的优点如下:
§          可靠性(Reliability):将表示层和处理层完全分开,可以在不重新编译model和controller的情况下修改view层。
§          复用性和适应性(reuse & adaptability):MVC使你可以使用多种view去访问相同的model。
§          快速开发(Rapid deployment):因为MVC清晰的将表示层和处理层分开,所以使得不同的程序员可以各司其则,增加开发速度。
§          可维护性(Maintainability):清晰的分层同样使得代码清晰、程序的可维护性提高。
 
3       Struts的概念和体系结构
§          概述
     struts源自于apache的jakarta工程,是一个开源代码工程(http://jakarta.apache.org/)。现在struts最新的版本是1.2,而jBuilder自带的版本是1.02。struts是一个完全遵照MVC模型设计的,web层的框架。
§          struts与MVC模式
     struts是一个完全遵照MVC模型设计的,web层的框架。在struts中,使用到了jsp、javabean、taglib和servlet技术。下图是一个描述了struts框架的应用请求的执行路径:
 
这个过程大体可以被分成5个基本步骤:
    1 view发起一个请求
2 ActionServlet(servlet技术实现)接受这个请求,它根据一份xml文件来得到处理这个请求的Action对象,并将请求发送给这个Action对象。
3 Action对象接受这个请求,并调用model(EJB)去处理这个请求,并将处理结果返回给ActionServlet。
4 ActionServlet根据Action 的返回结果中的信息,决定将处理结果返回给对应的view。
5 view得到处理结果,并将他显示给用户。
 
3.1       THE MODEL
Struts框架提供Action作为model的一种实现。Action 是继承org.apache.struts.action. Action的类,他用来处理用户的请求,并将处理结果封装在HttpServletRequest中,返回给ActionServlet。
 
3.2       THE VIEW
   Struts用JSP、taglib和javabean技术去实现view。JSP用来显示视图;struts通过使用自己定义的一组taglib来控制请求的流程、辅助处理结果的显示;javabean用来保存用户在JSP页面中的输入数据,他用来方便的向Action传递用户输入数据。
 
3.3       THE CONTROLLER
   Struts用org.apache.struts.action.ActionServlet去实现controller的功能。这个servlet接收所有JSP页面发送的请求,根据一份配置文件得到处理相应用户请求的Action,并调用Action去处理用户的请求。当Action处理结束后,ActionServlet接受处理结果,并根据同样的配置文件将处理结果发送当相应的JSP页面。
4       Struts主要技术介绍
4.1       相关技术
学习Struts,首先要了解一下以下相关技术。(有些部分只提供相关的资料链接,不做讲解)。
4.1.1    JavaBeans
大多数JavaBeans是由JavaBeans来编写的.
·   The JavaBeans Component Architecture Documentation page at 
java.sun.com, including a link to download the JavaBeans 1.01 Specification 
·   The JavaBean Trail in the Java Tutorial 
·   JavaBeans Components in JSP Pages in the Java Web Services Tutorial 
 
4.1.2    反射和内省
反射机制是一种决定一个对象哪些成员域和成员方法被采用的过程。内省技术是反射机制的一种特殊机制,Structs使用内省技术转换HTTP参数为JavaBean的属性,读取JavaBean属性装配HTML字段。
·   The Reflection Trail 
·       Chapter 8 of the JavaBeans API Specification 
4.1.3    属性文件和ResourceBundles
4.1.3.1         属性文件
属性文件主要用来设置程序属性,属性文件的后缀名为.properties,属性文件的格式类似于以下内容:
book=my  computer book  
pages=120
authors=zhf
seminar=12
4.1.3.2         使用属性文件
java.util包中Properties类用来管理一个Key/value对,Properties类提供了以下方法:
load()方法:Loading  key/value pairs into a  Properties object  form a Stream 从一个输入流中加载
getProperty()方法:Retrieving a value from its key   通过关键字来获得值
list()方法:Listing the keys and their values  列举
Save()方法:Saving the properties to a stream  保存属性
 
具体例子如下
 
import java.util.*;
import java.io.*;
public class useProperties
{
    public static void main(String[] args)
       {
              try{
                            Properties defaultProps=new Properties();
                      FileInputStream  file=new FileInputStream("test.properties");
              defaultProps.load(file);
                      file.close();
              defaultProps.list(System.out);
                      System.out.println("getProperty(String key,Stringdefault)= " 
+defaultProps.getProperty("book"));
            FileOutputStream out=new FileOutputStream("appProperties");
                     defaultProps.store(out,"-----no comment--");
                     out.close();
              }catch(Exception e)
              {
                     e.printStackTrace();
              }
       }
}
4.1.3.3         使用本地化数据
使用本地化数据,需要建立多个属性文件,假设我们系统中需要支持德文和法文,我们的默认属性文件为LabelsBundle.properties文件,那么我们需要建立德文和法文所对应的属性文件:
LabelBundle_de.properties
LabelBundle_fr.properties
 
# LabelsBundle.properties 内容
s1 = computer
s2 = disk
s3 = monitor
s4 = keyboard
 
# LabelsBundle_de.properties内容
s1 = Computer
s2 = Platte
s3 = Monitor
s4 = Tastatur
 
# LabelsBundle_fr.properties内容
s1 = Computerfr
s2 = Plattefr
s3 = Monitorfr
s4 = Tastaturfr
 
4.1.3.4         ResoureBundle和Locale                                  
通过ResourceBundle结合Locale对象可以选择属性文件:
 
下面我们给一个具体的例子
import java.util.*;
import java.io.*;
public class ResourceBundleDemo{
   public static void main(String[] args)
   {
              //采用了德国设置
              Locale  currentLocal=Locale.GERMAN;
ResourceBundle labels=ResourceBundle.getBundle("LabelsBundle",currentLocal);
              String myValue=labels.getString("s2");
          System.out.println("  Local=GERMAN ; S2= "+myValue);
              //采用了法国设置
              currentLocal=Locale.FRENCH;
        labels=ResourceBundle.getBundle("LabelsBundle",currentLocal);
        myValue=labels.getString("s2");
              System.out.println("  Local= FRENCH ; S2= "+myValue);
       }
}
更多的内容可以查看:
·   Using Properties to Manage Program Attributes in The Java Tutorial 
·   About the ResourceBundle Class in the Java Tutorial 
4.1.4    JSP和JSP标签库
Jsp中提供了一些标准的标签:
useBean,setProperty/getProperty,include,forward,plugin。
使用例子如:
<jsp:useBean  id=”bookname”  scope=”page”  class=”test.book”/>
       这些标准的标签,为操作JavaBean和相应请求等提供便利,除此之外,JSP技术允许我们自己封装特有的标签,来简化应用程序开发。有经验的开发者可以利用标签处理表单,访问数据库或其他企业服务(如e-mail或目录服务等)。
       
4.1.4.1         标签的主要技术
可以在JSP页面中设置标签的参数。
可以访问JSP页面中所有的对象。
可以获得JSP页面的Response对象。
标签之间互相通讯。
标签可以被嵌套,实现标签的多层使用。
 
 
4.1.4.2         标签的使用
为了能够在jsp页面中使用一个标签,我们需要变现一个实现了TagSupport类的java程序,然后通过tld文件,定义该标签的属性,然后通过web.xml声明这个tld文件,最后才可以在JSP页面中使用标签的。
 
下面我还是根据例子来简单讲一下
详细代码下src/taguse目录下。
4.1.4.2.1       定制标签类
package com.zhfelva.tag;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
/**
 * 一个显示当前时间的标签
*/
public class CurrentTimeTag extends TagSupport {
  public int doStartTag() {
    try {
      JspWriter out = pageContext.getOut();
      java.util.Date dt = new java.util.Date(System.currentTimeMillis());
      out.print(dt.getHours()+":"+dt.getMinutes()+":"+dt.getSeconds());
    } catch(IOException ioe) {
      System.out.println("Error in CurrentTimeTag: " + ioe);
    }
    return(SKIP_BODY);
  }
}
4.1.4.2.2       编写标签定义文件
放于\WEB-INF\taglib\mytaglib.tld
 
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
       "http://java.sun.com/j2ee/dtds/Web-jsptaglibrary_1_1.dtd">
<!-- a tag library descriptor -->
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>current time</shortname>
  <uri></uri>
  <info>
       A tag library for show current time
  </info>
  <tag>
    <name>CurrentTime</name>
    <tagclass>com.zhfelva.tag.CurrentTimeTag</tagclass>
    <bodycontent>EMPTY</bodycontent>
    <info>show current time</info>
  </tag>
</taglib>
4.1.4.2.3       在web.xml中进行配置
一个网页应用程序要在web.xml中声明他要使用的标签库:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE web-app      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2.3.dtd">
<web-app>
    <taglib>
        <taglib-uri>
                    my-taglib
        </taglib-uri>
        <taglib-location>
           /WEB-INF/taglib/mytaglib.tld
        </taglib-location>
    </taglib>
</web-app>
4.1.4.2.4       简单标签的使用
以上配置做好之后,就可以在JSP页面中使用标签了:
currenttime.jsp
<%@ page contentType="text/html;charset=gb2312" %>
<%@ taglib uri="my-taglib" prefix="mytag" %>
<HTML>
<HEAD>
<TITLE>显示当前时间 - JSP/TagLib</TITLE>
</HEAD>
<BODY>
<H1>显示当前时间 - JSP/TagLib</H1>
<mytag:CurrentTime />
</BODY>
</HTML>
 
 
 
 
Struts中真正将标签库应用了起来,大家可以从中看到标签库的强大功能。
更多的内容可以查看:
 
4.1.5    XML相关技术
这里,相关的内容非常多,而且很重要,相信大家也都熟悉XML技术,由于时间关系,这里就不做讲述了。
 
4.2       主要技术
4.2.1    Struts体系结构
 
 
控制:通过Struts体系图大家可以看到有一个XML文件Struts-config.xml,与之相关联的是Controller,在Struts中,承担MVC中Controller角色的是一个Servlet,叫ActionServlet。ActionServlet是一个通用的控制组件。这个控制组件提供了处理所有发送到Struts的HTTP请求的入口点。它截取和分发这些请求到相应的动作类(这些动作类都是Action类的子类)。另外控制组件也负责用相应的请求参数填充 Action From(通常称之为FromBean),并传给动作类(通常称之为ActionBean)。动作类实现核心商业逻辑,它可以访问java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件,后者生成视图。所有这些控制逻辑利用Struts-config.xml文件来配置。
       视图:主要由JSP生成页面完成视图,Struts提供丰富的JSP 标签库: Html,Bean,Logic,Template等,这有利于分开表现逻辑和程序逻辑。
       模型:模型以一个或多个java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用Java Bean或EJB等。
       流程:在Struts中,用户的请求一般以*.do作为请求服务名,所有的*.do请求均被指向ActionSevlet,ActionSevlet根据Struts-config.xml中的配置信息,将用户请求封装成一个指定名称的FormBean,并将此FormBean传至指定名称的ActionBean,由ActionBean完成相应的业务操作,如文件操作,数据库操作等。每一个*.do均有对应的FormBean名称和ActionBean名称,这些在Struts-config.xml中配置。
 
4.2.2    Struts的基本组件包
 
整个struts大约有15包,近200个类所组成,而且数量还在不断的扩展。在此我们不能一一介绍,只能列举几个主要的简要的介绍一下。下表说明了目前struts api中基本的几个组件包,包括action,actions,taglib。图片(5)则显现了这几个组件包之间的关系。其中action是整个struts framework的核心
| org.apache.struts.action | 
| 基本上,控制整个struts framework的运行的核心类、组件都在这个包中,比如我们上面提到的控制器ActionServlet,Action,ActionForm,ActionMapping等等。struts1.1比1.0多了 DynaActionForm 类。增加了动态扩展生成FormBean功能 | 
| org.apache.struts.actions | 
| 这个包是主要作用是提供客户的http请求和业务逻辑处理之间的特定适配器转换功能,而1.0版本中的部分动态增删FromBean的类,也在struts1.1中被Action包的DynaActionForm组件所取代 | 
| org.apache.struts.taglib | 
| 这不是一个包,而是是一个客户标签类的集合。下面包括Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags这几个用于构建用户界面的标签类。 | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
对于Struts 如何控制、处理客户请求,让我们通过对struts的四个核心组件介绍来具体说明。这几个组件就是:ActionServlet。Action Classes,Action Mapping(此处包括ActionForward),ActionFrom Bean。
4.2.3    Struts ActionServlet
    ActionServlet继承自javax.servlet.http.HttpServlet类,其在Struts framework中扮演的角色是控制器,参看上面的“Struts体系图”。控制器ActionServlet主要负责将客户的HTTP请求信息组装后,根据配置文件的指定描述,转发到适当的处理器。    按照Servelt的标准,所有得Servlet必须在web配置文件(web.xml)声明。同样,ActoinServlet必须在Web Application配置文件(web.xml)中描述,有关配置信息,后面将会介绍。
    
当用户向服务器端提交请求的时候,实际上信息是首先发送到控制器ActionServlet,一旦控制器获得了请求,其就会将请求信息传交给一些辅助类(help classes)处理。这些辅助类知道如何去处理与请求信息所对应的业务操作。在Struts中,这个辅助类就是org.apache.struts.action.Action。通常开发者需要自己继承Aciton类,从而实现自己的Action实例。
 
4.2.4    Struts Action Classes 
  
| 
public ActionForward execute(ActionMapping mapping,                              ActionForm form,                              javax.servlet.ServletRequest request,                              javax.servlet.ServletResponse response)                       throws java.io.IOException,javax.servlet.ServletException   | 
    Action类所作的工作,正如它的名称一样,就是具体的业务操作。Action类中最为常用的是execute()方法。
    当Controller收到客户的请求的时候,就会将请求转移到一个Action实例,然后会调用这个Action实例的execute()方法。Struts Framework为应用系统中的每一个Action类只创建一个实例。所有的用户都使用这一个实例, Action 类运行在一个多线程的环境中。
    
注意,客户自己继承的Action子类,必须重写execute()方法,因为Action类在默认情况下是返回null的。
 
 
4.2.5    Struts Action Mapping
上面讲到了一个客户请求是如何被控制器转发和处理的,但是,控制器如何知道什么样的信息转发到什么样的Action类呢?这就需要一些与动作和请求信息相对应的映射配置说明。在struts 中,这些配置映射信息是存储在特定的XML文件(struts-config.xml)。  
| 
<action-mappings>   <action  path="/logonAction"            type="com.test.LogonAction"            name="LogonForm"            scope="request"            input="logoncheck.jsp" validate="false"> <forward name="welcome" path="/welcome.jsp"/> <forward name="failure" path="/logon_failure.jsp "/> </action> </action-mappings>   | 
这些配置信息在系统启动的时候被读入内存,供struts framework在运行期间使用。在内存中,每一个<action>元素都与org.apache.struts.action.ActionMapping类的一个实例对应。下表就显示了一个登陆的配置映射。
Path:这个属性用来和JSP页面中,调用<html:form>时的action属性相对应,它将JSP页面和处理这个JSP页面的Action对象对应起来。
Type: 对应的Action子类的完整类名。
Name: 对应的ActionForm的名称。他与下面将描述的<form-bean>元素的name属性相应。
Scope:这个属性表示相对应的ActionForm bean 的scope属性。它的值可以是“page”、“request”、“session”和“application”。分别对应java bean的“page”、“request”、“session”和“application”属性。
Input:这个属性表示如果对应的ActionForm的validate方法返回值的ActionErrors非空,即ActionForm的属性没有通过校验,则跳转到当前的页面。
Validate: 是否调用FormBean的validate()方法来验证,关闭它之后就不会报出错误信
息了。True表示需要调用validate方法;false表示不需要调用validate方法。
    forward:定义可能的跳转路径。Name属性表示Action类的execute方法中,生成的返回结果时的参数;path表示将要跳转到的页面的路径。
 
| 
<form-beans>   <form-bean  name="LoginForm"   type="com.test.LoginForm"/> </form-beans> | 
上面的配置表示:当可以通过/logonAction.do提交请求信息的时候,控制器将信息委托com.test.LogonAction处理。调用LogonAction实例的execute()方法。同时将Mapping实例和所对应的LogonForm Bean信息传入。其中name=LogonForm,使用的form-bean元素所声明的ActionForm Bean。有关form-bean的声明如下显示。
 
<form-bean>有两个属性:
   name :这个ActionForm的名字,他与被JSP页面中的<HTML:form>元素的name属性应该是相同的。比如,如果在一个JSP页面中需要生成一个ActionForm对象,这个对象的名字(就是name属性)是“LoginForm”,则JSP页面中的<HTML:form>元素的name属性也应该是“LoginForm”。
  Type :这个ActionForm对象的完整类名。这个属性和JSP页面中的<HTML:form>元素的type属性是相对应的。
 
 
在此稍稍说一下有关global-forwards的概念。其在配置文件中描述了整个应用系统可以使用的ActionForward,而不是仅仅是一个特定的Action。
<global-forwards>元素用来表示全局的跳转页面。和<action>元素一样,他有无数个<forward>元素。当一个Action对象的execute方法执行完毕以后,如果他返回的ActionForward对象没有在这个<action>元素的<forward>子元素中有对应值的话,他将要查找<global-forwards>中的<forward>元素,并跳转到相应页面。 
| 
  <global-forwards>     <forward name="logout" path="/logout.do"/> <forward name="error"  path="/error.jsp"/>   </global-forwards> | 
 
 
| 
     <message-resources    parameter="test.ApplicationResources"/> | 
前面我们讲过Struts采用属性文件来保存应用程序的信息,那么,Struts如何知道属性文件的路径呢,也在struts-config.xml文件来配置:
<message-resource>元素用来表示ApplicationResources.properties文件的位置。这个元素有一个属性――parameter,这个属性用来表示ApplicationResources.properties文件的存放地点,但有意思的是,他是用一个类名来来表示存放路径的。比如“com. ApplicationResources”是表示存放在WEB-INF/classes / com 路径下面的ApplicationResources.properties文件。上图表示的文件路径为WEB-INF/classes /test/ApplicationResources.properties。
 
注意:以上所述的这些元素在struts-config.xml文件中的位置也是有先后顺序的。它们的顺序是:
<form-beans>
< global-forwards >
<actions>
< message-resources >
4.2.6    Struts ActionForm Bean
在上面讲解ActionServlet,Action Classes和Action Mapping的时候,我们都提到了ActionForm Bean的概念。ActionForm的主要功能就是为Action的操作提供提交表单相映射的数据。
对于每一个客户请求,Struts framework在处理ActionForm的时候,一般需要经历如下几个步骤:
(1)检查Action的映射,确定Action中已经配置了对ActionForm的映射
    (2)根据name属性,查找form bean的配置信息
    (3)检查Action的formbean的使用范围,确定在此范围下,是否已经有此form bean的实例。
    (4)假如当前范围下,已经存在了此form bean的实例,而是对当前请求来说,是同一种类型的话,那么就重用。
    (5)否则,就重新构建一个form bean的实例
    (6)form bean的reset()方法备调用
    (7)调用对应的setter方法,对状态属性赋值
    (8)如果validatede的属性北设置为true,那么就调用form bean的validate()方法。
 
 
4.3       例子讲解
在这一部分,我将根据一个简单的例子去详细的介绍一下struts框架的具体用法。
 
4.3.1    环境安装
4.3.1.1         利用Jbuilder8.0 使用Struts 1.1(版本)
     
目前Jbuilder中默认带的都是struts1.0版本,我们使用的是struts1.1版本,所以
需要手动的配置相关的类库    
第一步:Struts1.1版本的获得
可以通过访问jakarta.apche.org的方式来下载,也可以从我机器的共享目录拷贝:
IP:150.18.17.150  或机器名zhf
User: guest
PWD: 空
内容:  src文件夹下 有  Jarkarta-struts-1.1-rc1
                                          Jarkarta-struts-1.1-rc1-src
                                          Example_struts(例子文件源代码,可以用Jbuilder直接打开)
                                          Properties(属性文件使用例子)
                                          Taguse(taglib例子)
          
        还有一些资料。
 
第二步: Jbuilder配置Struts1.1
 
      首先将Struts1.1文件(包括源码)拷贝至jbuilder/thirdparty目录下:
   
 
打开jbuilder,选择tools/configure libraries,在弹出的窗口上点击new 按钮
 
Name :struts1.1
Location :Jbuilder
点击 Ok,回到刚才的界面,你会看到多出的一项struts1.1,选中它,在右边的class标签中点击Add按钮,将所带的所有jar包添加进去,最后的效果如下图:
 
 
然后选择FrameWork标签,在其中的Framework上选择Struts即可。
(这里Jbuilder会自动识别版本的)。
 
4.3.1.2         利用Jbuilder创建支持Struct1.1的工程:
 
 
首先建立一个jbuilder工程文件,名称可以自己定,这里我使用的easyuse
 
然后建立一个war文件,名称可以自己定,这里我使用的easyuse,注意在下面的选项中使用Struts1.1(Struts1.1)Frameworks
 
 
 
 
 
 
 
 
 
 
这时程序的项目浏览器内容如下
我们可以看到一个Struts1.1节点出现在树形图中,证明你前面的操作是正确的。
4.3.1.3         利用Jbuilder支持的Stucts对象创建向导:
 
   当我们点击新建按钮之后,我们可以看到在 Web标签下的其他对象。
      Struts Converter
      ActionForm
Action
JSP from ActionForm
 
大家可以跟着向导一步一步来操作。
 
4.3.2    程序编写
 
4.3.2.1         任务描述。
 
   createBook.jsp----输入一本书的标题和页码。
  bookview.jsp---正常运转之后,此界面将会获得createBook.jsp传来的title参数。
 
    再次提交之后,又回到了creatbook.jsp界面,一个循环过程。
 
 
 
 
4.3.2.2         ActionForm类
为了便于讲述,我在讲解内容写入代码中。
 
package test;
import java.util.*;
import org.apache.struts.action.*;
import org.apache.struts.validator.ValidatorForm;
import javax.servlet.http.*;
public  class BookActionForm  extends  ActionForm {
 
//这里要求 所有的自己编写的FormBean必须继承ActionForm
 
       private String title="";
       private int pages=0;
//这里的两个私有属性字段,对应了createBook.jsp中的两个文本框,Struts会自动给它们赋
//值的
       public void setTitle(String title)
       {   this.title=title;}
       public String getTitle()
       {    return this.title;}
       public void setPages(int pages)
       {   this.pages=pages;}
       public int getPages()
       {    return  this.pages;}
 
//Stuts会自动调用ActionForm的validate()方法,来对输入信息进行校验。
// validate()方法返回为ActionErrors,这如java的Exception处理机制。
 
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest) 
{
    ActionErrors errors =new ActionErrors();
    if((title==null)||(title.length()<3))
    {
            errors.add("Title", new ActionError("error.book.title"));
    }
    if(pages<1)
    {
            errors.add("Page",new ActionError("error.book.page"));
    }
    return errors;
  }
public void reset(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {
    title = null;
    pages = 0;
  }
}
 
4.3.2.3         Struts-config.xml
 
这是Struts核心文件,Struts-config.xml集中了所有页面的导航定义。对于大型的WEB项目,通过此配置文件即可迅速把握其脉络,这不管是对于前期的开发,还是后期的维护或升级都是大有裨益的。掌握Struts-config.xml是掌握Struts的关键所在。 
 
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
 
//FormBean的声明 
 <form-beans>
    <form-bean name="bookActionForm"
               type="test.BookActionForm" />
  </form-beans>
//公共跳转  
 <global-forwards>
    <forward   name="bookCreated"   path="/bookview.jsp"/>
    <forward   name="first"         path="/createBook.jsp"/>
  </global-forwards>
//action申明
  <action-mappings>
    <action  path="/createBook"
             type="test.BookAction"
             attribute="bookActionForm"
             name="bookActionForm"
             scope="request"
             validate="true"
             input="/createBook.jsp" />
  </action-mappings>
 //属性文件声明
   <message-resources      parameter="test.ApplicationResources"/>
 
 </struts-config>
 
 
4.3.2.4         Action类
 
 
package test;
 
import org.apache.struts.action.*;
import javax.servlet.http.*;
 
public class BookAction extends Action {
 
//这里要求 所有的自己编写的Action子类 必须继承Action
 
  public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
 
  System.out.println("Start perform("+actionForm+").....");
 
//我们首先从request中获得参数
  String title=httpServletRequest.getParameter("title");
  String strPages=httpServletRequest.getParameter("pages");
 
  System.out.println("getParameter  title  :"+title);
  System.out.println("getParameter Pages:"+strPages);
  System.out.println("run in this ----");
 
 //我们再从FormBean中获得参数 
title=((BookActionForm)actionForm).getTitle() ;
  strPages=""+ ((BookActionForm)actionForm).getPages() ;
  
System.out.println(" after  BookActionForm ");
System.out.println("BookActionForm  title  :"+title);
  System.out.println("BookActionForm Pages:"+strPages);
 
//跳转
  return actionMapping.findForward("bookCreated");
  }
}
 
 
 
 
 
4.3.2.5         应用程序属性文件的使用
 
在classes/test 目录下创建一个ApplicationResources.properties的文件(此路径在strut-config.xml中定义),打开它,内容如下
 
index.title=Struts 简单应用
index.content=这是Struts的一个简单应用
error.book.title=<li>书名最少要有3个字符</li>
error.book.page=<li>一本书的页数最少要大于1页</li>
errors.header=<h3><font color="red">错误<UL>
errors.footer=</UL></font><HR>
 
 
4.3.2.6         createBook.jsp页代码
 
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html:html locale="true">
<head>
<title>
//利用 bean前缀的标签, key为属性文件的关键字。
<bean:message key="index.title"/>
</title>
</head>
<body bgcolor="#ffffff">
<html:errors/>
<h1><bean:message key="index.content"/></h1>
 
//  createBook.do表示该请求交给了控制起来处理,然后拆分字符串,分解出 createBook,
// 这就是实际的请求。
 
<html:form   action="createBook.do" method="GET">
Title<html:text property="title"/><br/>
Pages<html:text property="pages"/><br/>
      <html:submit  property="submit"/>
</html:form>
</body>
</html:html>
 
 
 
 
 
 
4.3.2.7         bookview.jsp页代码
 
 
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
 
<html:html locale="true">
<head>
<html:base/>
<title>
<bean:message key="index.title"/>
</title>
</head>
<body bgcolor="white">
<h1><bean:message key="index.content"/></h1>
<html:form action="createBook" method="GET">
  title<html:text property="title"/><br/>
  <html:submit property="submit"/>
</html:form>
</body>
</html:html>
 
 
4.3.2.8         错误处理:
 
前面的流程已经实现了,下面讲一下它的错误处理机制。
这个例子程序中,需要用户输入标题和页码。
当标题的字符数小于3时和页数小于1时都是不允许的。
 
ActionForm为接收数据的类,它是错误产生的源头:
 
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {
    ActionErrors errors =new ActionErrors();
    if((title==null)||(title.length()<3))
    {
            //书名的字符数太少了
errors.add("Title", new ActionError("error.book.title"));
    }
    if(pages<1)
    {
            
//页数不能小于1
errors.add("Page",new ActionError("error.book.page"));
    }
    return errors;
  }
 
错误提示的描述  applicationResource.properties
 
error.book.title=<li>书名最少要有3个字符</li>
error.book.page=<li>一本书的页数最少要大于1页</li>
errors.header=<h3><font color="red">错误<UL>
errors.footer=</UL></font><HR>
 
对错误的选择处理
 
createBook.jsp中的处理
 
<html:errors/>
<html:errors property="Title"/>
<html:errors property="Page"/>