1. 方法调用
1. 默认方法
2. 自定义方法
3. 动态方法
一个Action类可以有多个业务逻辑方法,但是只需要配置一个Action标签,不需要method属性,在调用时指出Action名和业务逻辑方法。使用动态方法调用步骤如下:
-
struts.xml 开启动态方法调用
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
-
编写Action
-
注册Action
<!-- 2.5 版本后需要配置此属性才能够使用动态方法和通配符 -->
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="userinfoAction" class="com.javaee.struts2.action.UserinfoAction">
<result>/index.jsp</result>
</action>
==注意== 2.5 版本后为了安全动态方法和通配符在使用的时候需要添加如下代码:
<global-allowed-methods>regex:.*</global-allowed-methods>
禁用动态方法
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
动态方法特点:
-
一个Action类中有多个业务方法
-
一个Action类只需要配置一个<action>标签
-
相比使用method属性,Action的配置数量减少
-
请求时指明Action和业务方法
==总结==:动态方法核心就是去掉Action中method属性,在URL请求调用的时候通过!携带方法名称
4. 通配符
result 默认是转发
redirect 重定向URL 或Action
redirectAction 重定向到Action
<action name="user_*" class="com.javaee.struts2.action.UserinfoAction" method="{1}">
<result name="success">/index.jsp</result>
</action>
<action name="*_*" class="com.javaee.struts2.action.{1}Action" method="{2}">
<result name="success">/index.jsp</result>
</action>
Action 匹配顺序
-
优先使用完全匹配
-
当完全匹配匹配上,在使用通配符匹配
-
当多个通配符都匹配上时,优先使用写在前面的action
默认Action配置
当访问Action 找不到的时候会访问默认Action
<default-action-ref name="index" />
<action name="index">
<result>/index.jsp</result>
</action>
2. 返回值
2.1 name 属性
==result== : 每个Action 返回一个字符串,Struts2根据这个值来决定响应什么结果。 ==name属性==:result的逻辑名称。和Action里返回值匹配。默认是success ==值==:指定对应的实际资源位置
2.2 type 属性
type 属性指定result的类型,不同类型的result 代表的不同的结果输出 type默认是是转发(dispatcher)
type 常见取值介绍
-
redirect 请求重定向指定的URL或者Action
-
redirectAction 请求重定向到指定的Action
-
chain Action链式处理,将请求转发(forward)到指定的Action
-
json 实现Ajax时返回JSON对象
2.3 struts2 中 dispatcher、redirect和chain类型的区别
-
dispatcher:用于页面转发,页面跳转过程一直是同一个线程,Action中的数据一直保存在。
-
redirect:可用于返回一个页面、一个action、链接到一个网址。
-
缺点:redirect把一个http返回码(SUCCESS)以及返回的页面位置一起重新发给web服务器,容纳后由web服务器产生一个新的HTTP请求,就会产生一个新的线程,保存在原来Action执行的线程中的数据就无法访问。所以,result需要包含Action的数据,那么redirect不是一个可行的办法。因为新的HTTP请求时在Servlet容器的新的线程中处理的,ActionContext中的所有状态都不会存在。
-
chain:功能与redirect的action转发类似,不过与redirectaction转发功能不同的是它可以将Action中的数据一直保存在同一个HTTP请求中。
==1.跳转方式==dispatcher和chain是服务器端跳转,所以客户端只发起一次请求,产生一个action;redirect和redirectAction是客户端跳转,所以客户端发起两次请求。
==2.跳转内==容dispatcher和redirect跳转的是views(一般是jsp页面);chain和redirectAction跳转的是一个action。
2.3 全局返回结果
<!-- 全局返回配置,必须放在action的前面 -->
<!-- action中的result优先于全局result,当全局的result和Action中的result中都没有配置的时候就去父类中查找,如果父类中没有时就回报错 -->
<global-results>
<result name="error">/error.jsp</result>
</global-results>
==全局结果总结==
-
使用<result > 来配置,只不过不是在<action>中配置,而是在<global-result>中嵌套
-
当所有Action需要共享某个结果时,可以定义为全局结果、
-
全局结果的影响范围整个包含的所有Action,如果不是对所有Action都有效的结果,不要定义在全局返回结果中
==Result搜索顺序==
-
首先找自己的<action>元素内的<result>元素是否有匹配的。如果有就执行这个result,没有执行下一步
-
其次找自己<action>所在的包的全局result是否有匹配的,如果有就执行这个result,没有执行下一步
-
递归寻找自己的包的父包、祖包中的全局result是否有匹配的,如果有就执行这个result,没有执行下一步
-
最后都没找到就抛出Exception异常
2.4 动态返回结果
private HouseUser user;
//记录下一个跳转的Action是谁
private String nextDispose;
//userACtion访问的方法
public String login() {
if (user.getUsername().equals("common")&& user.getPassword().equals("common")) {
nextDispose = "common";// 下一个result中name的别名
return SUCCESS;
} else if (user.getUsername().equals("admin")&& user.getPassword().equals("admin")) {
nextDispose = "admin";
return SUCCESS;
} else {
return INPUT;
}
}
//省略getXXX()/setXXX()
<!-- 动态结果 -->
<package name="user" namespace="/user" extends="struts-default">
<action name="login" class="com.javaee.struts2.action.UserAction" method="login">
<result name="success" type="redirectActioin">${nextDispose}</result>
<result name="input">/login.jsp</result>
</action>
</package>
2. 返回JSON数据
-
采用传统JSON输出方法没有返回值,通过Struts2调用Servlet 底层API获得Response对象(HttpServletResponse response=ServletActionContext.getResponse();)进行JSON数据输出
struts.xml配置
<package name="default" extends="struts-default" namespace="/">
<action name="testJsonAction" class="com.javaee.struts2.action.TestJsonAction" method="doAction">
</action>
</package>
==注意==:action 没有result,且方法也是没有返回值
-
使用Struts2 方式
-
添加struts2-json-plugin.jar
-
package 必须继承json-default
-
result 返回值 type类型修改为json
<result type="json">
<!-- 这里指定将被Struts2序列化的属性,该属性在action中必须有对应的getter方法 -->
<!-- 默认将会序列所有有返回值的getter方法的值,而无论该方法是否有对应属性 -->
<param name="root">dataMap</param>
<!-- 指定是否序列化空的属性 -->
<param name="excludeNullProperties">true</param>
<!-- 这里指定将序列化dataMap中的那些属性 -->
<param name="includeProperties">userList.*</param>
<!-- 取消浏览器缓存-->
<param name="noCache">true</param>
<!-- 设置服务器响应类型-->
<param name="contentType">application/json</param>
<!-- 这里指定将要从dataMap中排除那些属性,这些排除的属性将不被序列化,一半不与上边的参数配置同时出现 -->
<param name="excludeProperties">SUCCESS</param>
</result>
==result==总结
-
name 属性:result逻辑名称,和Action里返回值匹配,默认"success"
-
type 属性:结果类型,默认dispatcher
-
全局结果:通过<global-results> 配置,对包内所有Action都有效的结果
-
动态结果:执行结果在配置时并不知道在运行时刻才能够确定