今天主要是写新产品的用户需求文档,并对一些方案进行可行性分析等,没有实际做什么开发任务,当既然定下今天要学习structs2的任务,就在中午和晚上返回抽空看了《structs2完全学习手册》一书和搜集一些相关资料。感觉那本书写的很水,要点不突出,条理性不强,只是跳着看了一些自己感兴趣的内容。把今天学到的一些要点总结下:
1.加入Struts2所依赖jar包到tomcat容器webapps 下面项目目录下面的 \WEB-INF\lib\
2.web.xml配置我们的核心控制器StrutsPrepareAndExecuteFilter
3.新建一个Action类,处理业务逻辑
4.在classpath下新建struts.xml文件,注册Action类
5.访问action:http://localhost/appName/<PackageNamespace>/<ActionName>.<Extension>
<PackageNamespace> 代表你在struts.xml中配置package的namespace,action配置中name! <Extension>默认可不写或者是.action
分为内部配置文件和开发人员使用的配置文件。其中,内部配置文件由Structs2框架自动加载,对其自身进行配置,如structs-default.xml和structs-plugin.xml;外部配置文件由开发人员使用,如web.xml,structs.xml等。
1.在根元素<struts>下可以使用include子元素引入其他的配置文件,这样可以将各个模块分散在不同的配置文件中进行配置。
2.package元素下可以定义全局视图,如果两个package要共享相同的全局视图,那么为它们定义一个相同的父包。
3.<action>元素的method属性可以不设置,默认为execute;class属性可以不设置,默认为ActionSupport。
4.<result>元素的type属性和name属性都可以不设置,默认值分别为dispatcher和success。当<result>元素中只有默认的<param>子元素要设置时,可以将该<param>子元素中的内容直接写在<result>标签中。
5.在<package>元素下配置<default-action-ref>子元素,用于说明在该包下不存在的action路径映射,都可以统交给一个默认的<action>元素去处理。
6.在<package>元素下配置<default-class-ref>子元素,用于说明默认的Action类是可以进行配置修改的。
7.在根元素<struts>下可以使用constant子元素配置常量。
8.从strut2的核心jar包内的org.apache.struts2包下的default.properties文件中可以看到 各个常量的注释说明,典型几个常量:
<constant name="struts.action.extension" value="do,go"/>配置访问Action的后缀,可以配置多个后缀名。 提示:default.properties文件中为该常量配置了一个空字符串。
<constant name="struts.devMode" value="true"/>可以让struts在控制台中打印出更多的信息和重新加载配置文件。
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>可以配置不支持动态方法调用。
<constant name="struts.configuration.xml.reload" value="true"/>可以让struts重新加载配置文件,但不会导致web应用重新启动。
9.常量可以在下面多个文件中进行定义,struts2加载常量的搜索顺序如下,后面的设置 可以覆盖前面的设置:
default.properties文件
struts-default.xml
struts-plugin.xml
Struts.xml(建议放到该文件中)
struts.properties(为了与webwork向后兼容而提供)
web.xml
当用户发出请求后,web.xml中的StrutsPrepareAndExecuteFilter核心控制器进行拦截过滤。一般情况下,它负责拦截所有的用户请求。默认情况下,如果用户的请求路径不带后缀或者以".action"结尾,这是请求将被转入structs2框架处理,否则structs2忽略请求。当请求转入structs2框架时会先经过一系列的拦截器,然后再到action。与structs1不同,structs2对用户的每一次请求都会创建一个action,所有structs2中的action是线程安全的。
如果不存在相应的包,则查找上一层的包名,注意,只要一旦追溯到了一个最匹配的上层包名,不管这个包中是否存在要访问的Action,都不会再追溯更上层的包名了。如果struts2定位到的包名中不存在当前要访问的Action ,struts2接着还会在默认名称空间寻找该Action,只有在默认名称空间的包名中还没找到该action时,才报错action找不到的错误。注意("/"也算是一个包,只是这个包比较特殊!)
1.自定义拦截器
<1>定义一个类实现interceptor接口
<2>在structs.xml中注册拦截器
<3>为action应用拦截器
2.其他
<1>一旦为某个action显式指定了某个拦截器,则所属包中定义的默认拦截器将不起作用。
<2>如果想保留structs2的拦截器,又想使用我们自定义的拦截器,可以定义一个拦截器栈。
<3><default-interceptor-ref name="defaultStack"/>把拦截器定义为默认的拦截器。每个包只能定义一个默认的拦截器。
可以对action中的指定方法和所有方法进行校验。
1.提供了两种实现方式
采用手工编写代码实现
基于xml配置方式实现
2.手工编写代码对action中所有方法进行校验
通过重新validate()方法实现,当某个数据校验失败时,应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息。为了使用addFieldError()方法,action可以继承ActionSupport,如果系统的fieldErrors包含失败信息,structs2会将请求转发到名为input的result,在input视图中可以通过<s:fielderror/>显示失败信息。
<1>提供validate方法
<2>提供input视图,一般该视图为提交信息的页面。
<3>在编辑页面导入s标签,使用<s:fielderror/>显示失败信息。
3.手工编写代码对action中指定方法进行校验
通过validateXxx()方法实现,它之后校验action中方法名为xxx的方法。
4.输入校验流程
<1>类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
<2>如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldError里。不管类型转换是否出现异常,都会进入第3步。
<3>系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
<4>再调用action中的validate()方法。
<5>经过上面四个步骤,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
注意:如果确认validate方法中没有问题,但还是跳到input视图时,需要判断类 型是否转换失败。
5.基于xml方式对action中所有方法进行校验
使用xml配置方式实现输入校验,action也需要继承ActionSupport,并且提供校验文件,校验文件和action类纺织同一个包下。文件的取名格式为:ActionClassName-validation.xml。
采用配置文件校验方式校验后,Action中的validatable有关的校验方法也会执行,且配置文件校验方式在validate校验方法之前执行。
系统定义的校验器在xwork-2.x.jar中...validators包下的default.xml中找到。
6.基于xml方式对action中指定方法进行校验
xml文件的取名格式为:ActionClassName-actionName-validation.xml 。如:
UserAction-user_add-validation.xml(action的名称是由url路径决定的)。
在处理请求方法上使用@SkipValiation注解,配置文件校验方式也将无效。
7.基于xml校验的一些特点
当为某个action提供了所有方法和指定方法校验两种规则时,系统会先寻找所有方法的校验文件,然后继续寻找指定方法的校验,当寻找完所有的相关校验文件后,会将所有的校验规则进行汇总,然后全部应用于action的校验。如果两个校验文件中指定的校验规则发生冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类的action校验文件会先被搜索到。
1.采用基本类型接受请求参数(get/post)
在action类中定义与请求参数同名的属性,structs2便能自动接受请求参数并赋予给同名属性。如:
请求路径:http://localhost/test/view.action?id=78
public class ProductAction{
public Integer id;
setter和getter.......
}
structs2通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值。
2.采用复合类型接收请求参数
请求路径:http://localhost/test/view.action?product.id=78
public class ProductAction{
private Product product;
setter和getter.....
}
Structs2首先通过反射技术调用Product的默认构造器创建product对象,然后通过反射技术调用product中的请求参数同名的属性的setter方法来获取请求参数值。
3.其他
<1>Struts框架在把请求交给action的业务方法去处理之前,可以将请求参数来填充到Action的相应属性中,所以,对于请求消息中的每个参数(包括网页表单中的每个字段),Action中 通常都有一个对应的属性来接受相应的参数值。
<2>在action的业务方法中也可以访问Servlet API,通过request.getParameter获得参数,框架使用中不建议这种方法。
<3>在structs2.1.6的版本中,会出现中文乱码问题,可以自己写一个filter,在structs2之前进行过滤。
1.要想让浏览器把文件内容也传给服务器,必须将form表单的enctype属性设置为"multipart/form-data",提交方式必须是post。
2.文件过大,请求将会被拒绝。在structs.xml中可以更改它的最大文件上传限制。
<constant name="struts.multipart.maxSize" value="60000"></constant>
3.文件上传action类中的命名一定要符合structs2的规范。
上传文件的名称必须是:上传文件+FileName;
上传文件的类型必须是:上传文件+ContentType。
如:上传文件名称为:uploadFiles,则上传文件的名称命名是uploadFilesFileName上传文件的类型命名为uploadFilesContentType,切勿写成uploadFileFileNames。
1.在action元素的name属性中可以使用*通配符,它可以匹配除了"/"以外的多个连续字符,在action元素的class和method属性以及result元素中可以引用*通配符在访问期间实际匹配的内容。
2.如果*匹配的内容为空,则调用execute方法;对于采用下划线连接*的方式,如果访问路径中没有为*部分指定内容,那么在访问路径中还可以省略下划线。
3.使用*通配符可能导致有多个action元素与一个访问路径匹配,这时候以排在配置文件中最后的配置项为准,所以更具体的模式应在更不具体的模式之后进行配置。