1,strtus2的执行流程:
页面form表单数据提交到name.action:
struts2的过滤器(org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter)拦截请求,查找struts.xml文件里的action元素,action元素的name属性值和form表单提交的action对应,则实例化action元素的class属性值对应的类,并且将form表单提交的值通过setXxx()方法设置到class类属性。
之后调用action类的execute方法,该方法必须返回一个字符串!根据返回的字符串在action元素的子元素result的name属性name对应的值,如果匹配,则返回result元素值所指定的页面。
通常每个action类都要继承com.opensynphony.xwork2.ActionSupport类
2,对于自定义类型转换器来说需要提供三个信息:Action的名字,Action中待转换的属性名以及该属性对应的类型转换器。其中Action的名字是通过属性文件(和Action同包)来获得的,Action中待转换的属性名是通过属性文件中的key值获得的,该属性对应的类型转换器是通过key值所对应的value值获得的。
3,可使用struts2框架自带的类型转换器StrutsTypeConverter简化类型转换。StrutsTypeConverter继承于DefaultTypeConverter。提供两个抽象方法,分别为convertFromString和converToString,分别实现从页面向后台对象转换和从后台对象转换成字符串
4,全局类型转换,属性文件在src根目录下,属性文件名为xwork-conversion.properties。待转换的类=转换器的名字
struts2校验:
一编码方式:在action中实现validate方法,该方法在ActionSupport类中是空实现,需要用户自己继承实现方法,定义该方法后,框架自动先执行validate方法,再执行execute方法。
struts先进行类型转换后进行数据校验,如果在上述过程中都不会执行execute方法,页面会转向struts.xml中action元素名input的result指定的页面(一般指定为输入页面)。如果在类型转换时发生的错误,将错误放到fielderror中而不是actionerror中!
ActionSupport类的addActionError()方法的实现:首先创建一个ArrayList对象,然后将错误消息添加到ArrayList中。
当调用getActionErrors()方法返回Action级别的错误信息列表时,返回的实际是集合的一个副本,因此调用clear()方法无法清除原来集合的错误信息!Action级别的错误信息对开发者来说是只读的。
Field级别的错误信息底层是用LinkedHashMap实现的,该Map的key值是String,value是一个List
如果想清除错误信息:可以调用clearActionErrors(),clearFieldErrors()和clearErrors()
Action中自定义方法的输入校验,对于通过action的method属性所指定的自定义方法,其对应的自定义输入校验方法名为validateMyExecute()(假设自定义方法名为myExecute),底层是通过反射来调用的。
当在action中中指定execute方法时,会先调用自定义的validate方法,然后再调用validate方法,校验过程出现任何错误,不会在执行execute方法。
自定义field级别的错误提示信息1,新建一个以action名字命名的属性文件。2,然后再该属性文件中指定每一个出错字段的错误信息invalid.fieldvalue.fieldname=error msg.
struts2的校验框架(一个有效的xml文件),具体来说分为字段优校验和校验器优先校验。
对于国际化的资源文件命名规则。package_语言名(小写)_国家名(大写)
struts2框架校验执行的先后顺序
1,首先执行校验框架,2,执行自定义方法的校验方法。
3,执行validate方法
对于struts.xml文件的结果配置来说,局部要优于全局。
我们既可以在action中定义异常与结果,也可以定义全局的异常与结果,局部总是优先与全局的,如果定义成全局,那么可以为所有的action所公用,而局部的异常与结果只能被当前的action所独享,不能为其他action所使用。
sturts2的模型驱动(Model Driven),和属性驱动的比较:
1,属性驱动灵活,准确,模型驱动不灵活,很多时候,页面提交过来的参数并不属于模型中的属性。
2,模型驱动更加符合面向对象的编程风格,使得我们获得的是对象而不是一个离散的值。
服务器端代码单元测试有两种模式:
1,容器内测试(jetty)
2,Mock测试(继承HttpServletRequest、HttpSession、HttpServletResponse等servlet API)
Preparable接口的作用是让Action完成一些初始化工作,这些工作放在prepare方法中执行的!
防止表单重新提交的方法:
1,通过重定向
2,通过Session Token(Session 令牌),当客户端请求页面时,服务器会通过token标签生成一个随机数,并且将该随机数放置到session中,然后将随机数发送到客户端,当客户端发送请求时,服务器会接收到随机数并且与session中所保存的随机数进行比较,这时两者是相同的,服务器就认为是第一次提交,并且更新这个随机数,如果客户端再重新提交,那么客户端发送服务器端得还是之前那个随机数,而服务器端得随机数已经变了,两者不同,这服务器认为是重复提交,故不成功,进而转向invalid.token所指向的结果页面。
拦截器(Interceptor):是sturts的核心,
1,编写实现Interceptor接口的类
2,在struts.xml文件中定义拦截器
2,在action中使用拦截器
一旦定义了自己的拦截器,将其配置到action上后,需要在action的最后加上默认的拦截器栈,否则默认的拦截器就失效了。
定义烂机器可以直接继承AbstractInterceptor抽象类(该类实现了Interceptor接口并对init和destroy方法进行了空实现)然后实现其抽象方法即可。
方法拦截器(可以对方法进行过滤拦截)
在方法过滤拦截器中,如果既没有指定includeMethods参数,也没有指定execludeMethods,所有的方法都会被拦截。如果只指定了includeMethods参数,只拦截包含的方法。
package元素的abstract属性表示该包是抽象的,不能直接使用,需要由子包继承。如struts-default包。
package元素的namespace属性起到命名空间分割的作用,通常将namespace的值设置为目录的名字。
文件上传:
进行文件上传时,必须将表单的method属性设置为post,将enctype属性设置为multipart/form-data.
struts2文件上传:首先将客户端上传的文件保存到struts.multipart.saveDir键所指定的目录中,如果该键所对应的目录不存在那么就保存到javax.servlet.context.tempdir环境变量指定的目录中。
action中所定义的File类型变量file实际上指向的是临时目录中的临时文件,然后再服务器端通过IO写入指定目录。