开始Struts的日记。

今天终于对《Jakarta Struts编程》看了一个大概,

准备搭建一个环境进行进一步学习。

我将下载的status-1.2.7.tar.gz解压缩后,

把lib目录中的status.jar、jstl.jar和standard.jar拷贝到了WEB-INF的lib目录中,

起动服务器后,竟然一个劲儿的抛出异常,

郁闷死……

最后,把所有的jar文件都拷贝到WEB-INF的lib目录后,

才解决了问题。

回过头再看书,才发现,

书上已经写的很明白了,只怪当时没有注意到。

看来,看书还是要仔细一些。

又或是,水平不够,所以注意不到书上说的内容的重要性。

Author: sinpool

java和linux爱好者,至于English嘛,提高中...

12 thoughts on “开始Struts的日记。”

  1. 我还是经常碰到这个问题,有时干脆把想得到的库文件都给它拷上,例如在我试验那个struts+spring+hibernate的程序时就是这样的。http://www.learndiary.com/disDiaryContentAction.do?searchDiaryID=1468&goalID=1468&naviStr=a10ac0ad0

    ...

    6)、还有就是要把每个开源项目的包完整的拷到你的应用程序的lib中,比如:spring就要把它所有的在lib下的第三方支持包全部拷入你的应用程序的lib中。做这些事不要怕有冗余的文件,java的运行机制是要用的时候再去创建类的实例。多些文件只是占点硬盘空间而已。

    ...

    祝你学习愉快。

    --admin

  2. 谢谢您的鼓励。

    ----------------------------------------------------------------------------------------------------

    搭建环境成功以后,

    尝试着自己写了一个小程序,

    结果搞了半天才弄好。(还好弄出来了)

    问题出在:在JSP上显示FormBean中的数据的问题上。

    主要还是两个标签的使用上,不太明白。

    一、<bean:define>标签

    研究了半天,才弄明白那几个常用的属性是什么意义。

    作个总结,省得自己忘了。

    这是copy已有的对象到bean:

    id:新生成的bean的标识;

    name:以存在的对象名;

    type:新生成bean的类(型)。

    比如:<bean:define id="form" name="loginForm" type="com.sinpool.formbeans.LoginForm"/>

    新生成一个名为form的bean,类型是com.sinpool.formbeans.LoginForm,因为没有指定toScope,所以就是Page。

    然后就可以用<bean:write>输出这个Form的属性了。

    哈哈,接触Struts后,第一次对她产生好感了。

  3.   你在这里讲了,我才大概知道。我会用这个标签去试着解决我碰到的一个没有解决而悬着的问题:

    疑问:不知道在Struts标签中怎么引用jsp片断里的变量 http://www.learndiary.com/disDiaryContentAction.do?goalID=1498

  4. 不知道提供的方法是否可行,

    希望可以……

    ×××××××××××××××××××××××××××××××××××××××××××

    昨天,只是作了一个小实验,

    从jsp页面输入用户名后,

    提交请求到Action,

    在Action中将根据输入的用户名,

    选择不同的View,显示给用户,

    这个View还将输出刚才输入的用户名。

    今天,在昨天的基础上,开始练习在ActionForm中进行数据的验证,

    当然是在validate方法中写东西了,

    要想使用这个方法进行验证,有两个条件必须达到:

    1)必须在status-config中定义一个form-bean;

    2)在响应的action标签中指定validate属性为“true”。

    哈哈……还好我的配置是正确的,

    顺利出现了错误信息,

    可是,用<html:errors property="error1"/>显示的错误信息是黑色的,

    郁闷……

    还后,后来找到了一个解决的方法,

    在定义的properties文件中加入以下两句:

    errors.header=<FONT COLOR="#ff0000">

    errors.footer=</BR></FONT>

    一个是设置错误信息开头的html代码,另一个是设置错误信息结束时的html代码,

    这样,错误信息就被显示成红颜色了。

  5. 先来无聊,想了一个问题:

    当工程很大的时候,很可能把不同模块的文件放到不同的目录中,

    所以打算把作好的几个jsp文件放到一个新建的目录中,

    修改了相关的联接后,可以正常显示目录中的页面了,

    不过,提交请求后,总是显示“错误500”,说找不到我在<form name="aaa" action="login">

    中定义的login.do。

    郁闷了半天,最后将刚才的form标记改成了<html:form action="login" >,就可以了。

    得出了一个结论:尽量使用Struts提供的标记即可。

  6. 首先说,她真是一个好东西,只是我掌握的还不好!

    她可以使网站所有的网页表现出相同的风格,

    每个页面只需要指定与其他页面不同的地方就可以了。

    我也只是初步了解了Tiles的使用方法,

    还有很多东西等待以后再去深入。

    先作一个小小的总结,省得自己忘了。

    建立一个“模板”的步骤:

    1)建立一个“模板”文件:

    <tiles:insert attribute="header"/>

    指出一个用于插入模板文件的地方;这里的attritbute属性说明了要插入模板文件的名字(name)。

    可以通过修改这个模板的布局,来影响所有使用此模板的页面的布局风格。

    +++++++++++++++++++++++++++++++++++++++++

    例如:

    <%@ page language="java" pageEncoding="GBK" %>

    <%@ include file="/commons/StrutsHead.jsp" %>

    <!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">

    <html>

    <head>

    <title>Classic Layout</title>

    </head>

    <body topmargin = "0" leftmargin = "0" bgcolor="#FFFFFF">

    <!-- 页眉信息  -->

    <tiles:insert attribute="header"/>

    <hr>

    <!-- 菜单条   -->

    <tiles:insert attribute="menu"/>

    <hr>

    <!-- 主体信息 -->

    <tiles:insert attribute="body-content"/>

    <hr>

    <!-- 所有权声明 -->

    <tiles:insert attribute="copyright"/>

    </body>

    </html>

    +++++++++++++++++++++++++++++++++++++++++

    2)在页面中套用刚才的模板文件:

    一、<tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">

    page属性说明模板文件的位置,假设刚才的模板文件命名为classicLayout.jsp;

    flush属性是通知控制器把内容插入到页面之前要刷新输出流。

    二、<tiles:put name ="header" value="/commons/header.jsp"/>

    把value指定的页面文件放入(put,或者是替换到)一、中指定的模板文件中,替换模板文件中attribute属性与这个标签中name属性相匹配的地方。

    +++++++++++++++++++++++++++++++++++++++++

    例如:

    <%@ page language="java" pageEncoding="GBK" %>

    <%@ include file="/commons/StrutsHead.jsp" %>

    <tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">

    <tiles:put name ="header" value="/commons/header.jsp"/>

    <tiles:put name ="menu" value="/commons/menu.jsp"/>

    <tiles:put name ="body-content" value="/TableMaster/t_compT.jsp"/>

    <tiles:put name ="copyright" value="/commons/copyright.jsp"/>

    </tiles:insert>

    +++++++++++++++++++++++++++++++++++++++++

    3)编写模板用到的每个具体的页面:

    针对这个例子来说,就是/commons/header.jsp、/commons/menu.jsp、/TableMaster/t_compT.jsp和/commons/copyright.jsp

    其中,name为“body-content”的部分标识每个页面的主体,所以在每个页面中这个部分是不同的,而其他的三个部分应该是一样的,这样就使得不同页面据有相同的风格了。

    +++++++++++++++++++++++++++++++++++++++++

    下面这个页面是另一个套用此模板的例子,唯一不同的就是“body-content”部分:

    <%@ page language="java" pageEncoding="GBK" %>

    <%@ include file="/commons/StrutsHead.jsp" %>

    <tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">

    <tiles:put name ="header" value="/commons/header.jsp"/>

    <tiles:put name ="menu" value="/commons/menu.jsp"/>

    <tiles:put name ="body-content" value="/TableMaster/t_orderT.jsp"/>

    <tiles:put name ="copyright" value="/commons/copyright.jsp"/>

    </tiles:insert>

    +++++++++++++++++++++++++++++++++++++++++

    1)中提到的模板是一个很普通的模板,样式[1]是:

    (发现网页不能正常显示空格,所以用“`”代替之。)

    -------------------------------------

    |```````````header```````````|

    -------------------------------------

    |````````````menu````````````|

    -------------------------------------

    |````````body-content````````|

    -------------------------------------

    |```````````footer```````````|

    -------------------------------------

    我想把她改成下面这个样式[2]:

    ------------------------------------

    |```````````header```````````|

    ------------------------------------

    |```m```|````````````````````|

    |```e```|`````body-content``|

    |```n```|````````````````````|

    |```u```|````````````````````|

    ------------------------------------

    |```````````footer```````````|

    ------------------------------------

    疑惑:

    我尝试在1)中的模板文件中使用table标记和<td width="xx%" align="left">(只是在第二行menu和body部分使用),

    样子是出来了,不过menu的文字在最左面,而body的部分是在最右面。

    中间有很大一个空间什么也没有,而采用样式[1]的时候,body部分是占据了浏览器整个宽度的,

    现在也变得很窄了!

    不知道该如何解决,郁闷中……

  7. 可以正常显示汉字及全角空格:

    ------------------

    | 菜 |            |

    |   |      正文    |

    | 单 |            |

    ------------------

    不过,如果中间混杂有半角字符,以及英文和半角空格混合就不正常了,我发现半角的空格跟一个英文字母的宽度比起来窄很多,不知怎么样一回事,如下,实际里面的字符数是一样的,但是长度却差太多了:

    this is a book.

    t i  i  a    k.

    我对页面的设计简直一窍不通。

  8. 原来是这样呀!

    =================================================================

    在使用Validator之前,需要先配置一些东西。

    (我使用的是Struts 1.2.7)

    1)必要的包:

    将Struts发行包中的commons-validator.jar和jakarta-oro.jar

    这两个文件放到Web应用的WEB-INF/lib目录中。

    2)在struts-config.xml中设置插件:

    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">

      <set-property property="pathnames"     

        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>

    </plug-in>

    value值用来指定验证规则的文件,要用“,”分割。

    3)配置验证规则:

    Validator框架有两个重要的配置文件:

    <1>``validation-rules.xml文件,

    这个配置文件包好了一组可供应用程序使用的全局验证规则。

    这个文件是所有应用程序都使用的,任何Struts应用程序也都能

    使用。除非打算修改或扩展这组规则,否则无需修改这个文件!

    注意1:需要在资源包中加上一下的“键-值”:

    errors.required={0} is required.

    errors.minlength={0} can not be less than {1} characters.

    errors.maxlength={0} can not 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 an invalid credit card number.

    errors.email={0} is an invalid e-mail address.

    因为,验证出错的时候,系统会自动在资源包中查找对应的错误消息,

    比如:required验证规则出现错误时,就会输出“errors.required”的值。

    注意2:在Struts 1.2.7中,验证类使用的是:“org.apache.struts.validator.FieldChecks”,

    以前使用的是“org.apache.struts.util.StrutsValidtor”,

    只要是从struts 1.2.x发行包中拷贝的“validation-rules.xml”文件,就可以保证是正确的。

    <2>``validation.xml文件

    这个文件是专门用来验证页面指定的Field。

    注意1:这个文件是由“<!DOCTYPE form-validation PUBLIC

              "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"

              "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">”来管理其语法的。

    (因为这个没有找到,耽误了很长时间,每次起动服务器都抛出异常“must match DOCTYPE root "null"”)

    ********************************

    待续…………

    ********************************

  9. 在《使用Validator验证框架 一》中,

    已经把要配置的东西说完了,

    这次就记录一下对页面上某个Field具体是如何验证的。

    这个功能是通过validation.xml文件实现的,

    其实,这个文件名可以是任意的,可以起成别的名字,

    比如:validators.xml,不过,也要相应修改struts-config.xml文件中的

    加入validator框架PlugIn中的value属性。这个value属性用来指定validator-rules文件和具体的验证文件。

    1)根元素:

    validators.xml文件的“根元素(Root)”是form-validation,

    意味着整个文件的内容包含在“<form-validation>”和“</form-validation>”之间,

    2)元素global:

    这个东西包含constant子元素,用来定义一个全局的“验证限制”,

    以便在这个文件的其他地方使用这些验证规则。

    例如:

    <global>

     <constant>

      <constant-name>zip</constant-name>

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

     </constant>

    </global>

    这个例子就定义了一个全局的验证规则,名字是“zip”,具体的规则由“constant-value”指出。

    3)formset元素:

    这个可能是这个文件最重要的元素了,

    主要负责的就是指定对哪个Field进行验证以及验证规则。

    例如:

    <formset>

     <constant>

      <constant-name>zip</constant-name>

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

     </constant>

     <form name = "loginForm">

      <field property = "usename" 

             depends = "required,mask"

        <arg0 key = "label.usename"/>

        <var>

          <var-name>mask</var-name>

          <var-value>^[a-zA-z]*$</var-value>

        </var>

      </field>

      <field property = "postalCode"

             depends = "required,mask"

        <arg0 key="The postalCode" resource="false"/>

        <var>

          <var-name>mask</var-name>

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

        </var>    

      </field>

      <field property = "ordno"

             depends = "required,minLength"

        <arg0 key="The ordno" resource="false"/>

        <arg0 name="minLength" 

              key="${var:minLength}"resource="false"/>

        <var>

          <var-name>minLength</var-name>

          <var-value>5</var-value>

        </var>    

      </field>

     </form>

    </formset>

    <1>在formset元素中仍然可以定义验证规则(“constant”),但是,它不是全局的!

    这里定义了一个为“zip”的验证规则(这个例子与global的例子没有关系,不要混淆)。

    <2>在formset元素中可以定义一个或多个“form”子元素,这个form子元素指的是“from-bean”,

    name用于指定被验证的是哪个form-bean,具体的意思一会儿再提。

    <3>form子元素中也可以包括一个或多个“field”子元素,这个用来指定这个form-bean中,

    哪个field被验证。

    <3.1>field元素中的property:指定用来验证的field名;

    <3.2>field元素中的depends:指定要采用那些验证规则对其进行验证;

    <3.3>field元素中可以包含msg元素(这个例子没有用到),这个元素有三个属性:

    name:指定这个message用于哪条规则;

    key:这个值应该是资源包中一个可用的“键”;

    resource:是一个布尔值,用来说明key中指出的数值是否为资源包中的“键”。如果这个值是“false”,msg中的内容就是key中的字符串,而不是资源包中的值。

    <3.4>field元素中可以包括一个到四个arg子元素,用于对应资源包中errors.XXX中的代换参数,

    arg0对应{0},arg1对应{1}……,这个子元素包含的属性与msg一致。

    小结:

    var可以定义验证规则,比如:usename行;

    var可以引用在constant中定义的验证规则(包括global中定义的),比如:postalCode行;

    var可以定义要显示的数据,在key中引用这个值,比如ordno行。

    写在最后的,刚才在介绍form子元素时,并没有具体说明它的name属性具体是如何指定要验证的form-bean的。

    这里进行说明一下:

    1、如果form-bean是ValidatorAction或DynaValidatorActionForm子类的话,系统将把struts-config中action元素的path属性传递给Validator,此时,Validator中form子元素的name属性应该对应action元素的path属性。

    2、如果form-bean是ValidatorForm或DynaValidatorForm子类的话,系统将把struts-config中action元素的name属性传递给Validator,此时,Validator中form子元素的name属性应该对应action元素的name属性。即,与form-bean的名字是一致的!

  10. 通过今天的实践,

    发现了两个问题,

    可能需要以后注意。

    1)错误信息不能为某个特定的Field使用。

    Validator验证框架如果发现有不满足验证规则时,

    将自动封装ActionErrors对象,并将这个对象返回给页面。

    但是,这些ActionError(或ActionMessage)对象,使用add方法

    加入ActionErrors使用参数是ActionMessages.GLOBAL,

    所以,不能将错误信息定位到某个具体的Field上,

    只能使用“<html:errors/>”元素将所有信息

    一起输出出来。

    2)Validator验证框架与ActionForm的validator方法冲突。

    这里所说的ActionForm应该是某个ValidatorForm的子类或子孙类,

    如果在这个对象中使用了validator方法,并且在struts-config文件中

    的action元素中定义了需要使用validator方法验证。

    这时,Validator验证框架将失去作用,只进行ActionForm的validator方法,

    如果有了错误,将直接返回到struts-config中的action元素input属性指定的页面。

  11. 见:头疼,我搞不懂网页中空格的使用了(http://www.learndiary.com/disGoalContentAction.do?searchDiaryID=1690&goalID=1690&naviStr=a10a2416ah1334)

  12.     这个Action类可以将据有类似功能的Action合并到一起。它与DispatchAction类的作用差不多,唯一不同的是:这个类是通过资源包中的key作为请求参数来进行对方法的映射,而DispatchAction是通过请求参数来选择方法,即,SUBMIT的value与方法名必须一致。如果使用这个类,SUBMIT的value是资源包中key所对应的值,而根据这个key是如何选择运行方法的,下面就来介绍一下。

        步骤一:扩展一个LookupDispatchAction的子类。

                注意:1)每个方法必须是public的,为了向外面提供调用接口;

                      2)不能包括execute方法,这个方法使用LookupDispatchAction的默认方法;

                      3)每个方法的返回值与参数应该与普通Action类的execute方法一样;

                      4)每个方法代表一个功能,就相当于合并以前各个普通Action子类的execute方法。

        步骤二:在这个子类中实现个体KeyMethodMap方法,实现“键--方法”的映射。

                例子:

                      public Map getKeyMethodMap(){

                          Map map = new HashMap();

                          map.put("save","saveStatus");

                          map.put("load","loadStatus");

                          return map;

                      }

      

        步骤三:在资源包中定义“键”对应的“值”,用于表示在SUBMIT按钮上。

                例子:

                      save=save this status;

                      load=load this status;

        步骤四:配置struts-config.xml。

                例子:

                      <action path = "/qqq"

                         input = "/www.jsp"

                         parameter = "method"

                         scope = "request"

                         type = "com.sinpool.strtus.QQQAction"

                         <forward name = "success" path = "/order/complete.jsp"/>

                      </action>

             其中parameter="method",指定的字符串是method,说明SUBMIT的property(name)就应该是method。 

     

        步骤五:在JSP中的代码。

                例子:

                      <html:form action = "/qqq>

                          <html:submit property = "method">

                              <bean:message key = "save"/>

                          </html:submit>

                      </html:form>

                必须用<bean:message key = "save"/>设置SUBMIT应该显示的值,这段代码提交请求时,应该类似这        

            个样子:http://localhost:8080/qqq?method="save this status"。参数名“method”应该与步骤四中

            的action标签中的parameter一样。

        总结:虽然在提交请求时,仍将SUBMIT的value("save this status")提交了,但是,可以按照getKeyMethodMap()方法的定义,通过资源包的key映射到具体的方法名上。所以,这个请求实际调用了save方法。

Comments are closed.