`

struts2输入校验深入总结

阅读更多
Struts2把错误消息分成两类:
1、第一类叫做Action级别的(比Field级别更高一层的)
2、第二类叫做Field级别的


下面首先讲解struts2里自带的输入校验(编码方式校验):

正常情况下,页面输入正确的内容(包括相应框内输入正确的类型,比如出生日期框内我输入的是正确的Date类型,而不是输入的其他的错误的比如字符串类型),那么到action里我定义正确的类型之后,程序就会自动的转换成功类型,调用相应属性的set方法,然后返回最后显示的结果视图页面。、


但如果我在输入页面上输入错误的类型,比如在action里定义的Date类型的属性,我在输入页面上写成一般的字符串了,那么程序执行到action那里的相应属性的set方法时就会出现类型转换不成功的错误,之后就不会执行execute方法了。直接在页面上抛出错误。而如果我在struts.xml里相应的action里再配置一个result,名称为input,对应的页面为当初输入内容的起始页面的话。那么在出现上述错误的时候程序就会找到这个input入口,再次返回到当初输入内容的页面,让用户再重新输入正确的内容(当然,这个input对应的页面也可以是最后的结果视图页面,这时即使类型转换没有成功,也会把用户输入的错误类型的信息显示到此页面上,而不会在页面上直接报错)


在action里配置一个result,名称为input。作用就是这样的,当action里的类型转换不成功的话就不会再执行execute方法了,也找不到相应的正确的结果视图页面了。而是会找struts.xml里的相应的action里有没有名称为input的result,如果有就跳到此result对应的页面,如果没有就直接报错。当然,名称为input的result对应的页面一般就设定成用户当初输入信息的视图页面,相当于放回去了,让用户重新填写正确的信息


但如果在action里再重写ActionSupport类里的validate()方法的话,执行流程就变为。
先执行相应属性的set方法,再执行validate()方法【此方法是用来做输入校验的】,最后执行execute()方法返回到结果视图页面。但如果类型转换出问题了,则就不会执行execute()方法了,而validate()方法还是会执行完的,完了再去找名称为input的result。下面就重点讲如何在validate()方法里实现输入校验了

如果输入校验方法validate方法里的校验失败了(没有通过),那么就不会再去执行execute方法了。去找input,跳转到对应的页面

对于struts2,它把错误消息分成两类,第一类叫做action级别的,第二类叫做field级别的。action级别高于field级别的
与action级别对应的方法为addActionError(String anErrorMessage),与field级别对应的方法为addFieldError(String fieldName,String errorMessage),这两个方法都是继承自父类ActionSupport的方法

如何将错误信息显示在页面上呢:
【action级别的错误信息】
在action里的validate方法里调用父类的addActionError方法将错误信息添加到actionError里,然后在jsp页面上引用struts2自带的标签库,并引用标签库里的标签<s:actionerror>就可以将错误信息显示到页面上
重点:对于action级别的错误信息一般都是我们自己往里面添加的,struts2不会自动给我们添加
【field级别的错误信息】
而对于field级别的错误信息,两种情况,如果我们不自己手动添加(在action里调用addFieldError(String fieldName,String errorMessage)方法),那么在校验出错时struts2会自动给我们添加,格式是固定的:Invalid field value for field "属性名称",如果我们在jsp页面上调用<s:fielderror>来显示错误信息的话,就是以这种格式显示的。第二种情况,也像action级别的错误一样,可以我们自己手动添加,然后将错误信息显示到页面上。
重点:要想将错误信息显示在页面上,就必须在页面上引用struts2自带的标签库,调用里面相应的标签才可以

而对于struts2帮助我们自动生成的错误信息又存在两种情况:1。类型转换不成功时生成;2。


fielderror底层的实现:将针对这一个属性的所有的错误信息都放到一个集合里面去(他们整体是放到一个map里,key是属性名称,value是一个集合,存放所有错误信息),当页面调用这个属性的错误信息时,把所有的都打印出来(一个属性field,可能对应多条错误信息),比如包括struts2帮我们自动生成的和我们自己定义的。那么又遇到一个问题,有些信息是我们自己希望输出的,而有些是我们不希望输出的,那到底怎么实现呢?
这里又查看了源代码,我们可以通过this.getFieldErrors("age");得到特定于age这个属性的所有错误信息,得到的是一个Map,我们试图通过Map.remove()方法移除里面的我们不希望在页面上输出的信息。但这样是行不通的,因为返回的这个Map是底层给我们又新生成的一个集合返回了。而不是底层程序里使用的那个,所以即使这里移除了,底层正在用的那个也不会移除的。所以这种方法是行不通的。这里只是提醒下,这不是解决问题的办法。

对于field级别的错误信息,struts2提供的(帮助我们生成的)默认错误信息格式是英文的而且不好看,这样显示到页面上用户很难接受。需要我们自己定义一个文件(消息属性文件)去改变这种固定的格式。【当然不配置这个文件也可以,那就会按默认的错误信息格式显示在页面上,其他不会受影响】。实现方法是在与之相关联的action相同的目录下建一个properties文件,文件名称为"actionname".properties,其中actionname为关联的action的名称。例如RegisterAction.properties,然后在这个文件里写内容,这个文件里等号左边的内容的前两部分是固定的,为invalid.fieldvalue,第三部分为属性名称,例如invalid.fieldvalue.username。等号右边为错误信息(注:这些信息添加的时候必须在myecplise里的Properties这个操作中点Add添加。不能在Source里手动写,因为添加完之后会给我们自动转码,而如果我们自己在Source里写的话就不会转码了)

那么又遇到问题了。因为在struts.xml文件里可以通过method=....指定访问时所调用的执行逻辑的方法,那么同一个action就有可能被很多地方调用,他们各自在这个action里都有一个自己调用的执行逻辑处理的方法,个处理各的,互不干扰。那么又出现问题了。既然各调用个的,而且逻辑也不同,那么输入校验的规则也就很可能不同(比如有四个逻辑),而现在只有一个validate()方法执行输入校验,也就是只有一种校验规则,这肯定是不能满足所有调用此action的客户端的。解决办法:在action里还可以定义其他校验方法,针对某个逻辑方法的校验方法。例如我的action里有execute()和test()两个逻辑处理方法,我可以定义一个针对test()方法的特定的校验方法,这个校验方法只针对test()方法里的内容做校验,其他方法里的东西它不管,命名规则是validate+逻辑方法名(首字母大写),就可以定义成validateTest(),这里做的输入校验只针对test()方法执行它里面属性的校验。针对execute()方法的校验方法可以定义成validateExecute()。当然,validate()方法也还可以保留(它是无论执行哪个逻辑处理方法,它都会执行),执行顺序是:首先执行自定义的那个校验(验证)方法,紧接着再去执行validate()方法【注:自定义的和validate()方法一定都会执行的】

struts2三个配置文件的解析顺序:先解析struts-default.xml;再解析struts-plaging.xml;最后解析我们自己写的struts.xml

默认action文件里执行的是execute()方法,但可以在配置文件里的action里显示的指定调用哪个方法,而不去调用execute()方法。(这个方法和execute方法除了名称不同外,其他都必须相同,包括返回值 抛异常 修饰符等)

没有反射,就没有任何一个框架

如果想使用全局类型转换器(就是此应用里遇到的所有词类型变量,都用此转换器来转换)。那么这个配置文件必须放到src下面,而且文件名字叫xwork-conversion.properties(必须是这个)

如果validate()方法通不过验证,那么页面就会转向input所标识的那个页面(一般这个页面就是开始填写信息的页面,让用户自己填),如果某属性set方法出错,会自动添加一个Field级别的错误消息。总的来说只要是执行过程中添加了Field级别或是Action级别的错误消息,不论是怎么添加的,那么在执行完validate()方法之后都会转到input标识的页面而不会再去执行execute()方法。注意;如果某属性的set方法出错了(比如Date类型的字段你填成字符串的了,set方法肯定会报错),那么后面还会执行validate()方法,不是说报错了就不往下执行了,但是后面的execute()方法肯定是不会执行了。

action文件里的流程,先调用相应属性的set方法,如果某个属性set方法出错就默认的自动为该属性添加一个Field级别的错误消息,然后调用validate方法执行输入校验,如果通过了并且上面执行的各个属性set方法没有出错那么就根据相应的返回值转向相应的成功页面,否则如果通不过就转向input所标识的页面【重点】








Action级别的错误消息是我们自己增加的,Field级别的错误消息可以是服务器为我们添加的,我们自己也可以添加Field级别的错误消息。


Field级别错误消息两种生成方式:
1、struts2自动帮助我们生成(当类型转换失败的时候,例如界面上定义名称为birthday的输入框输入aaa字符串点击提交,后台Action里birthday定义为Date类型,那么类型转换就会失败,此时Struts2就会自动帮助我们针对birthday这个属性生成Field级别的错误消息,格式为Invalid field value for field +属性名称)
2、我们自己增加Field级别的错误消息(和增加Action级别的错误消息一样)。
【注:一个Field可以对应多条错误消息,即:比如说birthday这个字段类型转换失败的时候,struts2会帮助我们生成一条错误消息,而如果我们自己也针对这个属性增加了一条Field级别的错误消息,那么在页面上就会针对这一个属性输出两条错误消息】


而在struts2往Field里面增加错误消息又分为两种情况:
1、发生在类型转换的时候(即上面提到的第一种情况,类型转换失败的时候,strus2自动帮助我们针对相应的属性往Field里面增加一条错误消息,格式Invalid field value for field +属性名称)。


又遇到新的问题了。在增加Field级别的错误消息的时候,在Action里我们一般都写的是比如”birthday invalid”,但是用户在界面上看到这种样式的信息显然不好看,我们应该提示给用户例如”出生日期不合法”这样的提示。那么现在就需要有一个配置文件来描述针对某个属性给用户输出错误信息的格式了。那么比如我是针对RegisterAction这个类里输入校验建立的这个文件,那么就需要再与RegisterAction相同目录下建立RegisterAction.properties配置文件(名称命名格式:Action类名+.properties),然后再里面做相应的配置,此文件的配置格式为:invalid.fieldvalue+.属性名称=针对此属性要在界面上输出的错误信息(添加完配置之后切换到配置文件的Source兰会看到等号右面的信息已变成uncode码)


现在又出现个问题,一般在同一个Action里不止一个方法,每一个方法都是不同的逻辑处理,最常见的例如一个Action里例如有增删改查四个方法,但在调用这四个方法分别处理业务逻辑时所要求的验证规则肯定不同,所以在一个Action里光有一个validate()方法肯定是不行的(不同的业务逻辑只有一套验证规则,显然这是很不合理的),那么struts2给出这样一种解决办法,可以在Action里定义自定义的验证方法,例如针对test()方法可以定义validateTest()验证方法,命名规则是“validate+需要验证的方法名称(首字母大写)”,那么这个方法就只针对test()方法做验证,对其他方法不管用。需要注意的是,如果Action里还有validate()方法的话,那么就首先执行自定义的验证方法,再执行validate()方法。

针对实例Struts2Validate.zip里的代码的一些说明:
在RegisterAction类里面的validateTest()方法是自定义的针对test方法的校验方法。命名规则validate+逻辑方法名(首字母大写)。
下面的代码this.addActionError("username invalid");//这里是调用父类ActionSupport类的addActionError方法将错误信息写到action里。然后在jsp页面上通过引入struts2自带的标签库将信息显示出来。
再下面的代码this.addFieldError("username","username invalid");//这是我们自己显示的添加field级别的错误信息,如果我们自己不显示的添加,那么在此属性校验出错的时候struts2会自动帮助我们添加固定格式的错误信息,页面调用标签显示错误信息的时候也会显示固定格式的错误信息。
针对RegisterAction类里的说明:这个action里有两个逻辑处理方法,test()和execute(),validateTest()方法是针对test方法的特定的校验方法,它只针对test()方法里的属性做校验,也就是说只有test()方法执行的时侯此方法才会执行。而validate()方法是无论执行哪个逻辑处理方法都会调用它来验证一下。调用顺序是先执行自定义的校验方法,再执行validate()方法。当然,validate()方法也可以不写。


       
【以上讲的是普通的自己编写代码校验方式,实例为Struts2Validate.zip。下面讲解使用校验器框架做校验,实例为Struts2Validation.zip】

下面讲解校验框架(使用校验框架校验):
使用校验框架需要在需要校验的Action类的相同包下建立一个xml文件,命名规则为“类名-validation.xml”(例如我们需要对RegisterAction类做校验,那么就需要再和它相同目录下建立RegisterAction-validation.xml)。

校验框架又分为两种情况:属性(字段)优先,校验器优先。


属性(字段)优先:在校验xml配置文件中,<validators>下面的子节点,如果是<field>就是属性优先,如果是<validator>就是校验器优先。


重点知识点:如果jsp页面上使用的是stuts2自带的标签中的表单的话,这种表单是增强型的表单,对于action里输出的错误信息(例如利用this.addFieldarror()方法添加的错误信息),要想在页面上显示出来,不用在页面上显示的调用struts2标签库里的错误信息(例如<s:fielderror></s:fielderror>)。自动就会显示出来,因为这种增强型的表单已经内置了错误消息输出的这个功能

使用校验框架对输入内容进行校验:
先写一个配置文件(对哪个action进行校验,此文件就放到和这个action相同的包下面即可),命名规则为
action名称-validation.xml,例如RegisterAction-validatioin.xml。
此校验框架又分为两种情况,第一种叫属性(字段)优先,另一种叫校验器优先

下面先讲第一种:先给出属性,后面跟着校验规则。就是属性优先。

注:配置文件里的根元素为validators,下面的子元素如果第一个是field(里面的name表示属性名称,继续往下的元素field-validator表示用什么类型的校验器对此属性进行校验,再往下就是校验规则和错误信息了),那么就是属性优先;如果是第一个是validate,那么就是校验器优先

注:每个属性可以包含多个校验器
注:对于field-validator元素里的type表示所用的校验器的类型,但这些类型哪来的呢?这个人为记不住,需要到一个jar包里去找,struts2的一个jar包,xwork-core-2.2.3.jar——com.opensymphony.xwork2.validator.validators——default.xml,这里面列出了struts2提供的所有校验器的类型,每种类型对应一个校验类。由这个类来处理校验过程。
注:又一个问题来了。field-validator里的type类型问题解决了,找到了。但这个元素里面的param里的名称又是哪来的呢?那就先通过field-validator到那个jar包的那个文件里找到这种校验类型对应的类,然后查看这个类的源代码,找到里面的param

注:这里的错误提示都是field级别的错误提示

重点:struts永远是先去执行类型转换,完了再执行输入校验



注:关联好源代码之后才能查看jar包里Java文件里的源代码


当同时使用到两种校验方式的时候,两种方式都会起作用。校验框架先执行,编码方式(validate方法方式)后执行
分享到:
评论

相关推荐

    [Struts 2权威指南--基于WebWork核心的MVC开发(高清完整版) 1/12

    第1章 Struts 2概述,第2章 Struts 2下的HelloWorld,第3章 Struts 2基础,第4章 深入Struts 2,第5章 Struts 2的类型转换,第6章 文件的上传和下载.,第7章 Struts 2的拦截器,第8章 Struts 2的输入校验,9.2 ...

    struts2学习笔记

    Struts2环境搭建 Struts2类型转换 Struts2输入校验 拦截器 文件的上传与下载 Struts2的国际化 深入探析 struts2与servlet API耦合方法

    struts2学习ppt

    掌握Struts2原理、基本配置及...掌握Struts2核心解析、国际化、类型转换、输入校验、OGNL、Struts2标签库 了解AJAX技术支持 掌握文件的上传与下载。 深入理解MVC与Struts之间的关系,并使用基本MVC和Struts进行项目开发

    Struts2电子课件

    Struts2的讲义 1、入门及基本配置 2、类型转化 3、输入校验 4、校验框架 5、拦截器 6、文件上传与下载 7、国际化 8、深入了解struts 9、ognl

    structs2教程

    structs2教程,重点介绍了Struts2入门及基本配置 Struts2核心概念及原理 Struts2输入校验 Struts2实现文件上传及下载 Struts2深入探索 Struts2的拦截器 Ognl语言 Struts2标签

    Struts in Action[文字版][中文]

    2.深入Struts架构 3.构建一个简单应用 4.配置Struts组件 5.用ActionForm传递数据 6.连线ActionForward 7.设计ActionMapping 8.和女主角Action对象共舞 9.扩展ActionServlet 10。显示动态内容 11.用Tiles开发应用 12....

    struts深入理解

    Struts 使用 Model 2 架构。Struts 的ActionServlet 控制导航流。其他Struts 类,比如Action, 用来访问业务逻辑类。...一个 Action可以校验输入,并且访问业务层以从数据库或其他数据服务中检索信息。

    跟我学javaweb全套ppt

    《跟我学Java Web》内容包括搭建Web开发环境、HTML相关技术基础知识、...输入校验、国际化、Struts2的各种标签、对Ajax的支持等)、Spring2.5(容器、装配Java Bean、JDBC和Hibernate模板等)以及Hibernate3技术详解...

    跟我学Java_Web源代码

    《跟我学Java Web》内容包括搭建Web开发环境、HTML相关技术基础知识、...输入校验、国际化、Struts2的各种标签、对Ajax的支持等)、Spring2.5(容器、装配Java Bean、JDBC和Hibernate模板等)以及Hibernate3技术详解...

    java web技术开发大全(最全最新)

    《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring...

    Struts in Action中文版

    2. 深入 STRUTS架构..................................................................................37 2.1. 随便谈谈......................................................................................

    java web开发技术大全

    《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring...

    struts in Action

    2. 深入STRUTS 架构..................................................................................37 2.1. 随便谈谈.......................................................................................

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

     国内知名的高端IT技术作家,已出版《Spring 2.0宝典》、《基于J2EE的Ajax宝典》、《轻量级J2EE企业应用实战》、《Struts 2权威指南》、《Ruby On Rails敏捷开发最佳实践》等著作。 目录: 第0章 学习Java...

Global site tag (gtag.js) - Google Analytics