一、概念
1.1什么是ActionContext
ActionContext是map结构容器,Action的上下文,存放Action执行过程中的数据信息。存放的数据有:
每次请求都会为当前线程创建一个新的ActionContext,而且ActionContext是基于ThreadLocal存放的,所以ActionContext是线程安全的。
1.2 获取ActionContext
ActionContext方法提供了一个静态方法ActionContext.getContext(),由于ActionContext是线程安全的,并且通过静态方法获取,那么在同一个线程的非Action类中也可以获取并使用即在Service层也能获取到ActionContext中的值,但是:ActionContext是基于请求创建的,所以非请求线程中获取到的ActionContext对象也是空的,不能使用,比如在Filter的init()方法就不能获取到,因为此时ActionContext还没创建赋值。获取ActionContext的方法如下图:
1.3ThreadLocal线程安全演示
存放线程局部变量的一个容器。
package com.david.struts2.hello.test;
public class ThreadLocalTest {
public static void main(String[] args) {
//ThreadLocal存放线程局部变量的容器
//所以存放在ThreadLocal中的局部变量是线程安全的,可以通过查看set方法
//源码,其是获取当前线程,然后与当前线程绑定的
final ThreadLocal<String> tl=new ThreadLocal<String>();
tl.set("David");
new Thread(new Runnable() {
public void run() {
System.out.println("子线程:"+tl.get());
}
}).start();
System.out.println("主线程:"+tl.get());
}
}
输出:
set方法,源码如下:
get方法也是如此,因此可以证明存放在ThreadLocal的数据是线程安全的。
1.4 ActionContext中的6大对象(实际可能会用到)
二、值栈ValueStack和OGNL表达式
2.1概念
值栈是ActionContext里面的一个对象,值栈是栈结构FILO(先进后出)。Struts中值栈中存放的就是Action对象。而值栈就是Ognl表达式取值的根目录,数据直接取,如下验证OGNL表达式取值方式:
package com.david.struts.ognl.test;
import java.util.HashMap;
import java.util.Map;
import com.david.struts2.objectdata.domain.User;
import ognl.Ognl;
import ognl.OgnlException;
public class OgnlTest {
public static void main(String[] args) throws OgnlException {
//原则上,数据分为常用的和不常用的,常用的一般是小部分数据,不常用的一般是大数据。
//表达式:常用数据直接取,不常用的加#号取
Map<String,String> map=new HashMap<String,String>();
map.put("name", "david");
map.put("age", "22");
User u=new User();
u.setName("DAVID");
Object obj1 = Ognl.getValue("name",map,u);
System.out.println("根数据:"+obj1);
Object obj2 = Ognl.getValue("#name",map,u);
System.out.println("非根数据:"+obj2);
}
}
输出:
2.2 Struts2中使用ognl是通过struts2标签来取值的。
注意:要使用struts2的标签必须通过struts2的核心过滤器,如果过滤器配置为*.action的话,访问jsp页面时不经过核心过滤器的,这种jsp页面需要通过action跳转,如果核心过滤器配置为/*,那么jsp页面可以直接访问,但是通过ognl表达式获取的值将为空。因为ValueStack里面仅仅存放的acton对象,所以通过ognl标签获取Action的属性值,可以直接使用标签,而ActionContext中的值需要加"#"来获取,ognl可以实现级联取数据。如下例子(简单登陆演示):
aciton
package com.david.struts.ognl.action;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
public class OgnlAction {
private String name;
private String pwd;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String toLogin(){
public String login(){
ActionContext.getContext().getSession().put("pwd", pwd);
return Action.SUCCESS;
}
}
登陆成功页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!--引入struts标签库-->
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- name为Action的属性,而值栈里面仅仅存放Action对象,而值栈为Ognl表达式的根目录,所以可以直接获取 -->
这个是来之值栈的数据:<s:property value="name"/>
<!--后台将密码存放到session中的,而session存在于ActionContext中对象,所以获取session中的值,需要加#session.-->
这个是来之ActionContext的值:<s:property value="#session.pwd"/>
</body>
</html>
访问结果:
因实际开发中ongl表达式用得不多,后续项目如果使用较多,再来总结ognl表达式的用法。