Struts2框架自学之路——值栈
来源:互联网 发布:淘宝店组织架构 编辑:程序博客网 时间:2024/06/02 00:41
目录
- 目录
- Servlet和Action的区别
- 什么是值栈
- 获取值栈对象
- 值栈的内部结构
- 向值栈存放数据
- 向值栈存放对象
- 向值栈存放List集合
- 从值栈获取数据
- 获取字符串
- 获取对象
- 获取List集合
- 其他操作
- EL表达式获取值栈数据
Servlet和Action的区别
在正式讲解值栈之前,我们先来了解下Servlet和Struts2中Action中的区别:
- 对于Servlet而言,默认在第一次请求访问时被创建,创建成功后驻留在内存中,直到Web应用关闭。后续对该Servlet的请求,将都使用原先创建的Servlet对象进行处理。
- 对于Action,则每次请求访问Action时,均会创建新的Action对象处理请求。
什么是值栈
在Servlet中,我们使用域对象存放数据,然后在页面中使用EL表达式获取数据。在Struts2中同样支持这样的存取操作。同时,Struts2中还提供了另一种存储机制——值栈,类似于域对象,可以存值也可以取值。如在Action中我们可以数据存储到值栈中,在页面中我们可以获取到值栈中的数据。
值栈存储的位置
每次请求访问Action时,均会创建新的Action对象处理请求。此时,在每个Action对象中都有且只有一个值栈对象。
获取值栈对象
获取值栈对象有多种方式,常用方式是通过调用ActionContext对象的getValueStack方法获取值栈对象。如:
// 1. 获取ActionContext对象ActionContext context = ActionContext.getContext();// 2. 调用ActionContext对象的方法获取值栈对象ValueStack valueStack = context.getValueStack();
在每个Action对象中只有一个值栈对象。如:
ActionContext context = ActionContext.getContext();ValueStack valueStack1 = context.getValueStack();ValueStack valueStack2 = context.getValueStack();System.out.println(valueStack1 == valueStack2); // 同一值栈对象
值栈的内部结构
debug标签的使用
使用struts2中的标签debug,我们可以查看值栈结构和存储值。使用如下:
通过访问Action,执行Action中的方法,返回结果,匹配返回值对应转发的JSP页面,在该JSP页面中使用该标签。(为什么不“将该标签放置为JSP页面后直接访问JSP页面”呢?因为值栈对象存在于Action中,访问Action同时也是创建Action的过程,Action对象将拥有一个值栈对象。)
VSDebugAction.java
package com.wm103.action;import com.opensymphony.xwork2.ActionSupport;public class VSDebugAction extends ActionSupport { @Override public String execute() throws Exception { return SUCCESS; }}
在struts.xml中的配置:
<package name="demo1" extends="struts-default" namespace="/"> <action name="debug" class="com.wm103.action.VSDebugAction"> <result name="success">/debug.jsp</result> </action></package>
debug.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--导入struts标签库--%><%@ taglib uri="/struts-tags" prefix="s"%><html><head> <title>debug标签的使用</title></head><body> <%--使用struts2标签查看值栈结构--%> <s:debug></s:debug></body></html>
将应用部署到服务器后访问VSDebugAction,显示debug.jsp页面,如下:
值栈内部结构
值栈分为两部分:
第一部分为root部分,以List集合方式存储数据(我们一般也是操作root这一部分的数据),如:
第二部分为context部分,以Map集合方式存储数据。如:
注:我们会发现值栈的root部分:在Action没有进行任何操作时,root部分栈顶为Action对象的引用。我们可以知道Action对象中有值栈对象,同时值栈对象中也存放着Action对象的应用。
向值栈存放数据
在Struts2中,向值栈中存放数据有多种方式:
(1)获取值栈对象,调用值栈对象的set方法存放数据。如:
ActionContext context = ActionContext.getContext();ValueStack valueStack = context.getValueStack();valueStack.set("vs-key", "vs-value");
debug标签显示调用set方法存放数据后值栈的结构如下(数据被存到Map集合中,最后压入值栈中,如果后续还有调用set方法存值的话,将用刚保存数据的Map集合再次保存数据):
(2)获取值栈对象,调用值栈对象的push方法存放数据。如:
ActionContext context = ActionContext.getContext();ValueStack valueStack = context.getValueStack();valueStack.push("abcd");
debug标签显示调用push方法存放数据后值栈的结构如下:
(3)【常用方式!】在Action定义变量,生成变量的get方法。如:
这里定义了一个username变量。
package com.wm103.action;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.util.ValueStack;/** * Created by DreamBoy on 2017/5/27. */public class ValueStackAction extends ActionSupport { private String username; public String getUsername() { return username; } @Override public String execute() throws Exception { // 第一种 调用值栈的set方法存放数据 ActionContext context = ActionContext.getContext(); ValueStack valueStack = context.getValueStack(); valueStack.set("vs-key", "vs-value"); // 第二种 调用值栈的push方法存放数据 valueStack.push("abcd"); // 第三种 在Action定义变量,生成变量的get方法 this.username = "DreamBoy"; return SUCCESS; }}
debug标签显示存放数据后值栈的结构如下:
可以发现数据以Action成员变量的形式存入值栈中。
向值栈存放对象
实现步骤:
(1)定义对象变量(可以初始化);
(2)生成变量的get方法;
(3)在Action执行方法中给对象设置值。
案例如下:
ObjectAction.java
package com.wm103.action;import com.opensymphony.xwork2.ActionSupport;import com.wm103.entity.User;public class ObjectAction extends ActionSupport { private User user = new User(); public User getUser() { return user; } @Override public String execute() throws Exception { this.user.setUsername("DreamBoy"); this.user.setPassword("123456"); return SUCCESS; }}
向值栈存放List集合
实现步骤:
(1)定义List集合变量(可以初始化);
(2)生成变量的get方法;
(3)在Action执行方法中给List集合设置值。
案例如下:
ListAction.java
package com.wm103.action;import com.opensymphony.xwork2.ActionSupport;import com.wm103.entity.User;import java.util.ArrayList;import java.util.List;public class ListAction extends ActionSupport { private List<User> list = new ArrayList<>(); public List<User> getList() { return list; } @Override public String execute() throws Exception { User user1 = new User(); user1.setUsername("DreamBoy"); user1.setPassword("123456"); User user2 = new User(); user2.setUsername("DreamBoy223333"); user2.setPassword("223333"); list.add(user1); list.add(user2); return SUCCESS; }}
从值栈获取数据
使用struts2的标签property
和OGNL表达式获取值栈中的数据:<s:property value="OGNL表达式"/>
。
以下案例的Action类:
VSGetDataAction.java
package com.wm103.action;import com.opensymphony.xwork2.ActionSupport;public class VSGetDataAction extends ActionSupport { // 在这里定义存入值栈中的变量 // 对应的get方法 @Override public String execute() throws Exception { // 在这里设置变量的值 return SUCCESS; }}
在struts.xml中Action的配置:
<package name="demo1" extends="struts-default" namespace="/"> <action name="vsGetData" class="com.wm103.action.VSGetDataAction"> <result name="success">/data.jsp</result> </action></package>
data.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--导入struts标签库--%><%@ taglib uri="/struts-tags" prefix="s"%><html><head> <title>从值栈中获取数据</title></head><body> <%--在这里写从值栈中获取数据的案例--%></body></html>
获取字符串
在VSGetDataAction中定义字符串并存入值栈,如下:
private String username; public String getUsername() { return username; } @Override public String execute() throws Exception { this.username = "Hello Struts2!"; return SUCCESS; }
在data.jsp中获取值栈中的数据:
<s:property value="username"/>
获取对象
在VSGetDataAction中定义对象并存入值栈,如下:
private User user = new User(); public User getUser() { return user; } @Override public String execute() throws Exception { this.user.setUsername("DreamBoy"); this.user.setPassword("123456"); return SUCCESS; }
在data.jsp中获取值栈中的数据:
<s:property value="user.username"/><s:property value="user.password"/>
获取List集合
在VSGetDataAction中定义List集合对象并存入值栈,如下:
private List<User> list = new ArrayList<>(); public List<User> getList() { return list; } @Override public String execute() throws Exception { User user1 = new User(); user1.setUsername("DreamBoy"); user1.setPassword("123456"); User user2 = new User(); user2.setUsername("DreamBoy223333"); user2.setPassword("223333"); list.add(user1); list.add(user2); return SUCCESS; }
在data.jsp中获取值栈中的数据:
<%--从值栈中获取List集合数据--%><!--第一种方式--><s:property value="list[0].username"/> <s:property value="list[0].password"/><br/><s:property value="list[1].username"/> <s:property value="list[1].password"/><br/><!--第二种方式--><%--使用struts2标签中类似jstl的forEach标签的 iterator 标签,用来遍历值栈中的List集合--%><s:iterator value="list"> <%--遍历List得到List中每个User对象--%> <s:property value="username"/> <s:property value="password"/><br/></s:iterator><br/><!--第三种方式--><s:iterator value="list" var="user"> <%-- 遍历值栈中的List集合对象,得到每个user对象。每次遍历出来的user对象会被放到值栈中的context部分进行存储。 根据context部分数据的特点,需要写OGNL表达式,使用特殊符号# --%> <s:property value="#user.username"/> <s:property value="#user.password"/><br/></s:iterator>
其他操作
(1)调用值栈的set方法向值栈中存数据后从值栈中获取,如:
向值栈中存数据
ActionContext context = ActionContext.getContext();ValueStack valueStack = context.getValueStack();valueStack.set("setKey", "setValue");
从值栈中取数据
<%--调用值栈的set方法向值栈中存数据后从值栈中获取--%><s:property value="setKey"/>
(2)调用值栈的push方法向值栈中存数据后从值栈中获取,如:
向值栈中存数据
ActionContext context = ActionContext.getContext();ValueStack valueStack = context.getValueStack();valueStack.push("pushValue");
从值栈中取数据
<%--调用值栈的push方法向值栈中存数据后从值栈中获取--%><%--**注:向值栈中放入数据后,值栈会放数据存放到一个数组中去,并把数组名称为top,可以数组的名称获取值。**--%><s:property value="[0].top"/>
EL表达式获取值栈数据
这里以上述中提及的从值栈中获取List集合数据为例,使用JSTL标签和EL表达式的方式中值栈中获取数据,如:
<!--使用EL表达式获取--> <c:forEach items="${list}" var="user"> ${user.username} ${user.password}<br/> </c:forEach>
这我就好奇了?EL表达式不是从域对象获取到数据吗?它居然可以从值栈中获取到数据?
需要明确的是,EL表达式确实是从域对象中获取值的,且是通过调用域对象的getAttribute方法获取到值的。那么它为什么能从值栈中获取值呢?
原因是struts底层增强了request对象中的getAttribute方法:从request域对象获取值时,调用了原来的getAttribute方法,如果获取到则直接返回;如果获取不到则从值栈中把值取出来(ValueStack的findValue方法获取值),再返回结果值。
那struts底层在哪里增强request对象的getAttribute方法呢?在struts2的过滤器 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
的 doFilter
方法中开始增强的操作。
- Struts2框架自学之路——值栈
- Struts2框架自学之路——轻松入门
- Struts2框架自学之路——拦截器
- Struts2框架自学之路——结果页面的配置
- Struts2框架自学之路——Action获取表单数据的方式以及表单数据的封装
- Spring框架自学之路——简易入门
- java自学之路-----jdbc_框架
- struts2自学笔记之二
- Java自学之路——开篇
- 自学之——SurfaceView
- struts2 自学笔记(3)之类型转换
- Java自学笔记之struts2入门
- Java自学笔记之struts2 文件上传
- Java自学笔记之struts2异常处理
- 【转】Java自学之路——by马士兵 (java自学之前思想准备)
- 【转】Java自学之路——by马士兵 (java自学之前思想准备)
- Struts2——Struts2框架概述
- Struts2自学入门(四)——简单拦截器
- Linux混杂设备驱动
- 搭建自己的git服务器 gitlib
- spring cloud搭建微服务second-fiberhome(二):结合consul实现服务注册与服务发现
- JSP 自定义标签
- 获取当前的spring容器ApplicationContext 。
- Struts2框架自学之路——值栈
- Presto查询性能测试记录
- mongodb命令行group分组和java代码中group分组
- spark 上python启动脚本
- 熟练键盘的一些快捷键提升开发效率
- layoutSubviews解析
- 欢迎使用CSDN-markdown编辑器
- ffmpeg参数中文详细解释
- windows server 2012 启动目录