分享知识-快乐自己:Struts2(动态方法、动态结果、通配符、方法内部跳转、action跳转、OGNL 的使用及注意事项)
这里主要以案例演示:涵盖以下知识点
1、动态方法调用:使用关键 符号 ! 进行操作 例如:/命名空间 ! 方法名
2、动态结果集:就是说,通过后台返回的结果 ${} 获取,重定向到符合预期的页面。
3、万能通配符:*_* :第一个 * 为 类名、第二个 * 为方法名;{1}是第一个 *
4、内部方法的调用:就是说 Action 类中的 A() 调用 B() A方法返回B()的结果集
5、跳转Action:就是说访问一个方法,根据返回的结果匹配 result中的 name 值 跳入下一个action (result type=chain)
6、OGNL:(不过多讲述相关概念,这里以代码为核心)
值栈的内部结构分为两部分:
第一部分:root,结构是 list 集合一般操作的都是 root 里面的数据
第二部分:context,结构为 Map 集合
使用经历:
root 单列集合下的 前台获取的时候不需要写 #
context 双列集合 前台获取的时候需要写 #
1、往 单列集合中推送 集合类型的数据时,不能触碰到集合的引用名称。
将泛型集合推送到值栈中:
使用 <s:debug/> 标签查看 值栈的信息:
2、值栈的访问顺序为 从上往下 寻址。如有同名的属性名,则寻址离值栈顶端最近的。
核心代码截取:推送到root 也就是单列集合下
使用 <s:debug/> 标签查看 值栈的信息:
3、在我们实现 Action 接口 或 继承ActionSupport 的类中的成员属性都是放在 root 单列集合下的
4、往值栈 context 推送 key那一列会有我们指定的引用名称(需要获取的时候需要 #)
以上为可能会遇到的问题。
完整Demo展示:
案例结构:
为演示通配符需要方法名与jsp名称一致,add.jsp 与 list.jsp 创建在 CoordinAction文件下
POM:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <!--测试JAR--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <!--javaee.jar包是支持javaweb编程的基础jar包,跟javase编程需要jre一样!--> <dependency> <groupId>javaee</groupId> <artifactId>javaee-api</artifactId> <version>5</version> </dependency> <!--Struts2-core核心--> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.4.1</version> </dependency> <!--xwork 的核心包,最主要的功能是 支持了过滤器(interceptor)。--> <dependency> <groupId>org.apache.struts.xwork</groupId> <artifactId>xwork-core</artifactId> <version>2.3.4.1</version> </dependency> </dependencies>
CoordinAction:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.gdbd.action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import java.util.Map; /** * @author asus */ public class CoordinAction extends ActionSupport { private String message; private String mess; ...省略 Get Set /*** * 动态方法的调用 * @return */ public String list() { this.setMessage("通过调用 add 方法拿到返回的name寻址,再次调度 Action 中的list"); return "list"; } public String add() { this.setMessage("动态方法调度!!!!"); return "add"; } public String get() { Map<String, Object> session = ActionContext.getContext().getSession(); if (this.message != null) { session.put("message", "动态结果集调用成功!!!"); this.setMess("demo2"); } else { session.put("message", "动态结果集调用失败!!!"); this.setMess("error"); } return "get"; } /*** * 内部方法的调用 * @return */ public String demo1() { Map request = (Map) ActionContext.getContext().get("request"); request.put("message", "测试数据Action内部调度!!!"); return "demo2"; } public String demo2() { return demo1(); } }
OgnlAction:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.gdbd.action; import com.gdbd.bean.UserInfo; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.ValueStack; import java.util.List; import java.util.ArrayList; /** * @author asus */ public class OgnlAction extends ActionSupport { private List<UserInfo> List; ...省略 Get Set /*** * OGNL:存储到单列集合 */ public String demo1() { ActionContext context = ActionContext.getContext(); //获取值栈 ValueStack valueStack = context.getValueStack(); //伪造数据 UserInfo userInfo=new UserInfo(); userInfo.setUserName("MLQ"); userInfo.setUserPwd("MLQ"); UserInfo userInfo1=new UserInfo(); userInfo1.setUserName("FKX"); userInfo1.setUserPwd("FKX"); List<UserInfo> infoList=new ArrayList<UserInfo>(); infoList.add(userInfo); infoList.add(userInfo1); /*** * 将数据推送到单列集合中 * 缺点:对集合类型进行操作的时候,没有办法触碰到集合的引用名称 * 例如:添加一个 泛型List<UserInfo> 集合 没有 */ valueStack.push(userInfo); valueStack.push(userInfo1); valueStack.push(infoList); return "demo1"; } /*** * OGNL:存储到双列集合 */ public String demo2() { ActionContext context = ActionContext.getContext(); //获取值栈 ValueStack valueStack = context.getValueStack(); //伪造数据 UserInfo userInfo=new UserInfo(); userInfo.setUserName("MLQ"); userInfo.setUserPwd("MLQ"); UserInfo userInfo1=new UserInfo(); userInfo1.setUserName("FKX"); userInfo1.setUserPwd("FKX"); List<UserInfo> infoList=new ArrayList<UserInfo>(); infoList.add(userInfo); infoList.add(userInfo1); /*** * 将数据推送到双列集合中 */ //valueStack.push(infoList);将泛型集合推送到值栈中,没有引用地址 this.List=infoList; valueStack.getContext().put("infoList",infoList); return "demo1"; } }
UserInfo:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.gdbd.bean; import java.io.Serializable; /** * user 实体类 * @author asus */ public class UserInfo implements Serializable { private String userName; private String userPwd; ...省略 Get Set }
struts.xml:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!-- 是否开启动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"/> <!--更改 Struts.xml的 节点不需要重启--> <constant name="struts.devMode" value="true"></constant> <!--动态--> <package name="default" namespace="/" extends="struts-default"> <!--动态方法调度 使用( ! ) --> <action name="demo" class="com.gdbd.action.CoordinAction"> <result name="add">/error.jsp</result> </action> <!-- *_*: 第一个 * 为 类名 第二个 * 为 方法名 --> <!--万能通配符--> <action name="*_*" class="com.gdbd.action.{1}" method="{2}"> <result name="{2}">{1}/{2}.jsp</result> </action> </package> <!--内部方法的调用--> <package name="demo" namespace="/demo1" extends="struts-default"> <!-- action 内部方法调度 --> <action name="mo" class="com.gdbd.action.CoordinAction" method="demo1"> <result name="demo2">/demo2.jsp</result> </action> <!-- action 内部方法调度 重定向页面 --> <action name="mo1" class="com.gdbd.action.CoordinAction" method="demo1"> <result name="demo2" type="redirect">/demo2.jsp</result> </action> </package> <!--调度 action 中的方法,在根据结果集再次跳转到 action 方法 --> <package name="demo2" namespace="/demo2" extends="struts-default"> <action name="listdemo" class="com.gdbd.action.CoordinAction" method="list"> <result name="list">/demo2.jsp</result> </action> <action name="mo" class="com.gdbd.action.CoordinAction" method="add"> <result name="add" type="chain"> <!--默认是转发--> <param name="actionName">listdemo</param> <param name="namespace">/demo2</param> </result> </action> </package> <!--动态结果:重定向页面(转发无效)--> <package name="demo3" namespace="/demo3" extends="struts-default"> <action name="mo" class="com.gdbd.action.CoordinAction" method="get"> <result name="get" type="redirect">${mess}</result> </action> <action name="demo2"> <result>/demo2.jsp</result> </action> <action name="error"> <result>/error.jsp</result> </action> </package> <!--OGNL 测试--> <package name="demo4" namespace="/demo4" extends="struts-default"> <!--推送到单列集合中--> <action name="mo" class="com.gdbd.action.OgnlAction" method="demo1"> <result name="demo1">/demo1.jsp</result> </action> <!--推送到双列集合中--> <action name="mo1" class="com.gdbd.action.OgnlAction" method="demo2"> <result name="demo1">/demo1.jsp</result> </action> </package> </struts>
add.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 9:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>add==========</h1> </body> </html>
list.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 9:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>list==========</h1> </body> </html>
demo1.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%@ taglib prefix="s" uri="/struts-tags" %> <%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 9:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <fieldset> <legend>OGNL:获取的结果(值栈单列集合)</legend> 姓名为:<s:property value="userName"></s:property> <br/> 密码为:<s:property value="userPwd"></s:property> </fieldset> <br/><br/> <fieldset> <legend>OGNL:获取的结果(值栈Root 单列集合)</legend> 姓名为:<s:property value="List[0].userName"></s:property> <br/> 密码为:<s:property value="List[1].userPwd"></s:property> </fieldset> <br/><br/> <fieldset> <legend>OGNL:获取的结果(值栈双列集合)</legend> 姓名为:<s:property value="#infoList[0].userName"></s:property> <br/> 密码为:<s:property value="#infoList[1].userPwd"></s:property> </fieldset> <br/><br/> <fieldset> <legend>OGNL:获取的结果(值栈双列集合,便利读取)</legend> <s:iterator value="infoList" id="info"> <s:property value="#info.userName"/> </s:iterator> </fieldset> <br/><br/> <s:debug/> </body> </html>
demo2.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 9:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <h1>${message}</h1> </body> </html>
error.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 9:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <h1>${message}</h1> </body> </html>
index.jsp:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<%-- Created by IntelliJ IDEA. User: asus Date: 2018/11/17 Time: 10:34 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <fieldset> <legend>动态方法调度</legend> <a href="/demo!add">动态方法调度</a> </fieldset> <br/><br/> <fieldset> <legend>万能通配符</legend> <a href="/CoordinAction_list">万能通配符</a> <a href="/CoordinAction_add">万能通配符</a> </fieldset> <br/><br/> <fieldset> <legend>内部方法调度返回的信息</legend> <a href="/demo1/mo">内部方法调度返回的信息:默认是转发</a> <a href="/demo1/mo1">内部方法调度返回的信息:使用重定向</a> </fieldset> <br/><br/> <fieldset> <legend>调度 action 中的方法,在根据结果集再次跳转到 action 方法</legend> <a href="/demo2/mo">跳转 add 方法 根据结果再次 指向list:转发操作</a> <a href="#">###</a> </fieldset> <br/><br/> <fieldset> <legend>动态结果调度</legend> <a href="/demo3/mo?message=123">动态结果调度:重定向</a> <a href="#">###</a> </fieldset> <br/><br/> <fieldset> <legend>OGNL</legend> <a href="/demo4/mo">OGNL:存储到值栈的单列集合</a> <a href="/demo4/mo1">OGNL:存储到值栈的单列集合</a> </fieldset> <br/><br/> </body> </html>
web.xml:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <!--核心过滤器--> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>