1、相对于Struts 1 而言,Struts 2 采用了低侵入式设计,Struts 2 不要求Action类继承任何的Struts 2 的基类,获实现任何Struts 2 接口。在这种设计方式下,Struts 2 的Action类是一个普通的POJO(通常应该包含一个无参数的execute方法),从而有很好的代码复用性。
2、Struts 2 通常直接使用Action来封装HTTP请求参数,因此,Action类中应该包含与请求参数对应的属性,并且为这些属性提供对应的getter和setter方法。
3、Action类里的属性,不仅可用于封装请求参数,还可以用于封装处理的结果。例如,我们希望将服务器提示的“登录成功”或其他信息在下一个页面输出,那么可以在Action类中增加一个tip属性,并为该属性提供getter和setter方法:
private String tip;
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
}
一旦在Action中设置了tip属性的值,就可以在下一个页面中使用Struts 2 标签来输出该属性的值。:
<s:property value=”tip” />
4、为了让用于开发的Action类更规范,Struts 2 提供了一个Action接口,这个接口定义了Struts 2 的Action处理类应该实现的规范。下面是标准的Action接口的代码:
public interface Action {
public static final String ERROR = “error”;
public static final String INPUT = “input”;
public static final String LOGIN = “login”;
public static final String NONE = “none”;
public static final String SUCCESS = “success”;
public String execute() throws Exception;
}
5、Struts 2 为Action接口提供了一个实现类:ActionSupport。该类是Struts 2 默认的Action处理类,开发者的Action类如果继承该类,将大大地简化Action的开发。另外,如果我们配置的Action类没有指定class属性,系统自动使用ActionSupport类作为Action的处理类。
6、Struts 2 框架提供了一种很轻松的方式来访问Servlet API。Web应用通常要访问的Servlet API就是:HttpServletRequest、HttpSession和ServletContext,这三个接口分别代表JSP内置对象中的request、session和application。
7、Struts 2 提供了一个ActionContext类,通过该类可以访问Servlet API。常用方法有:
·Object get(Object key):该方法类似于调用HttpServletRequest的getAttribute(Object key);
·Map getApplication():返回一个Map对象该对象模拟了该应用的ServletContext实例。
·static ActionContext getContext():静态方法,获取系统的ActionContext对象。
·Map getParameters(Object key):获取所有的请求参数。类似于调用HttpServletRequest对象的getParameterMap方法。
·Map getSession():返回一个Map对象,该对象模拟了HttpSession实例。
·void setApplication(Map application):直接传入一个Map实例,将该Map实例里的key-value对转换成application的属性名和属性值。
·void setSession(Map session):直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名和属性值。
8、虽然Struts 2 提供了ActionContext来访问Servlet API,但这种访问毕竟不是直接获得Servlet API的实例。为了在Action中直接访问Servlet API,Struts 2 还提供了如下的接口:
·ServletContextAware:实现该接口的Action可以直接访问Web应用的ServletContext实例。
·ServletRequestAware:实现该接口的Action可以直接访问Web应用的HttpServletRequest实例。
·ServletResponseAware:实现该接口的Action可以直接访问Web应用的HttpServletResponse实例。
9、必须指出的是:虽然可以在Action类中获取HttpServletResponse,但如果希望通过HttpServletResponse来生成服务器响应是不可能的,因为Action只是业务控制器。
10、为了能直接访问Servlet API,Struts 2 还提供了一个ServletActionContext工具类,这个类包含了如下几个静态方法:
·static PageContext getPageContext():取得Web应用的PageContext对象。
·static HttpServletRequest getRequest():取得Web应用的HttpServletRequest对象。
·static HttpServletResponse getResponse():取得Web应用的HttpServletResponse对象。
·static ServletContext getServletContext():取得Web应用的ServletContext对象。
11、Struts 2 使用包来组织Action,因此将Action定义放在包定义下完成,定义Action通过使用<package.../>下的<action.../>子元素完成。
12、配置<package.../>元素时,必须制定name属性,这个属性是引用包的唯一标识,除此之外,还可以制定一个可选的extends属性,extends属性值必须是另一个包的name属性。指定extends属性表示让该包继承另一个包。子包可以从一个或多个父包中继承到拦截器、拦截器栈、Action等配置。
13、Struts 2 提供了一种所谓的“抽象包”,抽象包意味着该包不能包含Action的定义,为了显式地指定一个包为抽象包,可以为该<package.../>元素增加:abstract=”true”的属性。
14、<package.../>元素支持的属性:
·name:这是一个必须的属性,该属性指定了该包的名字,该名字是该包被其他包引用的key。
·extends:该属性是一个可选属性,该属性指定该包继承其他包。继承其他包,可以继承其他包中的Action定义、拦截器定义等。
·namespace:该属性是一个可选属性,该属性定义该包的命名空间。
·abstract:该属性是一个可选属性,指定该包是否是一个抽象包。抽象宝中不能包含Action的定义。
15、注意:Struts 2 的配置文件是从上到下定义的,因此,父包应该在子包的前面定义。
16、struts-default.xml文件中定义了struts-default抽象包,该包中包含了大量的结果类型定义、拦截器定义、拦截器引用定义等,这些定义是配置普通Action的基础,所以,开发者定义的package通常应该继承struts-default包。
17、Struts 2 之所以提供命名空间的功能,主要是为了处理同一个Web应用中包含同名Action的情形,Struts 2 以命名空间的方式管理Action,同一个命名空间里不能有同名的Action,不同的命名空间里可以有同名的Action。当某个包指定了命名空间后,该包下所有的Action处理的URL应该是:命名空间 + Action名。
18、默认命名空间里的Action可以处理任何命名空间下的Action请求,而根命名空间下的Action只负责处理根命名空间下的Action请求,这是根命名空间和默认命名空间的区别。
19、struts.xml文件中的的Action配置片段:
<package>
<action name=”Login” class=”lee.LoginAction”>
<result.../>
<result.../>
</action>
...
<package>
20、定义<action.../>子元素时,如果需要在name属性中使用斜线(/),则需要制定Struts 2 允许Action name中出现斜线。通过设定struts.enable.SlashesInActionNames常量指定,设置其值为true。
21、不推荐在Action的name属性中使用点(.)或中划线(-),因为可能会引发一些未知异常。
22、动态方法调用(Dynamic Method Invocation; DMI)是指表单元素的action并不是直接等于某个Action的名字,而是以如下的形式来指定表单的action属性:
action=”actionName!methodName”
23、注意:使用动态方法调用前,不许设置Struts 2 允许动态方法调用,通过设置struts.enable.DynamicMethodInvocation常量为true来开启。
24、Struts 2 支持使用通配符来配置Action,在配置<action.../>元素时,允许在指定name属性时使用模式字符串(即用“*”代表一个或多个任意字符,接下来就可以在class,method属性以及<result.../>子元素中使用{N}的形式代表前面第N个星号所匹配的子串:
<action name=”*Action” class=”org.crazyit.app.action.LoginRegistAction” method=”{1}”>
<result name=”input”>/login.jsp</result>
<result name=”error”>/error.jsp</result>
<result name=”success”>/success.jsp</result>
</action>
25、可以在class和method属性中同时使用{N}表达式:
<action name=”*_*” class=”actions.{1} method={2} >
26、对于使用Struts 2 框架的应用而言,尽量不要让超链接直接连接到某个视图资源,因为这种方式增加了额外的风险。推荐将所有的请求都发送给Struts 2 框架,即使是简单的超链接。
27、除非请求的URL和Action的name属性绝对相同,否则将按照先后顺序决定哪个Action处理用户请求,因此,应该将name=”*”的Action配置在最后,否则,Struts 2 将使用该Action来处理所有希望使用模式匹配的请求。
28、使用<default-action-ref.../>元素可以为Web应用配置默认的Action:
<default-action-ref name=”simpleViewResultAction” />
29、使用<default-class-ref.../>元素为Struts 2 配置默认Action处理类:
<default-class-ref class=”com.opensymphony.xwork2.ActionSupport” />
30、使用<result.../>元素定义逻辑视图名和物理视图名的映射关系。
31、Struts 2 支持多种结果映射:不仅可以是JSP视图资源,也可以是FreeMarker视图资源,甚至可以将请求转给下一个Action处理,形成Action的链式处理。
32、Struts 2 提供了2种结果:
·局部结果:将<result.../>作为<action.../>元素的子元素配置。
·全局结果:将<result.../>作为<global-results.../>元素的子元素配置。
33、一个Action可以对应多个结果。
34、配置<result.../>元素时通常需要指定如下两个属性:
·name:该属性所配置的逻辑视图名。
·type:该属性指定的结果类型。
最典型的的<result.../>配置片段如下:
<result name=”success” class=”dispatcher”>
<param name=”location”>/thank_you.jsp</param>
</result>
35、对于dispatcher结果类型,上面使用的<param.../>的name属性可以指定为如下两个值:
·location:该参数指定了该逻辑视图对应的实际视图资源。
·parse:该参数指定是否允许在实际视图名字中使用OGNL表达式,该参数值默认为true。
36、Struts 2 默认的结果类型就是dispatcher,默认的name属性值为success。
37、Struts 2 的结果类型要求实现com.opensymphony.xwork2.Result,这个结果是所有结果类型的通用接口。如果我们需要定义自己的结果类型,就应该提供一个实现该接口的类,并在struts.xml中配置该结果类型:
<result-type name=”dispatcher” class=”org.apache.struts2.dispatcher.ServletDispatcherResult” default=”true” />
38、不同的结果类型可以支持不同的参数:
<result-type name=”chart” class=”org.apache.struts2.dispatcher.ChartResult”>
<param name=”height”>150</param>
<param name=”width”>200</param>
</result-types>
39、Struts 2 内建的支持结果类型:
·chain:Action链式处理的结果类型。
·dispatcher:用于使用JSP作为视图的结果类型
·freemarker:用于指定使用FreeMarker模板作为视图的结果类型。
·httpheader:用于控制特殊的HTTP行为的结果类型。
·redirect:用于直接跳转到其他URL的结果类型。
·redirectAction:用于直接跳转到其他Action的结果类型。
·stream:用于向浏览器返回一个InputStream(一般用于文件下载)。
·velocity:用于指定使用Velocity模板作为结果的视图类型。
·xslt:用于与XML/XSLT整合的结果类型。
·plainText:用于显示某个页面原始代码的结果类型。
40、使用redirect结果类型的效果是,系统将调用HttpServletResponse的sendRedirect(String)方法来重定向指定视图资源,这种重定向的效果就是重新产生一个请求,因此,所有的请求参数、请求属性、Action实例和Action中封装的属性全部丢失。
41、redirectAction结果类型和redirect类型非常相似,一样是重新生成一个全新的请求。但与redirect结果类型区别在于:redirectAction使用ActionMapperFactory提供的ActionMapper来重定向请求。当需要让一个Action处理结束后,直接将请求重定向到另一个Action时,应该使用这种类型。
42、对于redirect和redirectAction两种结果类型,都是重新生成一个新请求,区别是前者通常用于生成一个堆具体资源的请求,而后者通常用于生成对另一个Action的请求。两个结果类型都会丢失请求参数、请求属性和前一个Action的处理结果。
43、配置<result.../>元素时,可以使用${属性名}的方式来指定视图资源。在这种配置方式下,${属性名}里的属性名就是对应Action中的属性名,并且,还可以使用完全的OGNL表达式。
44、<result.../>元素也可以作为<global-results.../>元素的子元素,此时,该<result.../>元素配置了一个全局的结果,将对所有的Action生效。
45、如果一个Action里包含了与全局结果里同名的结果,则Action里的局部Result会覆盖全局Result。也就是说,当Action处理用户请求结束后,会首先在本Action里的局部结果里搜索逻辑视图对应的结果,只有Action里的局部结果里找不到对应逻辑视图的结果,才会到全局结果里搜索。
46、PreListener是一个监听器接口,它可以在Action完成控制处理之后,系统转入实际的物理视图之前被回调。
47、Struts 2 应用可由Action、拦截器添加PreResultListener监听器。添加PreResultListener通过ActionInvocation类的adPreResultListener()方法完成。一旦为Action添加了PreResultListener监听器,该监听器就可以在应用转入实际物理视图之前就会回调该监听器的beforeResult()方法;一旦为拦截器添加了PreResultListener监听器,该监听器会对该拦截器所拦截的所有Action都起作用。