Struts2知识小结

时间:2024.4.27

Struts2点小

Struts Tag Library

对于一个MVC框架而言,重点是实现二个部分: 控制器部分和视图部分。 Struts2框架同样如此:控制器部分由
Action(以及隐藏的系列拦截器)来提供支持,而视图部分则通过大量标签来提供支持。

Struts2标签库使用OGNL表达式作为基础, 且默认支持OGNL, JSTL, Groovy和Velcity表达式。且把所有标签都
定义在URI为 /struts-tags 命名空间下,但我们依然可以依据功能将其分为三类:

1. UI标签;
   a. 表单标签;
   b. 非表单标签;树、Tab页等;

2. 非UI标签;
   a. 流程控制: 条件、循环;
   b. 数据访问: 输出ValueStack中的值;

3. AJAX标签;


Object Graph Navigation Language, 缩写为OGNL,是类似于EL的脚本语言,


一. 控制标签

    Struts2中的非UI标签包括控制标签和数据标签,其中控制标签可以完成输出流程控制,例如条件、循环等操作,
    也可完成对集合的合并、排序等操作,它有如下九个:

    1) if: 选择输出;
    2) elseIf/elseif: 与if标签结合使用;
    3) else: 与if标签结合使用
    4) append: 将多个集合拼接成一个新的集合;
    5) generator: 将一个字符串解析成一个集合;
    6) iterator: 将集合迭代输出;
    7) merge: 将多个集合拼接成一个新集合,与append拼接方式不同;
    8) sort: 对集合进行排序;
    9) subset: 截取集合部分元素,形成新的子集;

    1. iterator标签

       对集合进行迭代,包括List,Set和数组,Map.

       . value: 可选,被迭代的集合,通常使用OGNL表达式指定,如无,则使用ValueStack栈顶集合;
       . id: 可选,指向集合中元素;
       . status: 可选,指向迭代时IteratorStatus实例,通过该实例可判断当前迭代元素的属性;每次迭代都有
                 一个IteratorStatus实例,该实例包含以下方法:

         a. int getCount(): 返回当前迭代了几个元素
         b. int getIndex(): 返回当前迭代元素的索引
         c. boolean isEven(): 当前索引是否为偶数
         d. boolean isFirst(): 当前迭代元素是否是第一个元素
         e. boolean isLast(): 当前迭代元素是否是最后一个元素
         f. boolean isOdd(): 当前索引是否为奇数

    2. if标签

       根据一个Boolean表达式的值,来决定是否计算,输出标签体等内容。
      
    3. append标签

       将多个集合对象拼接起来,组成一个新的集合。
       其中 id 属性确定拼接生成的新集合的名字。 append可接受多个<s:param ..../>子标签,每个子标签指定一个集合,append
       将<s:param..../>指定的多个集合拼接成一个集合;

    4. generator标签

       将指定字符串按指定分隔符分隔成多个子串,临时生成的多个子串可以使用iterator标签来迭代输出。

       a. count: 指定生成集合中元素总数;
       b. separator: 指定解析字符串的分隔符;
       c. val: 指定被解析的字符串;
       d. converter: 可选,指定一个负责将集合中每个字符串转换成对象;
       e. id: 指定访问集合的名称,如指定,则集合放在pageContext属性中;

    5. merage标签

       功能和append类似,但是新集合中各元素顺序不同:

       append为:
       1) 第一个集合第一个元素;
       2) 第一个集合第二个元素;
       3) 第一个集合第三个元素;
       4) 第二个集合第一个元素;
       5) 第二个集合第二个元素;
       6) 第二个集合第三个元素;
       7) 第三个集合第一个元素;
       8) 第三个集合第二个元素;
       9) 第三个集合第三个元素;

       merage为:
       1) 第一个集合第一个元素;
       2) 第二个集合第一个元素;
       3) 第三个集合第一个元素;
       4) 第一个集合第二个元素;
       5) 第二个集合第二个元素;
       6) 第三个集合第二个元素;
       7) 第一个集合第三个元素;
       8) 第二个集合第三个元素;
       9) 第三个集合第三个元素;

    6. subset标签

       取得集合的子集:
       . count: 指定子集合元素个数;
       . source: 指定源集合,如不指定,则默认取得ValueStack栈顶的集合;
       . start: 指定从源集合中第几个元素开始截取,默契为第一个(值为0);
       . decider: 指定由开发者是否选中该元素;

    7. sort标签      

       对于指定的集合进行排序; 必须提供自己的排序规则,即提供实现 java.util.Comparator接口的实现类;
       . comparator: 指定进行排序的 Comparator 实例;
       . source: 指定被排序的集合,如不指定,则针对 ValueStack栈顶的集合;


二. 数据标签

    提供各种数据访问相关的功能,包含显示一个Action中属性以及生成国际化输出等功能;

    1. property标签

       提供一种快速、方便地方式从ValueStack或ActionContext中获取值并显示;

       . value: 指定输要输出的属性值,如没有指定,则默认输出ValueStack栈顶的值;
       . default: 如输出属性值为 null, 则显示 default 属性的值;
       . escape: 是否escape HTML 代码, 默认值为 true; 将 < 转化为 &lt;

    2. set 标签

       将一个已有的值复制给新变量,然后放到指定的范围内

       . name: 必填,新变量名字
       . scope: 可选属性,指定新变量放置的范围,可以接受 application, session, request, page 或 action 五个值,
               默认为 Action中;
       . value: 可选,赋给变量的值,没指定,则为ValueStack栈顶的值;
       . id: 可选,该元素的引用ID
      
    3. push 标签

       将某个值放到valueStack中,从而更加方便访问;

    4. bean 标签

       创建JavaBean实例;

       . name: 必须,要实例化的JavaBean的完整类名;
       . var:  可选,可通过该属性值在标签外访问已实例化的JavaBean;

    5. Date 标签
      
       格式化输出日期以及计算指定日期和当前时刻间的时差;

       . format: 可选,指定日期显示格式;
       . nice: 可选, 是否输出指定日期和当前时刻间的时差,默认值为 false;
       . name: 必填,日期值;
       . id: 可选,引用该元素的 id 值;

       如果既指定nice="true", 又指定 format 属性,则会输出指定日期和当前时刻间的时差,即format属性失效;
       如没有指定format属性,也没指定nice="true", 则系统会到资源文件中寻找 key 为 struts.date.format的消息作为格式,否
       则采用默认的 DateFormat.MEDIUM格式输出。

    6. action 标签     

       直接在JSP页面中直接调用Action

       . id: 该Action的引用ID;
       . name: 必须:调用哪个Action;
       . namespace: 可选,调用Action所属的namespace;
       . executeResult: 可选,是否将Action处理结果页面包含到本页面,默认值为false;
       . ignoreContextParams: 可选,该页面中请求参数是否需传入调用的Action, 默认值为 false, 传入。

    7. debug 标签

       用于辅助调试,它在页面上生成一个超级链接,通过该链接可以查看到ValueStack和Stack Context中所有的值信息;

    8. include 标签

       将一个JSP或servlet包含到本页面中:
       . value: 必填, 指定包含的资源;
       . id: 可选,该标签的ID引用;

    9. url 标签       
 
       生成一个URL 地址,可以通过为url标签指定 param 子元素,从而向指定URL发送请求参数。

       . includeParams: 可选,是否包含请求参数,值为 none, get或者all.
       . scheme: 设置schema属性;
       . value: 可选,指定生成的URL值,如果无value有action就使用action指定Action作为URL地址;
                如果均提供,则使用value指定URL值;如均不提供,则使用当前页面作为URL地址;
       . action: 可选,指定action;
       . namespace: 可选,指定命名空间;
       . method: 可选,指定使用Action的方法;
       . encode: 可选,是否需encode请求参数;
       . includeContext: 是否需将当前上下文包含在URL地址中;
       . anchor: 可选,指定URL锚点;
       . id: 指定该URL元素的引用ID

    10. i18n和text 标签 

        i18n用于显示指定指定语言资源文件;

        . name: 资源文件名称;
 
        text用于获取指定资源文件中指定key对应的值;

        . name: 资源文件 key 值;
        . id:  引用的标识;


三. Form标签

    1. checkbox 标签    
 
        <s:set name="aBoolean" value="false"/><br>
        <s:checkbox label="checkbox test" name="checkboxField1" value="#aBoolean" fieldValue="true"/>
        <s:set name="aBoolean" value="true"/><br>
        <s:checkbox label="checkbox test" name="checkboxField1" value="#aBoolean" fieldValue="true"/>

       显示结果:

    <input type="checkbox" name="checkboxField1" value="true" id="checkboxField1"/>
    <input type="checkbox" name="checkboxField1" value="true" checked="checked" id="checkboxField1"/>

    2. checkboxlist 标签  

       一次性创建多个复选框,它根据list属性指定的集合来生成多个复选框;

       . listKey: 指定集合元素中的某个属性作为复选框的 value;
       . listValue: 指定集合元素中的某个属性作为复选框的 标签;

    3. combobox 标签 

       生成一个单行文本框和下拉列表框的组合,但两个表单元素只对应一个请求参数,只有单行文本框里的值才包含
       请求参数,而下拉列表框则只是用于辅助输入,没有name属性。

    4. doubleselect 标签 

       生成一个级联列表框, 当选择第一个下拉列表框时,第二个下拉列表框的内容会随之改变。

       . list: 第一个下拉列表框的集合;
       . listKey: 指定集合元素中某个属性作为第一个下拉列表框的value;
       . listValue: 指定集合元素中某个属性作为第一个下拉列表框的标签;
       . doubleList: 第二个下拉列表框的集合;
       . doublelistKey: 指定集合元素中某个属性作为第二个下拉列表框的value;
       . doublelistValue: 指定集合元素中某个属性作为第二个下拉列表框的标签;
       . doublename: 第二个下拉列表框的 name 属性;

       doubleselect标签一定得位于form中,且form须指定action属性.


四. 数据传输以及类型转换

    1. 为什么要数据传输以及数据转换?

       所有的MVC框架,都需要负责收集用户请求参数,并将请求参数传给应用的控制器组件。但所有的请求参数都是,
       也只能是字符串数据类型,但Java是强数据类型语言,因此MVC框架必须将这些字符串请求参数转换成相应的数据
       类型,这个工作是所有MVC框架均应提供的功能。

       不仅于此,在请求处理结束,在格式化显示请求处理结果的时侯,我们也需将封装了结果数据的JavaBean属性值
       转换为HTML页面上显示的内容。

       数据的传输和转换贯穿于请求处理的整个生命周期。

       Struts2通过内置的拦截器提供了非常强大的类型转换机制,也提供了很好的扩展性,开发者可以非常简单地开发出
       自己的类型转换器,完成字符串和自定义复合类型的转换(例如将字符串到Student实例间转换). 如果类型转换中
       出现异常,开发者也无须关心异常处理逻辑。Struts2的conversionError拦截器提供了非常强大的表现层数据处理
       机制, 并且在页面上显示异常信息。总之, Struts2的类型转换器提供了非常强大的表现层处理机制,方便了开发者
       的使用和操作。

    2. OGNL和Struts2

       Struts2的类型转换是基于OGNL表达式的,只要我们将HTML输入项命名为合法的OGNL表达式,就可以充分利用Struts2
       的类型转换机制。

    3. 内置的类型转换器

       Struts2已经内建了字符串类型和如下类型间的类型转换器.

       . Date: 日期格式使用用户请求所在Locale的SHORT格式;
       . 数组:默认情况下,元素是字符串;
       . 集合:在默认情况下,集合元素类型是String;

    4. List中放置自定义的类型

       1) 提交页面

            <s:textfield name="users[0].name" label="User Name"/>
            <s:textfield name="users[1].name" label="User Name"/>
            <s:textfield name="users[2].name" label="User Name"/>
            <s:textfield name="users[0].age" label="User Age"/>
            <s:textfield name="users[1].age" label="User Age"/>
            <s:textfield name="users[2].age" label="User Age"/>                       

       2) Action

      public class ListConversion {
              private List<Student> users;
              ...;
          }

          其国com.briup.Student类为:

          public class Student {
         private String name;
             private int age;   
          }
           
          如果Action中List不使用范型,必须在Action同目录下新增一文件, 使名规则为:

          Action类名-conversion.properties, 例如,可命名为: ListConversion-conversion.properties

          内容为:

          Element_list类型属性名称=list中所包含对象完整类名

          例如,Element_users=com.briup.Student

       3) 显示页面

        User Name Number 3: <s:property value="users[2].name"/><br>
        User Age Number 2: <s:property value="users[1].age"/><br>
   
    5. Map中放置自定义的类型

       1) 提交页面

            <s:textfield name="students['one'].name" label="Name"/>
            <s:textfield name="students['two'].name" label="Name"/>
            <s:textfield name="students['three'].name" label="Name"/>
            <s:textfield name="students['one'].age" label="Age"/>
            <s:textfield name="students['two'].age" label="Age"/>
            <s:textfield name="students['three'].age" label="Age"/>                       

       2) Action

      public class MapConversion {
              private Map<Student> students;
              ...;
          }

          其国com.briup.Student类为:

          public class Student {
         private String name;
             private int age;   
          }
           
          如果Action中Map不使用范型,必须在Action同目录下新增一文件, 使名规则为:

          Action类名-conversion.properties, 例如,可命名为: MapConversion-conversion.properties

          内容为:

          Element_map类型属性名称=map中value对象完整类名
          Key_map类型属性名称=map中key对象完整类名      

          例如,Element_students=com.briup.Student
                Key_students=java.lang.String

       3) 显示页面

        Age Number One: <s:property value="students['one'].age"/><br>
        Name Number Two: <s:property value="students['two'].name"/><br>


    6. 自定义类型转换器:
 
       注:JSP页面控件名和Action中属性同名

       1) 转换器实现类实现接口 org.apache.struts2.util.StrutsTypeConverter,实现二个方法:

          //将请求字符转换成特定对象
    public Object convertFromString(Map context, String[] values, Class toClass) {
        System.out.println("----------From String-------------");
        for(Object key: context.keySet()) {
            System.out.printf("Key: %s\tValue: %s%n",
                    key,
                    context.get(key));
        }
        System.out.println("toClass: "+toClass);
       
        String userString = values[0];
        Circle newCircle = parseCircle(userString);
        return newCircle;
    }

          //将对象转换成字符串输出
    public String convertToString(Map context, Object o) {
        System.out.println("----------From String-------------");
        for(Object key: context.keySet()) {
            System.out.printf("Key: %s\tValue: %s%n",
                    key,
                    context.get(key));
        }       
        Circle circle = (Circle) o;
        String userString = "toString: C:r" + circle.getRadius();
        return userString;
    }

       2) 设置配置文件:

          局部转换器: 在Action所在目录下配置文件:

                      Action类名-conversion.properties , 例如 CircleAction-conversion.properties,

                      内容为:

                      对象属性名称=转换器的完整类名    例如:circle=com.briup.CircleConverter


          全局转换器: 在源文件根目录下配置文件:

                      xwork-conversion.properties,

                      内容为:

                      对象完整类名称=转换器的完整类名    例如:com.briup.Circle=com.briup.CircleConverter                

五. 拦截器

    1. 拦截器是什么?

       多个Action中需要重复执行一些代码,我们可以将这些代码提取出来形成单独一个类中的方法,从而提供更好的重用
       性。这个单独提供的类就是 所谓的拦截器。 也就是说 拦截器体现的其实是一种软件复用的原则。

       拦截器就是一个类,也个类也包含方法,只是这个方法是个特殊方法,它会在目标方法调用之前或之后被调用执行。

       拦截器体系是Struts2的一个重要组成部分, 正是大量的内建的拦截器完成了该框架的大部分操作。这些拦截器有的提供
       公用功能,有的提供高级功能。例如通过 params 拦截器将 HTTP 请求中的参数解析出来,设置成 Action 的属性;
       servlet-config拦截器直接将HTTP请求中的HttpServletRequest实例和HttpServletResponse实例传给Action;
       fileUpload拦截器则负责解析请求参数中的文件域,并将一个文件域设置成Action的三个属性等;

    2. 为什么需要拦截器?

       1) 代码重用;
          将重复代码从多个Action中剥离出来,实现代码重用,便于代码维护;例如一些日志,权限管理代码。

       2) 使用移除方便;
          Struts2中拦截器为了进一步的维护方便,将拦截器相关信息从源代码中移除,配置在配置文件中。这样开发者可以非常方便增
          加或移除拦截器。

    3. 拦截器是如何调用的?

       1) FilterDispatcher实例化ActionProxy并调用其execute()方法;
       2) 拦截器在请求抵达Action之前和响应抵达客户端之前被调用;
       3) 一旦请求处理完毕,请求被送往Result渲染响应结果;

    4. 拦截器

       Struts2框架大多数核心功能由拦截器组成。例如重复提交、类型转换、数据填充、验证、文件上传、页面预处理以及更多功能
       均得益于拦截器的帮助;

       每一个拦截器均是通过在配置文件中配置完成;

    5. 拦截器和Action

       拦截器在调用的时侯,很可能要和Action交互。这时侯可以持有Action的引用,实现类似于解决重复提交或输入验证功能。拦截器
       也可以在Action的execute()方法调用之前修改设置Action的状态;

    6. 拦截器的配置

       拦截器能基于每一个Action进行配置,自行定义的拦截器亦可和框架本身提供的拦截器混合使用;多个拦截器可以组合形成所
       谓的拦截器栈。这时侯拦截器配置的位置对于执行的顺序非常重要。

    7. 拦截器配置->具体代码

       拦截器是通过配置文件指定,因此通过拦截器来引入通用操作的方式,完全是可插拨式的:当系统需要执行这些通用操作时,则
       配置文件引用这些拦截器即可;如果系统不再需要执行这些通过操作,则在配置文件中取消引入这些拦截器即可。

       在struts.xml文件中定义拦截器只需为拦截器指定一个拦截器名,就完成了拦截器定义。

       <interceptor name="拦截器名" class="拦截器实现类"/>

       一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器来拦截Action了,拦截器的拦截行为将会在Action的execute()方法执行
       之前被执行。

       通过<interceptor-ref.../>可以在Action内使用拦截器。

       1) 默认拦截器

          每一个包只默置一个默认拦截器,一旦为某个包指定了默认拦截器,如果该包中Action没有显示指定拦截器,则默认的拦截器将会
          起作用。但值得注意的是:一旦我们为该包中的Action显示指定了某个拦截器,则默认的拦截器不会起作。如果该Action需要
          使用该默认拦截器,则必须手动配置该拦截器的引用。

          配置默认拦截器使用<default-interceptor-ref.../>元素,该元素作为<package.../>元素的子元素使用,为该包下的所有
          Action配置默认的拦截器。配置<default-interceptor-ref.../>元素时,需要指定一个name属性,该name属性值是一个已经
          存在的拦截器的名字,表明将该拦截器配置成该包的默认拦截器。需要注意的是每个<package.../>元素只能有一个
          <default-interceptor-ref.../>子元素,即每个包只能指定一个默认拦截器。

          <package name="包名">
              <interceptors>
                   <interceptor.../>
                   <interceptor-stack.../>
              </interceptors>
              <default-interceptor-ref name="拦截器名或拦截器栈名"/>
              <action .../>
          </package>

          配置默认拦截器是一种使用拦截器的方式——避免在每个Action中单独配置拦截器,通过在该包下配置默认拦截器,可以实现
          为该包下所有Action同时配置相同的拦截器。

          当我们定义的包继承struts-default包时,也继承了它的默认拦截器栈:defaultStack,这就意味着,如果我们不为Action指定
          任何的拦截器引用,则defaultStack拦截器栈将会拦截Action.

    8. 拦截器栈

       如果有多个Action在执行前同时做登录检查、安全检查和记录日志,则可以将这三个动作对应的拦截器组成一个拦截器栈。达到减少
       配置,重复使用的目的。

       配置拦截器栈的语法示例如下:

       <interceptor-stack name="拦截器栈名">
          <interceptor-ref name="拦截器一"/>
          <interceptor-ref name="拦截器二"/>
          ...
       </interceptor-stack>

       当然拦载器栈中也可以再次包含拦载器:

       <interceptor-stack name="拦截器栈一">
          <interceptor-ref name="拦截器一"/>
          <interceptor-ref name="拦截器二"/>
          ...
       </interceptor-stack>

       <interceptor-stack name="拦截器栈二">
          <interceptor-ref name="拦截器一"/>
          <interceptor-ref name="拦截器栈一"/>
          ...
       </interceptor-stack>

    9. 自定义拦截器

       实现接口 com.opensymphony.xwork2.interceptor.Interceptor接口,该接口包含三个方法:
       . init(): 拦截器实例化后立即执行,且在整个拦截器的生命周期中仅执行一次。主要用于打开一些一次性资源。
       . destory(): 在拦截器实例被销毁之前调用,且在整个拦截器的生命周期中仅执行一次。主要用于关闭一些一次性资源。
       . intercept(ActionInvocation invocation): 用户需要实现的拦截动作,就像Action的execute()方法一样,intercept()
                 方法会返回一个字符串作为逻辑视图。如果该方法直接返回了一个字符串,系统将会跳转至该逻辑视图对应的实
                 际视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通
                 过调用该参数的invoke方法,将控制权转给下一个拦截器,或者转给Action的execute()方法;

    10. 内置拦截器

        1) 工具

           a. timer: 负责输出Action的执行时间,在分析该Action的性能瓶颈时比较有用。
           b. logger: 负责日志记录的拦截器, 主要是输出Action的名字;
        
        2) 数据传输

           a. params: 最基本的一个拦截器,它负责解析HTTP请求中的参数,并将参数值设置成 Action 对应的属性值;
           b. static-params: 负责将xml中<action>标签下<param>标签名册中的参数传入action.
           c. autowiring: 自动装配的拦截器,主要用于当 Struts2 和 Spring 整合时, Struts2 可以使用自动装配的方式
                      来访问 Spring 容器中的 Bean.
           d. fileUpload: 主要用于文件上传,负责解析表单中文件域的内容;
           e. servlet-config: 某个Action需要直接访问Servlet API, 就是通过这个拦截器实现的。
 
        3) 工作流

           a. workflow: 负责调用Action类中的validate方法,如果校验失败,则返回 input 的逻辑视图;
           b. validation: 通过执行在 xxxAction-validation.xml中定义的校验器,从而完成数据校验;
           c. prepare: 如果 action 实现了 Preparable 接口,将会调用该拦截器的 prepare() 方法;
           d. model-driven: 这是一个用于模型驱动的拦截器,当某个 action 类实现了 ModelDriven 接口时,它负责把
                       getModel() 方法的结果堆入 ValueStack中;

        4) 混合

           a. exception: 负责处理异常, 它将结果映射为结果;
           b. token: 阻止重复提交,它检查传到Action中的token, 从而防止多次提交;
           c. token-session: 功能与token类同,只是将 token 保存在 HttpSession 中;
           d. scoped-Model-Driven: 如果一个Action实现了一个ScopedModelDriven接口,该拦截器负责从指定生存范围中
                     找出指定的Model, 并将通过setModel()方法将该Model传给Action;
           e. execAndWait: 后台执行action, 负责将等待画面发给用户;

六. 输入校验

    1. 为什么需要输入校验?

       对于一个Web应用而言,所有的用户数据都是通过浏览器收集的,用户的输入信息是非常复杂的:用户操作不熟练,输入出错,
       硬件设备的不正常,网络传输的不稳定,甚至有恶意的蓄意破坏..., 这些都有可能导致输入异常;
      
       输入的异常,轻则导致系统非正常中断,重则导致系统崩溃。应用程序必须能正常处理。对异常输入的过滤,就是输入校验,也
       称为数据校验;通常的做法是碰到异常输入时应用程序直接返回,提示浏览者必须重新输入。

       输入校验分为客户端校验和服务器校验,客户端校验主要是过滤正常用户的误操作,主要通过JavaScript代码完成;服务器端校
       验是整个应用阻止非法数据的最后防线,主要通过在应用中编程实现。

       Struts2提供了非常强大的输入校验体系,通过Struts2内建的输入校验器,Struts2应用无需书写任何输入校验代码,即可完成绝
       大部分输入校验,并可以同时完成客户端校验和服务器端校验。当然, Struts2也允许客户自行提供校验器。

    2. 服务器端校验

       1) 手动校验

          步骤:a. action继承ActionSupport, 重写方法

                   public void validate(){...}

                   如果出现错误,调用ActionSupport中所提供的addFieldError("提示内容key","提示内容")方法加入错误提示;
         
                b. 在 struts.xml 文件中 action 中配置名称为 input 的 result, 用以显示错误信息;

                c. 在名称为 input 的result对应的JSP页面,通过标记<s:fielderror/>显示错误信息;

                   <s:fielderror/>             ->  显示所有错误信息;
 
                   <s:fielderror>
                       <s:param>消息提示名称</s:param>
                   </s:fielderror>

          输入校验流程:

          a. 类型转换器负责对字符串的请求参数执行类型转换,并将这些值设置成Action的属性值;
          b. 在执行转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,conversionError拦截器负责将其
             封装到fieldError里,然后执行步骤3;如果转换过程中没有异常信息,则直接进入第3步;
          c. 通过反射调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名;
          d. 调用Action类里的validate()方法;
          e. 如果经过上面4步都没有出现fieldError,将调用Action里处理用户请求的处理方法,如果出现了fieldError, 系统将转入
             input逻辑视图所指定的视图逻辑;

       2) Xwork验证框架

          正如你所见,当你不同的用例需要不同的验证规则时,手动验证使你的代码显得很混乱;依然要写很多代码,编程依然很烦琐,
          代码复用不高。 Struts2提供了基于验证框架的输入校验,在这种校验方式下,所有的输入校验只需要通过指定简单的配置
          文件即可。

          采用框架验证与手动验证步骤基本相同,只不过第一步Action中无须重写validate()方法;

          a. 构建 *-validation.xml 文件

             采用Struts2的校验框架时,只需要为该Action指定一个校验文件即可。校验文件是一个XML配置文件,每一个Action都有一个
             校验文件,该文件的文件名应用遵守如下规则:

             <Action名字>-validation.xml

             该文件应该被保存在与Action class 文件相同的路径下,便于管理。

             增加了该校验文件后,其他部分无需任何修改,系统自动会加载该文件,当用户提交请求时,Struts2的校验框架会根据该
             文件对用户请求进行校验。

          b. 注册验证器

             验证器也是一个Java类,一个实现了com.opensymphony.xwork.validator.Validator接口的类;
             但验证器写好后必须注册,通过注册给该验证器指定一个逻辑名,以方便Struts2程序对该验证器的访问;
             注册有二种方式:

             i.  通过ValidatorFactory类编码注册:
                 通过调用类com.opensymphony.xwork.validator.ValidatorFactory类中静态方法

                 void registerValidator(String name, Class c);

                 实现。

             ii. 通过校验器注册文件配置注册:            
                 在classpath根路径下提供一个validators.xml文件,通过该文件进行配置;这个文件称之为校验器注册文件;

                 Struts2提供了大量的校验器,这些内建的校验器可以满足大部分应用的校验需求。这些内建的校验器也需
                 注册,它们采用了配置注册方式,校验器文件位于 xwork-2.0.1.jar 文件中 com\opensymphony\xwork2\validator\
                 validators\ 目录下,一个名为 default.xml 文件中。该文件就是 Struts2的默认校验器注册文件。

          c. 内建校验器

             . required: 必填校验器,要求指定字段必须有值;
             . requiredstring: 必填字符器校验器,要求字段值必须非空且长度大于0;
               i. trim:  是否在校验前截断被校验属性值前后的空白,该属性是可选的,默认是 true.
             . stringlength: 字符串长度校验器, 要求校验字符长度必须在指定范围;
               i.  trim:  是否在校验前截断被校验属性值前后的空白,该属性是可选的,默认是 true.
               ii. minLength: 指定字段值的最小长度,可选,不指定则最小长度不受限制;
               iii.maxLength: 指定字段值的最大长度,可选,不指定则最大长度不受限制;
             . int: 整数验校器,要求校验字段的整数值必须在指定范围内;
               i.  min: 指定该属性最小值,如不指定,则不检查最小值;
               ii. max: 指定该属性最大值,如不指定,则不检查最大值;
             . double: 浮点数验校器,要求校验字段的双精度浮点数值必须在指定范围内;
             . date: 日期验校器,要求校验字段的日期值必须在指定范围内;
               i.  min: 指定该属性最小值,如不指定,则不检查最小值;示例:<param name="min">1990-01-01</param>
               ii. max: 指定该属性最大值,如不指定,则不检查最大值;
             . email: 邮件地址校验器,它要求被检查字段的字符如果非空,则必须是合法的邮件地址;它基于正则表达式进行校验;
             . url: 网址校验器,它要求被检查字段字符如果非空,则必须是合法的URL地址;它基于正则表达式进行校验;
             . conversion: 检查被校验字段在类型转换过程中是否出现错误。
               i.  fieldName: 指定校验的 Action 属性名,如采用字段校验器风格,则无须指定该参数;
               ii. repopulateField: 类型转换失败,返回 input 页面时,类型转换失败的表单域是否保留原来的错误输入。
             . expression: 表达式校验器,非字段校验器,它会按OGNL语法指定一个返回boolean类型值的表达式。当返回 true,
                    校验通过;该逻辑表达式基于 ValueStack 进行求值;

               <validators>
                    <validator type="expression">
                          <param name="expression">...</param>
                          <message>Failed to meet Ognl Expression ...</message>
                    </validator>
               </validators>

             . visitor: 验证Action里的复合属性(自定义类型);
               i.  context: 指定校验规则文件的context
           ii. appendPrefix: 指定校验失败后提示信息是否添加前缀

               示例:
               i. StudentAction-validation.xml
                  -----------------------------------------
                  <field name="student">
                      <field-validator type="visitor">
                    <param name="context">studentContext</param>
                 <param name="appendPrefix">true</param>
                 <message>STUDENT:</message>
                </field-validator>
          </field>

               ii. Student-studentContext-validation.xml
                   -----------------------------------------
                 <field name="name">
            <field-validator type="requiredstring">
                <param name="trim">true</param>
                <message>PLEASE input your name!</message>
            </field-validator>
           </field>
           <field name="age">
            <field-validator type="int">
                <param name="min">1</param>
                <param name="max">100</param>
                <message>AGE must be between ${min} and ${max}!</message>
            </field-validator>
           </field>                                  
 
               iii. 错误页面显示:
                    -----------------------------------------                  
                    STUDENT: PLEASE input your name!
                    STUDENT: AGE must be between 1 and 100!
                  
             . fieldexpression: 功能类同于 expression, 适合于字段校验器,要求指定 fileName 要求校验的Action的属性名;

               <validators>
                    <validator type="expression">
                          <param name="fileName">name</param>
                          <param name="expression">...</param>
                          <message>Failed to meet Ognl Expression ...</message>
                    </validator>
               </validators>

             . regex: 检查被校验字段是否匹配一个正则表达式;
               i.  fieldName: 指定校验的Action属性名;
               ii. expression: 指定正则表达式
               iii.caseSensitive: 指定正则表达式匹配时,是否区分大小写,默认值为 true;

       3) 探索高级功能

          a. 自定义验证器

             步骤一:实现接口Validator或继承类FieldValidatorSupport
             步骤二:在验证器中提供与参数同名的属性以及对应的setter/getter方法,重写valide()方法
        public class MyValidator extends FieldValidatorSupport {
            private String validName="";
           
            public void validate(Object arg0) throws ValidationException {
                String fieldName=this.getFieldName();
                String fieldValue=(String)this.getFieldValue(fieldName, arg0);
                if(validName.indexOf(fieldValue.trim().toLowerCase())!=-1) return;
                addFieldError(fieldName,arg0);       
            }

            public String getValidName() {
                return validName;
            }

            public void setValidName(String validName) {
                this.validName = validName.toLowerCase();
            }
        }
             步骤三:在classpath中配置文件 validators.xml
            <validators>
                <validator name="validName" class="com.briup.MyValidator"/>
            </validators>
             步骤四:在验证文件中使用自定义验证器
        <field-validator type="validName">
            <param name="validName">zs,ls,ww</param>
            <message>Invalid name, please try again!</message>
        </field-validator>                       

          b. 使用OGNL表达式语言无须写Java代码构建验证规则

       4) 使用不同的context进行验证

          一个Action可以处理多个请求,不同请求有不同的验证规则,可以使用不同的验证文件封装不同的验证规则;

          1) struts.xml文件中:
                 <action name="studentLogin" class="com.briup.StudentAction" method="login">
            <result name="success">/studentResult.jsp</result>
            <result name="input">/studentLogin.jsp</result>
        </action>
          2) 验证文件应与Action同一个目录,名称应为 Action类名-action逻辑名-validation.xml

       5) Short-circuiting验证

          一个字段如果设置有多个验证器,多个验证器都会生效。从而显示多个错误提示。如果想在前面验证器验证
          失败后后面验证器就不参与验证,可在前面验证器上显示设置属性short-circuit值为"true", 其默认值为
          false. 示例:

          <field name="name">
             <field-validator type="stringlength" short-circuit="true">
            <param name="minLength">1</param>
            <param name="maxLength">10</param>
                <message>Length must be between 1 and 10!</message>
             </field-validator>       
             <field-validator type="validName">
            <param name="validName">zs,ls,ww</param>
                <message>Invalid name, please try again!</message>
             </field-validator>
      </field>

          上述例子上name表单控件值如果长度不符,则validName类型的验证器不会被调用。

          另 requiredstring 名称的验证器类型设置short-circuit="true"对后续验证器不起作用。

       5) ExpressionValidator验证
             
          使用OGNL表达式作为验证条件,示例:

          <validators>
          <validator type="expression">
         <param name="expression">name.equals("ls")</param>
         <message>INVALID NAME!</message>
          </validator>
              <field name="name">
                 <field-validator type="requiredstring">
                 <message>Name is required!</message>
              </field-validator>
          </validators> 

          上述例子中 name 为一属性名,使用expression验证器验证其值是否为 "ls". 其中"ls"为一个具体值直接写在
          验证配置文件中,也可以来自静态常量或静态方法的返回值。示例:

          <validators>
          <validator type="expression">
         <param name="expression">name.equals(@com.briup.Constant@NAME)</param>
         <message>INVALID NAME!</message>
          </validator>         
          </validators>     

      其中Constant类源文件为:
      public class Constant {
          public static final String NAME="ww";
          public static String getName() {
              return "sq";
          }
      }
          注意:属性和方法的修饰符应设置为 public.

       5) VisitorFieldValidator验证

          多个Action类中都要验证相同JavaBean对象的各个属性,为了避免验证配置信息出现在多个配置文件中,可以
          将JavaBean对象的验证信息单独写在一个文件中,然后各Action验证配置文件使用visitor类型验证器去引用。

          示例:

          a. 没有使用visitor类型验证器

             i.  JSP页面

                 login.jsp
                 ---------------------------------------------------------------
                 <h3>Student Login</h3>
                 <s:form action="login">
                     <s:textfield name="name" label="name"/>
                     <s:textfield name="password" label="Password"/>
                     <s:submit value="Submit"/>
                 </s:form>

                 register.jsp
                 ---------------------------------------------------------------
                 <h3>Student Register</h3>
                 <s:form action="register">
                     <s:textfield name="name" label="name"/>
                     <s:textfield name="password" label="Password"/>
                     <s:submit value="Submit"/>
                 </s:form>

             ii. Action

         StudentProAction.java
                 ---------------------------------------------------------------

                 public class StudentProAction extends
                     ActionSupport implements ModelDriven<Student> {
                     private Student student=new Student();
                    
                     public String login() {
                         return "success";
                     }
                
                     public String register() {
                         return "success";
                     }
   
                     public Student getModel() {
                         return student;
                     }
                 }

             iii.Struts.xml

        <action name="login" class="com.briup.StudentProAction" method="login">
            <result>/loginResult.jsp</result>
            <result name="input">/login.jsp</result>
        </action>
        <action name="register" class="com.briup.StudentProAction" method="register">
            <result>/registerResult.jsp</result>
            <result name="input">/register.jsp</result>
        </action>

             iii.验证配置文件:

                 StudentProAction-login-validation.xml(和StudentProAction同包)
                 ---------------------------------------------------------------
        <validators>
            <field name="name">   <!-- 属性名应与表单控件同名,而不是Action中属性名-->
                <field-validator type="requiredstring">
                    <message>Name is required!</message>
                </field-validator>
            </field>
            <field name="password">
                <field-validator type="requiredstring">
                    <message>Password is required!</message>
                </field-validator>
            </field>   
        </validators>


                 StudentProAction-register-validation.xml(和StudentProAction同包)
                 ---------------------------------------------------------------
        <validators>
            <field name="name">
                <field-validator type="requiredstring">
                    <message>Name is required!</message>
                </field-validator>
            </field>
            <field name="password">
                <field-validator type="requiredstring">
                    <message>Password is required!</message>
                </field-validator>
            </field>   
        </validators>

        注意:验证配置文件中<field>中name属性值与表单控制同名,使用<s:textfield>即可显示错误提示信息,
                      否则,须通过<s:fielderror/>显示错误提示信息;

                      . <s:fielderror/>:显示所有field级别的错误提示信息;
                      . <s:fielderror>
                   <s:param>student.password</s:param>
                    </s:fielderror>
                        : 提定显示名称为student.password的field级别的错误提示信息;

          b. 使用visitor类型验证器

             其它地方与上同,只是配置文件和显示错误信息设置有点变动:

             iii.验证配置文件:

                 StudentProAction-login-validation.xml(和StudentProAction同包)
                 ---------------------------------------------------------------
        <validators>
            <field name="student">   <!-- 属性名与Action中属性同名-->
                <field-validator type="requiredstring">
                    <message>Name is required!</message>
                </field-validator>
            </field>
        </validators>


                 StudentProAction-register-validation.xml(和StudentProAction同包)
                 ---------------------------------------------------------------
        <validators>
            <field name="student">   <!-- 属性名与Action中属性同名-->
                <field-validator type="requiredstring">
                    <message>Name is required!</message>
                </field-validator>
            </field>
        </validators>

                 Student-validation.xml(和Student类同包)
                 ---------------------------------------------------------------
        <validators>
            <field name="name">
                <field-validator type="requiredstring">
                    <message>Name is required!</message>
                </field-validator>
            </field>
            <field name="password">
                <field-validator type="requiredstring">
                    <message>Password is required!</message>
                </field-validator>
            </field>   
        </validators>

                注意这时显示错误信息时须使用标记 <s:fielderror/>.


    2. 客户端校验   
 
       在服务器端设置成功的基础上,在<s:form>标记中将属性validate设置为true即可。这时错误显示效果和服务器端
       验证相同,只不过借助于javascript实现而已。

       注意,借助于OGNL表达式使用expression类型的验证器还需使用服务器端验证实现。???
      

七. 国际化

    1. JSP页面显示国际化信息:
 
       <s:text name="login.title"/>            <!-- login.title为资源文件key值 -->
       <s:textfield name="name" key="login.name"/>    <!-- login.name为资源文件key值 -->
       <s:property value="%{getText('login.name')}"/>   <!-- login.name为资源文件key值 -->
      
    2. Action中获取国际化信息
       getText("资源文件key值");                        //getText为ActionSupport的方法

    3. 配置文件中获取国际化信息
       <message>${getText('login.name')</message>       <!-- login.name为资源文件key值 -->

更多相关推荐:
Struts2面试总结(20xx版)

1Struts2中Action通过什么方式获得用户从页面输入的数据又是通过什么方式把其自身的数据传给视图的Action从页面获取数据有三种方式1通过Action属性接受参数2通过域模型获取参数3通过模型驱动获取...

Struts2总结

第一章MiniStruts的制作不使用Servlet也不使用requestgetParameter获取参数是用户能够直接访问Dao中的查询方法1可以使用filter过滤器用来拦截用户的表单提交请求的路径请求的参...

Struts2知识点总结

1struts2步骤1创建web项目2添加struts2的必须jar包3添加支持配置webxml文件4创建界面和相应的action5配置strutsxml文件6部署运行项目2struts2的工作流程1浏览器发送...

Struts2最全面总结

20xx年5月13日221312Struts2总结fdteamcaptain陈玉龙1Struts2的起源和背景Struts2以WebWork优秀的设计思想为核心吸收了Struts1的部分优点建立了一个兼容Web...

Struts2基础知识总结

Day1一框架概述1三大框架是企业主流JavaEE开发的一套架构Struts2SpringHibernate2什么是框架为什么要学框架框架是实现部分功能的代码半成品使用框架简化企业级软件开发学习框架清楚的知道框...

Struts2 总结

Struts2框架主讲李洪鹤以下笔记均为我本人亲自整理若有描述不对或代码错误请同学们及时更改一下重新上传上去谢谢1234567891011Struts是基于MVC的轻量级框架1实现了MVC2轻量侵入性与量级成正...

struts2基础总结

Struts2基础三种方式接收用户输入1使用领域对象接收用户输入2使用ModelDrivenaction页面示例注意代码黑体部分3使用action属性接收用户输入二种方式访问requestsessionappl...

Struts2总结

Struts20处理流程值栈一次request只有一个值栈Action1当前正在访问的action永远在值栈栈顶2服务器端跳转到另外一个action时值栈里会有两个action且先访问的action在栈底默认a...

struts2学习小结

一配置问题最新的struts2为GA版221其中必须类库为1commonsfileupload121jar2commonsio132jar3freemarker2316jar4javassist37gajar5...

Struts2开发总结

Struts2项目开发总结注Struts2版本Struts216数据库Oracle9i所须架包commonslogging104jarcommonsfileupload121jarfreemarker2313j...

Struts2实践总结

拦截器Struts2中的输入校验使用Annotation取代strutsxml配置Struts2与AJAX交互驾驭XML数据第一个Struts2程序当我们在一个新的工作空间中创建一个Web项目的时候首先要将我们...

struts2常用标签方法总结

1输出action中属性值在jsp页面中显示用ltspropertyvaluequot属性名quotgt如果是对象域则表示为ltspropertyvaluequot对象属性名quotgt2在页面中实现自动增加的...

struts2总结(34篇)