您的位置:首页 > 编程语言 > Java开发

struts2与OGNL表达式

2017-01-17 21:01 351 查看

OGNL表达式

一、什么是OGNl语言

OGNL的全称为ObjectGraphic Navigation Language(对象图导航语言)。它是Struts2的默认表达式语言!

使用OGNL需要导入OGNL的Jar包:ognl-3.0.5.jar

强大的导航语言.一般我们使用ognl表达式取数据.
取数据的位置,需要给ognl准备两个.
context: 上下文=> 需要是一个map
root: 根 => 可以任何java对象=> javaBean,list,map,数组.....
规则: 表达式直接写标示从根下取
 表达式以"#"开头表示从context中取

二、OGNL功能

1、EL一样的JavaBean导航;

2、调用对象方法;

3、调用类的静态方法;

4、索引数组元素;

5、操作集合;

功能演示:

1        取值

1.1       根中取

1.1.1根是javabean

1.1.2根是list(
语法)

1.2       Map中取

2        赋值

2.1       表达式赋值

2.2       SetValue方法赋值

3        调用方法

4        调用静态方法

5        访问静态变量

6        数学运算符

7        “,”号连接

8        创建list

9        创建map

10    In与not in运算符

11    投影(了解)

12    过滤(了解)

Demo:
Address.java:
package cn.itheima.bean;

public class Address {
private String city;
private String street;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}

}


User.java:
package cn.itheima.bean;

public class User {
private String name;
private String password;

private int age ;

private Address address;

public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", address="
+ address + "]";
}

}


DateUtils.java:
package cn.itheima.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {

public static double PI = 3.14159265357;

public static String getTime(){
return new SimpleDateFormat("yyyy/MM/dd").format(new Date());
}

public static String echo(String str){
return str;
}
}


Demo:
package cn.itheima.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ognl.Ognl;

import org.junit.Test;

import cn.itheima.bean.Address;
import cn.itheima.bean.User;

public class Demo {
//1 演示ognl的基本使用
@Test  //1.1.1	根是javabean
public  void  fun1() throws Exception{
//参数1: 填写ognl表达式
//参数2: Map => context 上下文
//参数3: javaBean / List / Map.....  Root 根
//--------------------------------------------------------
User u = new User();
u.setName("tom");

String name =  (String) Ognl.getValue("name", new HashMap(), u);

System.out.println(name);
}

@Test  //1.1.2	根是list(
语法)
public  void  fun2() throws Exception{
//参数1: 填写ognl表达式
//参数2: Map => context 上下文
//参数3: javaBean / List / Map.....  Root 根
//--------------------------------------------------------
List<User> list = new ArrayList<User>();
User u1 = new User();
u1.setName("tom");
list.add(u1);
//---------
User u2 = new User();
u2.setName("jerry");
list.add(u2);

//ognl表达式 默认从根下取数据

String name =  (String) Ognl.getValue("[0].name", new HashMap(), list);

System.out.println(name);
}

@Test   //1.2	Map中取
public  void  fun3() throws Exception{
Map< String, Object> context = new HashMap<String, Object>();

context.put("name", "tom");

//-------------------------------
User u2 = new User();
u2.setName("jerry");

String name = (String) Ognl.getValue("name", context, u2);//从根中取
//		String name = (String) Ognl.getValue("#name", context, u2);//从context中取
System.out.println(name);
}
@Test
public  void  fun4() throws Exception{
User u = new User();
u.setName("jerry");

Address a = new Address();
a.setCity("北京");

u.setAddress(a);

String city = (String) Ognl.getValue("address.city", new HashMap(), u);

System.out.println(city);
}

@Test
public  void  fun5() throws Exception{
//演示赋值1
User u = new User();

Ognl.getValue("name='tom'", new HashMap(), u);

System.out.println(u.getName()); //tom
}

@Test
public  void  fun6() throws Exception{
//演示赋值2
User u = new User();

Ognl.setValue("name", new HashMap(), u,"jerry");

System.out.println(u.getName());  //jerry
}

@Test
public  void  fun7() throws Exception{
//演示方法调用(方法需要存在于根对象中)
User u = new User();

Ognl.getValue("setName('jack')", new HashMap(), u);

System.out.println(u.getName()); //jack

}
@Test
public  void  fun8() throws Exception{
//演示静态方法调用(不受方法必须在根中的限制)
User u = new User();

String time = (String) Ognl.getValue("@cn.itheima.utils.DateUtils@getTime()", new HashMap(), u);
//使用@引用静态方法和静态变量
String echo = (String) Ognl.getValue("@cn.itheima.utils.DateUtils@echo('hiahia~~')", new HashMap(), u);

System.out.println(time);  //2015/06/27

System.out.println(echo);  //hiahia~~

}

@Test
public  void  fun9() throws Exception{
//演示静态方法调用(不受方法必须在根中的限制)
User u = new User();

double Pi= (Double) Ognl.getValue("@cn.itheima.utils.DateUtils@PI", new HashMap(), u);

System.out.println(Pi);

}

@Test
public  void  fun10() throws Exception{
//演示数学运算符
User u = new User();

int result= (Integer) Ognl.getValue("1+1", new HashMap(), u);

System.out.println(result);

}

@Test
public  void  fun11() throws Exception{
//演示","连接符
User u = new User();

String name = (String) Ognl.getValue("name='tom',name", new HashMap(), u);

System.out.println(name);  //tom

}

@Test
public  void  fun12() throws Exception{
//演示 创建对象 (list)
User u = new User();

List list = (List) Ognl.getValue("{'tom','jerry','jack','rose'}", new HashMap(), u);

System.out.println(list);   //[tom,jerry,jack,rose]

}

@Test
public  void  fun13() throws Exception{
//演示 创建对象 (map)
User u = new User();

Map map =(Map) Ognl.getValue("#{'name':'tom','age':'18'}", new HashMap(), u);

System.out.println(map); //{name=tom,age=18}

}

@Test
public  void  fun14() throws Exception{
//演示 创建对象 (user)
User u = new User();

User u2 =  (User) Ognl.getValue("new cn.itheima.bean.User()", new HashMap(), u);

System.out.println(u2); //User [name=null,password=null,address=null]

}

@Test
public  void  fun15() throws Exception{
//演示 in
User u = new User();

boolean b = (Boolean) Ognl.getValue("'tom' in {'tom','jerry','jack','rose'}", new HashMap(), u);
//判断tom是否在后面的集合中
boolean c = (Boolean) Ognl.getValue("'tom' not in {'tom','jerry','jack','rose'}", new HashMap(), u);

System.out.println(b); //true

System.out.println(c); //false

}

@Test
public  void  fun16() throws Exception{
//集合的投影(了解)
List<User> list = new ArrayList<User>();
//--------
User u1 = new User();
u1.setName("tom");
list.add(u1);
//---------
User u2 = new User();
u2.setName("jerry");
list.add(u2);

System.out.println(Ognl.getValue("#this.{name}", new HashMap(),list));//[tom,jerry]

}

@Test
public  void  fun17() throws Exception{
//集合的选择(过滤)
//集合的投影(了解)
List<User> list = new ArrayList<User>();
//--------
User u1 = new User();
u1.setName("tom");
u1.setAge(10);
list.add(u1);
//---------
User u2 = new User();
u2.setName("jerry");
u2.setAge(20);
list.add(u2);

System.out.println(Ognl.getValue("#this.{?age > 18}", new HashMap(),list));
//[User [name=jerry,password=null,address=null]]
}

}


三、OGNL与struts2的结合

描述: struts2为OGNL表达式准备了两个对象

ActionContext:

作为ognl表达式的Context

valueStack: 

作为ognl表达式的Root

作用范围:值栈为request作用域中的一个属性,作用范围跟request一样,有多少个请求就有多少个值栈

以上两个对象的创建

都是strutsPrepareAndExecuteFilter中准备好.

ognl表达式:Ognl.getValue(ognl表达式,context,根);

1、值栈(作为ognl表达式的根)

就是struts中搞的一个list模拟的栈结构,而值栈作为OGNL表达式的root,并且会把action对象放入值栈中。



requestScope、sessionscope、applicationScope三个域的数据都放入了attribute中,如果有重名的键 则会被覆盖:

最终 都是以requestScope中的为准



2、ActionContext(struts2数据中心)



Demo:
action:
package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class Demo1Action extends ActionSupport {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String execute(){

System.out.println("action中的name属性值:"+name);

//获得值栈
ValueStack  vs =ActionContext.getContext().getValueStack();
//获得栈顶的User对象
User u
=(User) vs.getRoot().peek();
//打印user对象的name属性
System.out.println("现在在栈顶的User对象的Name属性:"+u.getName());

return "success";
}
}


User:
package cn.itheima.c_vs;

public class User {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "User [name=" + name + "]";
}

}


struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
<package name="vs" namespace="/vs" extends="struts-default"  >

<interceptors>
<interceptor name="vs" class="cn.itheima.c_vs.VSInterceptor"></interceptor>
</interceptors>

<action name="Demo1Action" class="cn.itheima.c_vs.Demo1Action"  >
<result name="success" type="dispatcher" >/index.jsp</result>
<interceptor-ref name="vs"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>

<action name="Demo2Action" class="cn.itheima.c_vs.Demo2Action"  >
<result name="success" type="dispatcher" >/index.jsp</result>
</action>
<action name="Demo3Action" class="cn.itheima.c_vs.Demo3Action"  >
<result name="success" type="dispatcher" >/index.jsp</result>
</action>
</package>

</struts>


VSInterceptor:
package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.ValueStack;

public class VSInterceptor extends AbstractInterceptor {

@Override
public String intercept(ActionInvocation invocation) throws Exception {
//1 得到ActionContext数据中心
ActionContext ac = ActionContext.getContext();
//2 获得 ValueStack(List)
ValueStack vs = ac.getValueStack();
//3 取出栈中的第一个对象验证是否是Action
Object obj = vs.getRoot().peek();

System.out.println("栈顶的对象是:"+obj);//应该是我们写Demo1Action
//4 创建一个User对象 压入栈中
User u = new User();

vs.getRoot().push(u);//哈哈,现在User对象替代Action在栈顶了!!
//放行
return invocation.invoke() ;
}

}


Demo2Action:
package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class Demo2Action extends ActionSupport {
private User user;

public String execute(){

// http://liuyd:8080/struts2-demo3/vs/Demo2Action.do?user.name=tom System.out.println(user);
return "success";
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

}


结合演示:

1.       <s:debug>标签介绍

package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;

public class Demo3Action extends ActionSupport implements ModelDriven<User> {
private User user = new User();

public String execute(){
// http://liuyd:8080/struts2-demo3/vs/Demo2Action.do?name=tom System.out.println(user);
return "success";
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

//---------------------------------------------------
public User getModel() {
return user;
}

}


2.       将表单的参数赋值到对象中(表达式方式)

超链提交参数:?user.name=tom  把参数直接赋值到了user对象中

user.name键作为ognl表达式访问root中的属性

action:

package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class Demo2Action extends ActionSupport {
private User user;

public String execute(){

// http://liuyd:8080/struts2-demo3/vs/Demo2Action.do?user.name=tom System.out.println(user);
return "success";
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

}


user:

package cn.itheima.c_vs;

public class User {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "User [name=" + name + "]";
}

}
控制台打印:User [name=tom]

3.       将表单的参数赋值到对象中(ModelDriver方式)

表单提交,其中提交的键可以看作是ognl表达式

Action中有User对象,我们想直接将表单参数提交到User对象中封装,做法:

         1>提交的参数的键=> user.name  就会在值栈中查找名为user的对象,并赋值到该对象的name属性

         2>使用ModelDriven,我们的Action在getModel方法中将User对象返回.ModelDriven拦截器会将我们返回的User对象放入值栈中(栈顶),那么 在表单中直接提交name,将会把name值装入栈顶的user对象的name属性

访问的方式使用:?name=tom  正常是从栈顶的action中找 找不到

思路:把user对象放到栈顶,这样name=tom就可以直接给user对象赋值了

步骤:实现ModelDriven接口,实现getModel方法,在该方法中返回一个对象,该对象就是想要赋值到的那个对象(user)

action:

package cn.itheima.c_vs;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;

public class Demo3Action extends ActionSupport implements ModelDriven<User> {
private User user = new User();

public String execute(){
// http://liuyd:8080/struts2-demo3/vs/Demo2Action.do?name=tom System.out.println(user);
return "success";
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

//---------------------------------------------------
public User getModel() {
return user;
}

}
底层是用modelDriven拦截器实现的,该拦截器位于在params拦截器之前

modelDriven拦截器会把返回的那个对象压入栈顶,这样赋值的时候就是给user对象赋值了



4.       文件下载中文件名乱码问题解决(配置文件中使用OGNL)

action:
package cn.itheima.b_ognl;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletContext;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class Demo1Action extends ActionSupport {

private InputStream is ;

public InputStream getIs() {
//1 获得ServletContext
ServletContext sc = ServletActionContext.getServletContext();
//2 获得apache-tomcat-6.0.35.zip的流
is = sc.getResourceAsStream("/WEB-INF/apache-tomcat-6.0.35.zip");
//3 返回
return is;
}

public String getFileName() {

try {
return URLEncoder.encode("汤姆凯特6.zip","UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}

@Override
public String execute() throws Exception {

return SUCCESS;
}

}


struts.xml:

<package name="ognl" namespace="/ognl" extends="struts-default" >
<action name="Demo1Action" class="cn.itheima.b_ognl.Demo1Action">
<result name="success" type="stream" >
<param name="contentType">application/zip</param>
<param name="inputName">is</param>
<!--
1.相应头中只能使用latin(Iso-8859-1)码表
2.使用URLEncode编码,对中文进行编码才能发送  => %E6%F7
3. 在struts.xml配置文件中可以使用ognl表达式=> ${} 在扩种书写ognl(注意:虽然跟el表达式格式看似相同,但是就是ognl不是el.)

-->
<param name="contentDisposition">attachment;filename="${fileName}"</param>   <!-- 从action中去找名为fileName的属性 -->
<param name="bufferSize">10240</param>
</result>
</action>
在xnl中使用ognl:${filename}:从根中找名为filename的属性
因为根中是struts的值栈,值栈中装了action,所以最终从action中找名为filename的属性
所以在action中提供filename属性,提供get方法



5.       Struts2标签中OGNL表达式(<s:properties>)

<s:debug>标签:

两部分:值栈(Value Stack Contents)和数据中心(Stack Context)
在jsp中使用标签,要导库:<%@ taglib prefix="s" uri="/struts-tags" %>

user:
package cn.itheima.b_ognl;

public class User {
private String name;
private String password;

public User() {
}

public User(String name, String password) {
super();
this.name = name;
this.password = password;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}


action:
package cn.itheima.b_ognl;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletContext;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class Demo2Action extends ActionSupport {

private String name = "ActionTom";

private User u = new User("beanTom","1234");

public User getU() {
return u;
}

public void setU(User u) {
this.u = u;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String execute() throws Exception {
//将User对象压入值栈中, 栈顶是User对象
ActionContext.getContext().getValueStack().push(u);

return SUCCESS;
}

}


jsp:
<body>

<%
request.setAttribute("name", "requestTom");
session.setAttribute("name", "sessionTom");
application.setAttribute("name", "applicationTom");
%>
<!-- <s:property/> 标签中使用ognl表达式 -->
<!-- 使用ognl表达式分别取得request session application 中的属性
ActionContext.getContext().get("request").get("name")
-->
#request.name:<s:property value="#request.name" /><br>
#session.name:<s:property value="#session.name" /><br>
#application.name:<s:property value="#application.name" /><br>
name:<s:property value="name" />
<hr>
<!-- 访问Action中user对象的name属性 -->
u.name:<s:property value="u.name" />
<hr>
<!-- 栈顶是User对象,Action在User对象下面 -->
#this[1].name:<s:property value="#this[1].name" />  <!--从值栈中取出脚标为1的对象-->
<s:debug></s:debug>
</body>


xml:
<action name="Demo2Action" class="cn.itheima.c_tag.Demo2Action">
<result name="success"  >/tag/demo2.jsp</result>
</action>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: