SSM 则指的是 SpringMVC 做控制器(controller),Spring 管理各层的组件,MyBatis 负责持久化层。
共同点:
1.Spring依赖注入DI来管理各层的组件。
2.使用面向切面编程AOP管理事物、日志、权限等。
不同点:
1.Struts2 和 SpringMVC 控制器(controller)控制视图和模型的交互机制的不同,
2.Struts2是Action类级别,SpringMVC是方法级别,更容易实现RESTful风格。
下面是我的笔记,复制上来不好看,但是我在笔记软件上整理的很好。
struts2提供了两种校验方式:服务器端校验(更重要)和客户端校验
也分为:validate()校验方法、自定方法的义校验方法、校验框架校验方法三种,其中校验框架校验方法又分为两种:校验器优先校验器和字段优先校验器.(没有业务逻辑的校验)
1、通过validate()校验方法进行校验
我们只写错误的情况,正确的情况我们不做处理。
注意:struts2当输入校验发生错误的时候,struts2会默认转到一个name为input的这样一个<result>,其实就是当输入错误的时候应该,用户应该尝试着再一次提供输入信息,因此转到input页面。
当发生错误时,struts2给出来各种错误级别的提示:
(1) action级别this.addActionError(anErrorMessage)
addActionError(放的是错误的提示信息),它应该是一个集合,每次都忘这个集合中添加错误信息。
页面使用<s:actionerror/>标签显示错误信息,指如果存在action的错误信息,就把错误信息显示出来。
<s:actionerror/>标签还有许多的属性,如cssStyle=""定义错误信息的cssStyle,如:cssStyle="color:red"错误信息为红色.
(2) 字段级别this.addFieldError(fieldName, errorMessage)
addFieldError(字段名, 错误提示信息),它应该是一个Map类型,有name和errorMessage两个参数。
页面使用<s:fielderror cssStyle="color:blue"></s:fielderror>标签来显示错误信息。
注意:当页面使用的是struts2自己的标签库的时候,它能自动显示field级别的错误信息,是struta2标签自带的功能。
若不需要这样的功能,把theme的值设为simple即可。
(3) ActionSupport类的addActionError方法的实现:首先创建一个ArrayList对象,然后将错误信息添加到该对象中。
(4) 当调用getActionError()方法返回Action级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本的调用clear()方法清除的依旧是副本中懂得元素而非原集合中的元素,此时原集合中的内容没有受到任何的影响。换句话说,Action级别的错误信息列别对开发者来说是只读的。
(5) FiledError级别的错误信息底层是用LinkHashMap实现的,该Map的key是String类型,value是List<String>类型,这就表示一个FieldName可以对应多条错误信息,这些错误信息都放置在List<String>集合当中。所以在页面中一个字段可能有多个错误信息。
(6) 判断是否有Action级别或者Field级别的错误根据hasActionError和hasFieldError两个方法的返回值,他们的返回值为布尔型,有错误返回true,没错误返回false。
(7) clearActionErrors()清除所有的Action错误
clearFieldErrors()清除所有的Filed错误
clearError()相当于上面两个方法的集合
例子:如下图,age为int类型。birthday和graduate是Date类型
为什么action级别中会出现age invoked!,birthday invoked!,graduate invoked!三个错误信息?
答:因为我们输入的都是字符串,因此在action中找不到对应的参数类型为String的setAge,setBirthday,setGraduate方法,因此就不能给这三个成员变量赋值,但是age,birthday,graduate在实例化对象时已经有默认的初始化值0,null,null,这样的值均满足if条件判断。
下面的前三个field错误信息是因为我们输入的字符格式错误,它是发生在类型转换阶段,不是发生在输入校验阶段。
知识点:类型转换的错误信息放置到field中。
2、执行流程
(1)首先进行类型转换
(2)然后再进行输入校验(执行validate方法)。
(3)如果上述过程中出现任何错误,都不会再执行execute或自定义方法。会转向struts.xml中对应action中name为input的<result>标签对应的页面。
当field级别错误和action级别错误都没有任何的错误才会执行execute方法。
3、自定义方法的校验方法
(1) 对于一个自定义的方法来说(如:上面的myExecute()),它的validate()方法在自定义方法之前被调用,即:先进行校验,再执行自定义方法。
(2) 自定义方法的自定义输入校验方式(action中method所指定的自定义方法)
public String myExecute() throws Exception{ return SUCCESS } 一个自定义方法;
校验方法的一般格式:public void validateMyExecute(){} 方法名为validate开头,再加上方法的名字,且方法名首字母大写。底层通过反射来实现的。我们称validateMyExecute()为myExecute()的输入校验的方法。
(3) 当Action中既有自定义方法的校验方法也有validate方法,则先执行自定义方法的校验方法,然后再执行validate方法,若两个校验方法有action或field级别错误,则都不会执行execute或自定义execute方法。
若把method中自定义方法删掉,则不会执行自定义发的校验方法,而validate方法是会一定会执行的(Action中写了这个方法),因此,validate是用来校验execute方法的。
4、Field级别错误的自定义错误提示
在Action同级目录下建一个以Action名字命名的properties文件,配置文件名的格式:Action名字.properties
如:RegisterAction.properties
配置文件内容写法格式:invalid.fieldvalue.字段名=错误提示信息 如:invalid.fieldvalue.age
其中字段名是Action中的属性名,即当那个属性发生Field错误时所提示的错误信息。
5、Struts2的校验框架(有效的xml文件)
(1) 校验框架xml文件和被校验的action在同一个包下
(2) 校验框架xml文件命名格式:Action名字-validation.xml 如:RegisterAction-validation.xml
(3) 具体来说分为字段优先校验器(field)与校验器优先校验器(validator)
6、字段优先校验器(先有字段再有校验器)
xwork内置校验器在com.opensympony.xwork2.validator.validators目录下的default.xml文件中。
有以下几中校验器分类:
required、requiredstring 、int、long、short、double、date、fieldexpression、expression、email
url、visitor、conversion、stringlength、regex、conditionalvisitor
(5) Struts2的校验框架xml文件标签及标签属性分析
① <field name=""></field>校验器类型,name属性值为Action中待校验的属性值(成员变量)
如:<field name="username"></field>
②<field-validator type=""></field-validator>校验规则或校验器,在<field>里面可以有多个<field-validator>
如:<field-validator type="requiredstring"></field-validator>指username只能为字符串,不能为空
若:type="required" 指除了string之外的其他类型
type="stringlength" 指字符串的长度
type="int" 指待检验的值必须为int类型
type="date" 指定带检验的值为date类型,且<param></param>标签中的字符串值必须写成日期的样 式,因为<param>标签中我们写的是字符串的日期样式,而在xmwork内部校验器的对应属 性是Date类型,所以这里用到了类型转换器。
③ <message>username</message>当发生错误的时候的提示信息标签
如:<message>username can't be blank!</message>
<message>标签属性key 如:<message key="username.invalid"></message>
注意:这个key变量的值是在配置文件中的,配置文件和Action在同一包下
书写格式:英文 package_en_US.properties 中文 package_zh_CN.properties
package.properties为默认的资源文件,当所要找的资源文件不存在时找默认的资源文件。
配置文件中的key和message中的key名字必须一样,若不一样,则会把message中的key值作为错误提示信息显 示在页面。
*. 通过修改浏览器显示语言的首选项来切换浏览器使用什么语言显示页面内容。
④ <param name=""></param><param name=""></param> 是<field-validator>子标签,可选.
param中的属性名都必须和源代码对应的类中的属性名一致,这样才能正确赋值。
如:<param name="minLength">4</param>设置字符串最大长度
<param name="maxLength">6</param>设置字符串最小长度
<param name="trim">false</param>设置是否去掉字符串两边的空格
拿minLength和maxLength的引用:
${minLength}取得是minLength的值,${maxLength}${minLength}取得是maxLength的值
如:<message>username should be between ${minLength} and ${maxLength}!</message>
7、校验器优先校验器(先有校验器再有字段)
<validator type="requiredstring"> -->这是一个校验器
<param name="fieldName">username</param>-->定义待校验的字段名,这里的name值是固定为fieldName
</validator>
校验器优先校验器和字段优先校验器可以混合使用.
struts2输入校验总结:struts2框架校验执行的先后顺序:
1) 首先进行类型转换(只有类型转换好后才能进行校验)
2) 首先执行校验框架的校验方法(xml文件)
3) 执行自定义方法的校验方法
4) 执行validate()校验方法
当validate()方法执行完以后,struts2框架才会检查Field级别或者Action级别有没有任何的错误消息,当出现任何一条错误消息的时候,struts2都不会执行自定义的execute方法和execute()方法,进而转向struts.xml中<result>标签中name为input所对应的页面。
推荐使用validate()校验方法。
回xiaoqulai,我早就把scope的设置改为了prototype,但是问题依旧,可能是我眼拙,调试时看不出什么问题,不知道还有没有什么建议--------------------
你的问题我下面已经说了。
你的值出现累加就是因为你的三次请求的三个线程访问了同一个对象实力。这说明两个可能:
1.你的action对象是单例的——尽管你一再强调你的配置文件使用的是prototype。请检查以下你的配置文件是否有错。比如有没有可能使用了某些插件,覆盖了你的设置。
2.你的标签使用不当,建议你了解<s:select />的每一个属性,也许你还需要在多一个属性没有写。
我不知道你的问题在哪,但我可以告诉你如何解决这个问题:就是在<s:select />中加一个属性value=""就可以了,假如有value这个属性的话。
你还可以multiple="false"
如果你的action是单例的,那么里面的定义的变量就会被多个线程共享。
你前后提交的两个请求是不同的线程,它们会在变量中累计,因此,你的第二次请求会加上第一次的请求。
所以,我可以肯定的告诉你,你的问题是你的Action不是原子的,而是单例的。
所以第一,你一定要将action配置为prototype。
如果还出现这个问题,其实是可以通过调试找出问题的。
我们没有必要对一个技术太过深究,struts2确实很好,但并不代表你需要使用它的一切,所以你如果找不出问题来,就别用它的标签好了。建议使用sun官方的jstl标签加el表达式。
另,不懂就别到这乱说,搞些错误的东西来误导人哈!!
--------------------------------------------
laogao3232 说:
这个是谁教你的啊!
action里怎么能写
private String str...
这个说法不正确的,我们不仅要这么些,而且还鼓励这么写,我们要去掉他娘的from对象。
struts 2.0之前的版本最大败笔就是form对象和struts标签,form对象严重影响了我们优良的程序设计,通过DTO设计模式,我们原本可以直接将对象传递到jsp,因为有了一个form,我们不得不将对象一个个变成form,再传过去。
struts标签更是烂,生成的form表单,连ID属性都没有,大家知道,ID属性是DOM树中唯一的引用标识,我们很多客户端的JS和CSS都需要ID!!!
struts2.0的标签大有改进,但还是不够灵活。
总值,struts2 以前的版本不允许是因为action中的变量是多线程共享的,但struts2 action对象是是可以配置为原子的prototype,就没问题了。
楼主的问题在于还没有理解struts2的精髓,就算这个问题解决了,还会碰到其它很多的问题。建议先理清struts2的原理及流程。