OGNL
OGNL的概述
OGNL中文名对象图导航语言,是一个比EL表达式更加强大很多倍的语言
EL表达式与OGNL的比较
EL:从域对象中获取数据,从EL的11个对象中获取数据
OGNL:可以调用对象的方法,可以获取Struts2的值栈数据
OGNL的java环境入门
OGNL调用对象的方法
- 获得context对象
- 获得根对象
- 执行对象的方法
public void demo1() throws OgnlException {
//获得context
OgnlContext context = new OgnlContext();
//获得根对象
Object root = context.getRoot();
//执行表达式
Object value = Ognl.getValue("'helloword'.length()", context, root);
System.out.println(value);
}
OGNL访问对象的静态资源
访问静态资源的表达式:
@类名@调用的方法
public void demo2() throws OgnlException {
//获得context
OgnlContext context = new OgnlContext();
//获得根对象
Object root = context.getRoot();
//执行表达式:@类名@方法名
Object value = Ognl.getValue("@java.lang.Math@random()", context, root);
System.out.println(value);
}
将数据存入root访问
- 创建一个实体类,生成get和set方法,以及有参无参
- 获得context对象
- 将数据存入root
- 获取根对象root
- 获取值
public void demo3() throws OgnlException {
//获得context
OgnlContext context = new OgnlContext();
//执行表达式
context.setRoot(new User("aaa","21231"));
//获得根对象
Object root = context.getRoot();
Object username = Ognl.getValue("username", context, root);
Object password = Ognl.getValue("password", context, root);
System.out.println(username+"..."+password);
}
将数据存入context访问
- 获得context对象
- 获得根对象root
- 向context中存入数据
- 执行表达式,注意执行表达式时,键需要加上#
public void demo4() throws OgnlException {
//获得context
OgnlContext context = new OgnlContext();
//获得根对象
Object root = context.getRoot();
context.put("name","张三");
Object value = Ognl.getValue("#name", context, root);
System.out.println(value);
}
OGNL的Struts2环境入门
导包
<%@ taglib prefix="s" uri="/struts-tags" %>
OGNL调用对象的方法
<s:property value="'hello world'.length()"></s:property>
OGNL访问对象的静态资源
-
配置struts.xml,修改常量struts.ognl.allowStaticMethodAccess的值,因为struts2默认是关闭静态资源访问的功能的
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
-
访问静态资源
<s:property value="@java.lang.Math@random()"></s:property>
注意: 有的时候在struts.xml里配置常量的时候没有效果,我们也可以在web.xml里面配置常量的值
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.ognl.allowStaticMethodAccess</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
值站(ValueStack)
值站的概述
- 值站其实类似于一个容器(Struts2的框架当中的数据都会保存在ValueStack中,在任何地方都可以取,可以在页面上取,可以在action中取,可以在配置文件中取,而request只能在页面中取)
- ValueStack是一个接口,OgnlValueStack是它的实现类
- ValueStack贯穿了整个action的生命周期(意思是有一个Action实例,就会有一个ValueStack对象)
值站的内部结构
- ValueStack中有两个主要的区域
- root区域:其实就是一个ArrayList,里面一般放置一些对象。获取root的数据是不需要加#
- context区域:其实就是一个Map,里面放置的是web开发常用的对象数据的引用,获取context数据需要加#
- request
- session
- application
- parameters
- attr
- 操作值栈,通常指的是操作ValueStack中的root区域。
查看值栈的结构:
<%@taglib prefix="s" uri="/struts-tags" %>
<s:debug></s:debug>
值栈的操作
保存数据到值栈中的root以及获取root值栈的数据
方式一:
- 创建一个全局变量,并生成get方法
- 给全局变量赋值
- 前端获取数据
代码实现:
前端:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<s:debug></s:debug>
<s:property value="user.username"></s:property>
<s:property value="user.password"></s:property>
</body>
</html>
后端:
public class ValueStackDemo1 extends ActionSupport {
public User getUser() {
return user;
}
private User user;
@Override
public String execute() throws Exception {
user = new User("张三","2222");
return SUCCESS;
}
}
结果展示:
点击Debug:
方式二:
- 获取valueStack对象
- 创建对象给对象赋值
- 将值压入值栈中
代码实现:
前端获取数据
<s:debug></s:debug>
<s:property value="username"></s:property>
<s:property value="password"></s:property>
<s:property value="name"></s:property>
后端:
User user = new User("张三","2222");
ValueStack valueStack = ActionContext.getContext().getValueStack();
valueStack.push(user);
//set一般用来传集合
valueStack.set("name","李四");
保存数据到值栈中的context以及获取context值栈的数据
后端存储数据:
ServletActionContext.getRequest().setAttribute("name","张三");
ServletActionContext.getRequest().getSession().setAttribute("name","李四");
ServletActionContext.getServletContext().setAttribute("name","王五");
前端获取数据(EL表达式可以获取到request对象的值):
<s:property value="#request.name"></s:property>
<s:property value="#session.name"></s:property>
<s:property value="#application.name"></s:property>
${name}
OGNL中的特殊字符
#号
-
获取context的数据
-
构建map集合
例如:
使用s:iterator 标签遍历list集合{‘aa’,‘bb’,‘cc’},结果表示使用i和#i都可以取到值<s:iterator value="{'aa','bb','cc'}" var="i"> <s:property value="i"></s:property> -- <s:property value="#i"></s:property> <br /> </s:iterator>
使用s:iterator 标签遍历map集合#{‘aa’:‘11’,‘bb’:‘22’,‘cc’:‘33’},结果表示使用key–value和#i.key–i.value都可以取到值<s:iterator value="#{'aa':'11','bb':'22','cc':'33'}" var="i"> <s:property value="key"></s:property> -- <s:property value="value"></s:property> <br /> <s:property value="#i.key"></s:property> -- <s:property value="#i.value"></s:property> <br /> </s:iterator>
demo
比较下面两个代码的区别:
<s:radio list="{'男','女'}" name="sex" label="性别" /> <br />
<s:radio list="#{'1':'男','2':'女'}" name="sex2" label="性别" /> <br>
%号
-
强制解析成OGNL,在有些标签中是不识别OGNL的,需要使用%强制解析
demo:<% request.setAttribute("name","张三"); %> 姓名:<s:textfield name="text" value="%{#request.name}"></s:textfield>
-
强制不解析OGNL表达式,在有些标签遇到OGNL表达式会自动解析,使用%可以让其不解析
<s:property value="%{'#request.name'}"></s:property>
$号
-
在配置文件中使用OGNL
-
属性文件:
demo
user.welcome=欢迎,${#session.user.username}
-
xml文件
demo
配置文件下载<action name="download" class="xxx.DownloadAction"> <result type="stream"> <param name="Content-Type">文件类型</param> <param name="Content-Disposition">attachment;filename=${文件名}</param> </result> </action>