struts2(二)值栈 threadlocal ogal ui
值栈(重要)和ognl表达式
1、 只要是一个mvc框架,必须解决数据的存和取的问题
2、 Struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构
3、 把数据存在值栈中,在页面上利用ognl表达式显示出来
讨论的问题
1、 讨论值栈的生命周期
2、 值栈的内存结构
3、 通过什么样的方法把数据放入到值栈中
4、 显示出来
值栈的内存结构
获取值栈的路径
说明:
1、 值是一样的,说明只有一个对象
2、 因为有一种是从request域中获取的,所以是一次请求
内存结构
1、 大致图:
2、 上面图中的context的放大
说明:
_root:(CompoundRoot)
_values:(HashMap)
在这里存放了request,response,session,application等servlet容器的内容
3、_root的放大
说明:
和ValueStack中的root是一致的
值栈的内存总图
说明:
从上图中可以看出valueStack总共分为两个部分:
对象栈:root
Map栈:_values
对象栈的存放
1、 Push方法
2、 add方法
对象栈的提取
从上图中可以看出,peek方法为获取对象栈的栈顶的元素
对象栈的元素的弹出*(栈顶的数据弹出)
作对象栈中的对象
说明:
可以利用valueStack.setParameter方法改变对象栈中对象的属性的值
Map栈的存放
通过该方法可以把一个字符串放入到map栈中的request域中
通过该方法可以把一个字符串放入到map栈中的application域中
通过该方法可以把一个字符串放入到map栈中
package com.itheima09.struts2.action; import ognl.OgnlContext; import org.apache.struts2.ServletActionContext; import com.itheima09.bean.Person; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.CompoundRoot; import com.opensymphony.xwork2.util.ValueStack; public class ValueStackAction extends ActionSupport{ /** * 获取值栈 */ public String testGetValueStack(){ ValueStack valueStack = ActionContext.getContext().getValueStack(); ValueStack valueStack2 = ServletActionContext.getValueStack(ServletActionContext.getRequest()); ValueStack valueStack3 = (ValueStack)ServletActionContext.getRequest().getAttribute("struts.valueStack"); System.out.println(valueStack); System.out.println(valueStack2); System.out.println(valueStack3); return SUCCESS; } /** * 把一个对象放入到对象栈中 * @return */ public String testPutObjToObjectStack_1(){ /** * 把一个对象放入到对象栈的栈顶 */ ActionContext.getContext().getValueStack().push("aaaa"); return SUCCESS; } public String testPutObjToObjectStack_2(){ /** * 把一个对象放入到对象栈的栈顶 */ ActionContext.getContext().getValueStack().getRoot().add(0,"aaa"); return SUCCESS; } public String testPutObjToObjectStack_3(){ /** * 把一个对象放入到对象栈的最底部 */ ActionContext.getContext().getValueStack().getRoot().add("aaa"); return SUCCESS; } /** * 从对象栈的栈顶提取元素 * @return */ public String testGetObjFromObjectStack_1(){ ActionContext.getContext().getValueStack().peek(); return SUCCESS; } public String testGetObjFromObjectStack_2(){ ActionContext.getContext().getValueStack().getRoot().get(0); return SUCCESS; } /** * 从栈顶把对象弹出对象栈 */ public String testPopObj_1(){ ActionContext.getContext().getValueStack().pop(); return SUCCESS; } /** * 从对象栈中清除一个元素 * @return */ public String testPopObj_2(){ ActionContext.getContext().getValueStack().getRoot().remove(0); return SUCCESS; } /** * 把一个对象放入到对象栈中 * @return */ public String testPutObjectToObjectStack(){ Person person = new Person(); person.setPid(1L); person.setName("王二麻子"); //把person放入到了对象栈的栈顶 ActionContext.getContext().getValueStack().push(person); ValueStack valueStack = ActionContext.getContext().getValueStack(); //通过setParameter方法把对象栈的属性赋值 valueStack.setParameter("name", "aaaaa"); //从对象栈中把栈顶的对象提取出来 person = (Person)ActionContext.getContext().getValueStack().peek(); System.out.println(person.getName()); return SUCCESS; } /** * 把一个字符串放入到request域中 */ public String testPutStrToRequest(){ ServletActionContext.getRequest().setAttribute("request_aaa", "request_aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } /** * 把一个字符串放入到application域中 */ public String testPutStrToApplication(){ ServletActionContext.getServletContext().setAttribute("application_aaa", "application_aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } /** * 把一个字符串放入到map栈中 */ public String testPutStrToMap(){ ActionContext.getContext().put("aaa", "aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } }
Threadlocal
1、 本地线程类
2、 可以存放一个对象
3、 Threadlocal对象只能当前线程访问,其他的线程是不能访问的()
4、 传递参数 主要作用
参数的传递
说明:通过参数的传递,一个字符串很容易的从客户端传递到tl1中的tl1方法,再传递到tl2中的tl2方法
说明:
在TL1Super中用到一个字符串
在TL2Super中用到同样的字符串,但是这两个类是完全松耦合,这个时候要用
Threadlocal传递数据,因为不管是否是送耦合的,但是可以肯定在同一个线程中。所以可以得到同一个线程threadlocal对象中的数据
Ognl表达式
Debug标签(重要)
在页面上引入标签库
可以通过网页的形式把valueStack中值提取出来
关于对象栈:
从上图可以看出来,对象栈的属性来自于对象栈中的每一个对象的属性的get方法
把一个对象放入到对象栈中
上述的两个类中都同时有name属性,而且当前请求的action在对象栈中
package com.itheima09.struts2.action; import ognl.OgnlContext; import org.apache.struts2.ServletActionContext; import com.itheima09.bean.Person; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.CompoundRoot; import com.opensymphony.xwork2.util.ValueStack; public class ValueStackAction extends ActionSupport{ /** * 获取值栈 */ public String testGetValueStack(){ ValueStack valueStack = ActionContext.getContext().getValueStack(); ValueStack valueStack2 = ServletActionContext.getValueStack(ServletActionContext.getRequest()); ValueStack valueStack3 = (ValueStack)ServletActionContext.getRequest().getAttribute("struts.valueStack"); System.out.println(valueStack); System.out.println(valueStack2); System.out.println(valueStack3); return SUCCESS; } /** * 把一个对象放入到对象栈中 * @return */ public String testPutObjToObjectStack_1(){ /** * 把一个对象放入到对象栈的栈顶 */ ActionContext.getContext().getValueStack().push("aaaa"); return SUCCESS; } public String testPutObjToObjectStack_2(){ /** * 把一个对象放入到对象栈的栈顶 */ ActionContext.getContext().getValueStack().getRoot().add(0,"aaa"); return SUCCESS; } public String testPutObjToObjectStack_3(){ /** * 把一个对象放入到对象栈的最底部 */ ActionContext.getContext().getValueStack().getRoot().add("aaa"); return SUCCESS; } /** * 从对象栈的栈顶提取元素 * @return */ public String testGetObjFromObjectStack_1(){ ActionContext.getContext().getValueStack().peek(); return SUCCESS; } public String testGetObjFromObjectStack_2(){ ActionContext.getContext().getValueStack().getRoot().get(0); return SUCCESS; } /** * 从栈顶把对象弹出对象栈 */ public String testPopObj_1(){ ActionContext.getContext().getValueStack().pop(); return SUCCESS; } /** * 从对象栈中清除一个元素 * @return */ public String testPopObj_2(){ ActionContext.getContext().getValueStack().getRoot().remove(0); return SUCCESS; } /** * 把一个对象放入到对象栈中 * @return */ public String testPutObjectToObjectStack(){ Person person = new Person(); person.setPid(1L); person.setName("王二麻子"); //把person放入到了对象栈的栈顶 ActionContext.getContext().getValueStack().push(person); ValueStack valueStack = ActionContext.getContext().getValueStack(); //通过setParameter方法把对象栈的属性赋值 valueStack.setParameter("name", "aaaaa"); //从对象栈中把栈顶的对象提取出来 person = (Person)ActionContext.getContext().getValueStack().peek(); System.out.println(person.getName()); return SUCCESS; } /** * 把一个字符串放入到request域中 */ public String testPutStrToRequest(){ ServletActionContext.getRequest().setAttribute("request_aaa", "request_aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } /** * 把一个字符串放入到application域中 */ public String testPutStrToApplication(){ ServletActionContext.getServletContext().setAttribute("application_aaa", "application_aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } /** * 把一个字符串放入到map栈中 */ public String testPutStrToMap(){ ActionContext.getContext().put("aaa", "aaa"); ValueStack valueStack = ActionContext.getContext().getValueStack(); return SUCCESS; } }
Property标签(重要)
介绍
输出标签
value 指定要输出的内容
如果在对象栈中,直接指定属性
也可以直接调用方法
如果在map栈中,用#指定
如果value属性不写,则默认输出栈顶的元素
把一个对象放入到对象栈中,可以利用s:prototype标签的value属性直接访问
该对象的属性。如果对象栈中出现两个相同的属性,则prototype标签的value属性会
从栈顶往下查找,直到找到为止。赋值的为第一个。
把一个对象放入到map中,再把map放入到对象栈中,在页面上可以利用
可以利用方法来访问利用该标签访问map栈中的元素
terator标签(重要)
1、 用途:主要用于迭代,可以迭代List,Set,Map,Array
2、 案例
1、 把集合放入到对象栈中
2、把list放入到map中
即使在map中,当前在迭代的对象会放在栈顶
3、 把list放入到request域中
总结:
1、 如果要迭代一个集合,当前迭代的元素在栈顶
2、 如果要迭代一个map,则当前迭代的元素是entry
3、 Iterator标签中有一个属性status
Ui标签
1、 struts2提供了一套标签机制,由struts2框架把struts2的标签解析成html标签。
2、 在struts2的配置文件中,增加
在struts2的配置文件中加入如下的内容
<constant name="struts.ui.theme" value="simple"></constant>
由struts2容器翻译过程来的html代码和struts2标签的代码就能保持一致。
<constant name="struts.devMode" value="true"></constant> xml配置文件改动后 立即生效 开发用
Select标签
1.静态资源
<td><s:select list="{'山西省','河南省','四川省'}" value="{'山西省'}"></s:select></td> <td><s:select list="#{1:'山西省',2:'河南省',3:'四川省'}" value="#{2:'河南省'}"></s:select></td>
2.动态资源, 从map栈中取
<td><s:select list="#provinces" listKey="pid" listValue="name"/></td>
<!--
listKey 为option元素的value属性的值
listValue option元素的文本内容
name
该属性的值用来获取选中的元素
用于回显
-->
checkbox
回显: 在jsp中显示栈值中的数据(ogal表达式)
如果要回显的内容在map栈中,不能根据name属性进行回显,必须用value属性进行回显<td><s:textfield name="username" value="%{#user.username}"></s:textfield></td>
如果把要回显的对象放入到对象栈中,则页面上可以根据name进行回显<s:textfield name="username"></s:textfield>
一般情况下,如果要回显一个对象,则把该对象放入到对象栈中
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <s:form action=""> <table> <tr> <td>用户名</td> <!-- s:select s:checkboxlist 这些标签中的list属性的值可以直接跟ognl表达式 一般情况下,表单中的元素的value属性都不能直接跟ognl表达式 可以使用%{ognl表达式} 如果要回显的内容在map栈中,不能根据name属性进行回显,必须用value属性进行回显 <td><s:textfield name="username" value="%{#user.username}"></s:textfield></td> 如果把要回显的对象放入到对象栈中,则页面上可以根据name进行回显 <s:textfield name="username"></s:textfield> 一般情况下,如果要回显一个对象,则把该对象放入到对象栈中 --> <td><s:textfield name="username"></s:textfield></td> </tr> <tr> <td>爱好</td> <!-- 用name进行回显 --> <td><s:checkboxlist list="#hobbies" listKey="hid" listValue="name" name="hids"/></td> </tr> </table> </s:form> </body> </html>
1、 如果把要回显的数据放入到map栈中,则必须根据value进行回显
Value=”%{ognl表达式}”
2、 一般情况下,应该把回显的数据放入到对象栈中,因为页面上可以直接根据name进行回显
3、 因为当前请求的action在对象栈中,所以可以利用action中的属性进行回显,action中的属性必须有get方法。
4、 Checkbox的回显