祸兮福所倚,福兮祸所伏

想随便当个小职员,随便赚点钱然后随便和一个不美也不丑的普通女孩结婚,随便生两个孩子,先生个女孩再生个男孩。等女儿结婚,儿子也能够独挡一面的时候,然后就退休,然后每天过着下着象棋和围棋的悠闲生活。然后在自己的老婆死之前自己先老死这种生活多美好呀!

BlogJava 首页 新随笔 联系 聚合 管理
  0 Posts :: 8 Stories :: 0 Comments :: 0 Trackbacks

    开发基于浏览器的客户端总是会遇到表单重复提交的问题。很明显的在一个商业应用中重复提交是不希望发生的。struts提供一个机制,使用Action基类的generateToken方法产生一个token来保护模型层避免受到表单多次提交的影响。为了控制事务的完整性和原子性,在使用ActionForward选择下一个视图前要调用request handler的saveToken方法。saveToken方法调用generateToken方法创建一个唯一标识符,然后用Action.TRANSACTION_TOKEN_KEY保存到session中。表单标签从session中获得token然后用Constants.TOKEN_KEY保存到隐藏字段中。在接下来的请求中,request handler通过调用action基类的isTokenValid方法检查token的合法性。如果该方法返回false,request handler必须实现合适的逻辑处理遇到的问题。一个处理的例子如下所示:
    if (!isTokenValid(request)) {
      errors.add(ActionErrors.GLOBAL_ERROR,
      new ActionError("transaction.token.invalid"));
      //errors object is of type ActionErrors
    }
    isTokenValid同步处理session对象的token来阻止表单重复提交请求。在request handlers中,isTokenValid方法必须跟一个resetToken来从session中移除token;这样可以保证任何后续请求都将导致isTokenValid返回fa,因此组织表单多次提交。request handler的saveToken方法应该被调用来重建一个新的事务token满足下次的请求。
    获得表单数据
    jsp规范使用在请求时的JavaBeans中提取和存储表单数据。然而,这种方式使表现层和JavaBeans强耦合;而且HTML文档的创建者还必须知道这些组件以及他们在页面中的正确用法。因为JavaBeans能够通过标签或另一个服务器组件在一个特定的范围创建和使用,这样可能会造成在不同组件共享的JavaBean的生命周期管理产生问题。struts提供了一个机制提取,存储,校验表单数据。同时也客服了的缺点。例子略。
    例子映射一个JavaBean类型为packageName.customerProfileForm用name=customerProfileForm (唯一标识),name=customerProfileForm; request handler通过输入请求中的路径/editCustomerProfile唯一标识。 表单的创建和使用在下面的图片中解释。

    首先,我们将用一个简单的JavaBeans对象研究表单的处理机制。这些对象是作为ActionForm对象实现的。我们接下来要讨论使用DynaActionForm进行表单处理,这个DynaActionForm对象能够支持才请求时动态设置属性。


    用FormTag初始化ActionForm对象
    用前面介绍的方式FormTag初始化ActionForm对象,在HTML表单中的action URL对应配置节点,该节点通过配置对于formbean。FormTag的action属性定义的URL通过配置描述文件中的的路径结构转换成URL。通过扩展名映射,实现了用    FormTag调用RequestUtils.createActionForm方法,该方法通过名字匹配元素的名字来搜索ActionFormBean配置对象((ActionFormBean是运行时表现形式)。使用元素创建一个新的ActionForm实例,如实例存在,则FormTag会在存在的form bean调用ActionForm.reset方法清除数据,为下一次请求的表单数据做准备。范围定义在元素的scope属性中;新的ActionForm实例或者重新初始化的实例保存在该属性定义的范围中。


    用ActionForm存储表单数据   
    被继承的ActionForm对象是用来存放表单请求对象参数的,因此他们是和用户紧耦合的。一个ActionForm子类是一个带属性存取方法的JavaBean,这些属性与HttpServletRequest对象的参数对应。如果一个ActionForm对象通过FormTag创建(前面介绍了),那么在接下来通过FormTag解析的表单请求将由RequestProcessor在特定范围处理。表单通过相关的action映射标识找到。RequestProcessor为重置表单属性,通常表单带有请求时间参数,然后调用表单对象的validate方法完成服务端校验用户输入。仅当ActionMapping对象的校验属性设为true时,validate方法才会被调用。这是一个默认的行为。使用request.getParameterValues(parameterName)获得一个String数组对象,这个对象用来存放表单数据;在请求参数类型转换一节将做解释。校验结构是一个ActionErrors对象(在错误处理一节解释了),它使用org.apache.struts.taglib.html.ErrorsTag显示校验错误给用户。ActionForm也能存储中间层模型状态,这些状态数据接下来会视图(jsp)引用并展示给用户。
    一个ActionForm类也可以被RequestProcessor创建。这种情况发生在导航到URL,该URL映射到控制器servlet而不是jsp,相关的action映射定义了表单属性。在这种情况下,RequestProcessor搜索form bean的尝试会导致创建一个新的ActionForm对象,如果在特定范围没有找到的话,或者在特定范围通过元素的名字属性找到ActionForm对象;当一个表单对象被RequestProcessor找到,将传递给请求处理对象的execute方法。一个ActionForm对象也能被请求处理器创建。
    表单对象的创建的目的是为了提供中间层模型状态给jsp时应该使用请求范围;这样可以保证在他们的有效性过期后对象不会再被使用。默认的所有表单保存在session范围。在session中存在的表单对象超过了他们的有效性范围会导致浪费内存,因此,请求处理者必须跟踪存储在session中的表单对象的生命周期。获得表单数据的一个好的实践是用单一的form bean关联跨越服务端用户交互的表单。form beans也能够存储中间层模型状态,这个状态在相应用户时,通过定制的标签适配到用户视图中。标签用来避免在视图层混合java代码,因此导致了一个好的分工,web开发团队处理标记,应用开发团队处理java代码。标签区分了中间层处理逻辑;这些逻辑可能相当复杂,比如处理嵌套对象或通过集合迭代对象。

    用动态属性创建ActionForm对象
    DynaActionForm对象是带动态集合属性的对象。DynaActionForm扩展了ActionForm对象;通过在struts-config.xml文件中声明来创建form对象。例子略。RequestProcessor创建,操作,校验DynaActionForm的方式和操作ActionForm是一致的,也就是说对于在DynaActionForm的动态属性(定义在元素的动态集合属性),请求对象参数是可操作的。其它参数被简单跳过。

    请求参数类型转换
    这节讨论request.getParameterValues(parameterName)获得的String数组类型怎样转换到表单对象的对应属性类型上。下面是支持的目标类型列表。
java.lang.BigDecimal
java.lang.BigInteger
boolean and java.lang.Boolean
byte and java.lang.Byte
char and java.lang.Character
double and java.lang.Double
float and java.lang.Float
int and java.lang.Integer
long and java.lang.Long
short and java.lang.Short
java.lang.String
java.sql.Date
java.sql.Time
java.sql.Timestamp
    目标类型,也就是说和表单对象属性关联的类型,是通过自省机制找到的;一个特定struts定制的自省机制是在DynaActionForm对象中使用的。struts也支持索引属性,parameterName[n];索引从0开始。这种命名转换的form bean的方法是通过按照下面定义的javabeans规范描述的,使用了索引属性模式。下面的方法用来处理所有的索引属性的数组元素。
public [] get();
public void set([] value);
下面的方法是用来处理单独的数组元素
public get(int index)
public void set(int index, value)
下面描述了使用简单的属性和索引属性的语法。
    1.当bean的属性是数组,且请求参数名没有使用索引符号parameterName[n]时,由request.getParameterValues(parameterName)返回的String[]将转换成目标组件类型的数组。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明。
public void set([] value)
public [] get();
    2.当bean的属性是数组,且请求参数名使用索引符号parameterName[n],由request.getParameterValues(parameterName)返回的String[]将被认为仅容纳一个简单的值;仅String[0]被转换成数组的组件类型。由struts框架内部实现该方法。ActionForm子类应该定义下面的方法声明来接收索引参数。
public void set(int index, value)
public get(int index)
上面的方法声明遵循了javabeans规范中定义的索引属性设计模式。当这些方法都没有时,通过实现下面的方法也可以处理索引存取属性。
public [] get();
在这个场景中,请求数组的读写是通过struts框架处理,首先获得根本的数组对象然后处理给定序号的元素。这个模式也支持基于list的请求参数实现,使用parameterName[n]访问。
     3.对于简单的属性类型,由request.getParameterValues(parameterName)返回的String[]将被认为仅容纳一个简单的值;仅String[0]被转换成目标类型。由struts框架内部实现该方法。对于简单的属性,ActionForm子类应该定义下面的方法声明。
public void set( value)
public get();
struts绑定的标签库提供了处理简单属性和索引属性的方式;org.apache.struts.taglib.nested包容纳了这些标签。struts中的完全的标签列表请参考http://jakarta.apache.org/struts/userGuide/index.html; 更多的资源请参考http://jakarta.apache.org/struts/resources/index.html. struts将来的趋势是采用JSTL和
JSF上。

posted on 2005-06-09 09:09 塞翁 阅读(269) 评论(0)  编辑  收藏 所属分类: Java翻译