form.../>默认已提供了输出校验错误的能力。
是否觉得这种校验忒不尽人情了,别急,Struts2可让你完全用配置来校验表单的,让你的Action还是那个Action(继承ActionSupport,无须实现validate()方法),只需写一个ActionName-validattion.xml文件扔在与Action同位置的目录中即可,这实质就是用的基于XWork的验证框架。
1.WebWork的核心控制器是ServletDispatcher,映射到*.action的即可。
在WebWork与Struts2的struts.xml和struts.properties相对应的分别是xwork.xml和webwork.properties,文件内容几乎一样,只几个关键字的差异。
2.Struts2的struts.xml中的name属性相当于struts1的的path属性,但在这里不需要以"/"开始。
3.Action中使用业务逻辑组件实例时,通常不直接New,而会通过工厂方法或IOC容器。
虽然WebWork有IOC容器,但Struts2通常会使用Spring的IOC。
4. 可把struts.xml拆成多个文件,如struts-part1.xml、struts-part2.xml...等,然后在struts.xml中逐个、...即可。
看看struts2-core-x.x.x.jar中的struts-default.xml为你内建了多少东西吧。
5.Struts2的官方说是它要求在支持Servlet2.4/JSP2.0的容器中运行,不过我仍然把那个简单的例子(web.xml中用web-app_2_3.dtd)放到Tomcat4.1.30(支持到Servlet2.3/JSP1.2)下运行了一番,能正常工作,不知可能产生的问题有哪些。
6.Struts2还提供一种类似Eclipse那种可插拔的方式来安装插件,看到下载的Struts2的lib目录下有好多struts2-xxx-plugin.jar,这些包中都有一个struts-plugin.xml(就是一个struts.xml配置文件),当把struts2-xxx-plugin.jar拷入到WEB-INF/lib下,这个struts-plugin.xml就会自动被加载。
你也可以像这样做自己的插件包。
struts.properties中属性struts.configuration.files=struts-default.xml,struts-plugin.xml,struts.xml。
7. struts.properties中本人认为比较重要的属性struts.action.extension、struts.serve.static.browserCache、struts.enable.SlashesInActionNames、struts.devMode、struts.i18n.reload、struts.configuration.xml.reload、struts.custom.i18n.resources、struts.i18n.encoding。
好多属性值都支持逗号分隔的多个值。
默认的属性配置在default.properties。
8.默认情况,*.action请求交给Struts2处理,你也可以改成其他扩展名,只要改struts.properties中的struts.action.extension属性值,如struts.action.extension=unmi,action,则*.unmi和*.action都会被Struts2处理了。
9.Struts2比起Struts1来在开发时不仅改了struts.xml不用重启应用,就连改了国际化资源文件都可以不需要重启应用。
设置struts.i18n.reload=true即可。
10.Struts2提供了两种方式来管理Struts2属性,既可以写在struts.properties,也可以写在struts.xml中配置为constant元素,如。
相信大多数人还是倾向于写在struts.properties中。
1.按这个顺序加载Struts2的常量,struts-default.xml、struts-plugin.xml、struts.xml、web.xml;后加载的会覆盖前面的同名常量。
强烈不推荐在web.xml中配置Struts2常量。
2.Struts1中有一种Action类型是ForwardAction,而在Struts2中相应的配置方式是/showcase.jsp,Showcase.action直接映射到/showcase.jsp。
3.struts.xml中的namespace(命名空间)相当于Struts1的模块的概念,但比Struts1的模块间切换要便。
例如,对于以下的配置
因actionGetBooks所在的包指定了命名空间,所以URL就需要/book/GetBooks.action与它映射了。
如果未指定命名空间或指定为""就是默认命名空间,指定"/"就是根命名空间,URL就应该是/GetBooks.action。
配置在默认命名空间中的Action相当于全局的,即类似于Struts1的。
也就是说当找不到指定命名空间(例如/barspace/bar.action)中的Action(bar.action)时,就会尝试去默认命名空间("")里去找。
4.系统不会严格区分Action里哪个属性是用于封装请求参数的属性,那个属性是封装处理结果的属性。
对系统而言,封装请求参数的属性和封装处理结果的属性是完全平等的。
5.Struts2的Action可以是一个POJO,可以实现Action接口,也可以继承ActionSupport。
实际上ActionSupport类是Struts2默认的Action处理类,就是说,配置Action时未指定class属性时,系统自动指定为ActionSupport类。
6.Struts2中要访问ServletAPI必须借助于ActionContext类,其中有访问对HttpServletRequest(request),HttpSession(session),ServletContext(application)进行操作的方法(操作的是各自的attribute属性),不过还没发现如何操作HttpServletResponse(response)对象。
注意,这些方法都转换成了对Map实例的操作,而非真实的ServletAPI实例,Struts2会完成与实际存储的映射,所以Action仍然是脱离ServletAPI的。
ActionContext直接的get()和put()方法针对的是request的属性。
7.Struts2也可以直接访问ServletAPI实例,让你的Action实现后面其中一个接口就能获取到相应ServletAPI实例:
ServletContextAware、ServletRequestAware、ServletResponseAware。
注意要实现的接口方法。
如果觉得实现接口的方式麻烦,那么可以借助ServletActionContext的方法来拿到ServletAPI的各个实例。
这样却是让Action与ServletAPI耦合起来了。
8.即使我们在Struts2的Action中获得了HttpServletResponse对象,也不要尝试直接在Action中生成对客户端的输出,没效果的,因为Action只是一个控制器,它并不直接对浏览者生成任何响应。
这也是为什么ActionContext未提供对HttpServletResponse的操作,只是操作Cookie要用到response。
在Struts1中,如果Action返回null时,可以通过response.getWriter().println("HelloWorld.");输出内容到页面。
9.Struts2也有像Struts1那样的对Action动态方法调用的特性,它是通过指定form的action="ActionName!
methodName.action"来实现的,例如某表单的action="Login!
regist.action",提交后将会调用name="Login"的Action类的regist()方法,而非默认的execute()方法。
这种方式可以在一个Action中包含多个处理逻辑。
是不是Struts1要方便,不需要在配置文件中对这个Action配置额外的属性。
10.可为action配置指定一个method属性,同上,这种方式也在一个Action类中定义多个逻辑,每个处理方法映射成一个逻辑Action,有不同的name属性,非常类似于Struts1的MappingDispatchAction。
缺点就是不像上面那样,被分开的多个逻辑Action不能共享配置,并且action配置的class属性值产生冗余。
1.动态Action:
元素的一个前所未有的特性是,name属性可以用通配符,class和method属性中可以用name中的匹配参数,{0}/{1}的形式。
举两个例子说明:
①
URL是registAction.action时,会执行LoginRegistAction类实例的regist()方法
②
URL是Book_save.action时,会执行actions.BookAction类实例的save()方法
说明:
{1},{2}是用来匹配name属性中的*,这和正则表达式一样的,{0}表示的完整的name属性值。
这也是托Struts2的每请求产生新的Action的实例才能这么用的,试想一下,Struts1是没法针对通配符来预先加载好所有的Action实例的。
可由此定义一个能用的Action,里也能用参数。
/{1}.jsp
2.关于在中使用通配符时的校验文件命名规则。
校验文件的搜索规则是:
①--validation.xml 为name属性值
②-validation.xml
同时有这两个文件时,后面的规则能与前面的规则叠加或覆盖,例如①中有name域的校验,②中有password域的校验,这两个文件同时存在所在路径时,会同时校验name和password域。
例如对于
URL是registAction.action时,会搜索校验文件LoginRegistAction-registAction-validation.xml和LoginRegistAction-validation.xml。
3.使用通配符就会涉及到URL与哪个Action匹配的问题。
例如匹配有name为"*"、"*Action"、"LoginAction"的,如果URL与某个Action的name完全相同(如LoginAction.action),否则按顺序来匹配,而不是按匹配度来对应。
如abcAction.action会匹配到"*",而不是"*Action"。
4.可配置默认的Action,URL匹配不到对应的Action时就用它,用配置在中。
5.Struts2支持两种,配置在中的局部result,配置在中的全局result。
默认的name属性是"success";默认的type属性是"dispatcher",即使JSP类型。
6.type="plaintext"的会显示页面的源文件,如果其中有中文一般会产生乱码,这时候可设置它的charSet属性为"GBK",用标记。
7.的dispatcher和redirect类型的区别就是一个是转发(带请求参数、属性、址址栏不变)和重定向(丢失请求参数、属性、重新产生请求,所以地址栏会变)。
8.redirect-action类型是重定(不是转发)向到一个Action上,那么要为指定两个参数actionName和namespace。
简写为actionName。
这种类型相当于在Struts1中的 /anotherAction.do写法。
当然在Struts2中也可以用redirect类型写成相同的形式。
9.动态结果资源有两种,根据的name属性的模式匹配后的参数和请求参数决定结果。
①
/{1}.jsp
URL为crud_delete.action处理成功后会转到delete.jsp页。
②
/show${user.type}
要在ShowAction的设置了属性${user.t