struts2与OGNL表达式

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([n]语法)

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([n]语法)
	public  void  fun2() throws Exception{
		//参数1: 填写ognl表达式
		//参数2: Map => context 上下文
		//参数3: javaBean / List / Map.....  Root 根
//--------------------------------------------------------		
		List list = new ArrayList();
		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();
		
		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 list = new ArrayList();
		//--------
		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 list = new ArrayList();
		//--------
		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对象放入值栈中。

struts2与OGNL表达式_第1张图片

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

最终 都是以requestScope中的为准

struts2与OGNL表达式_第2张图片

2、ActionContext(struts2数据中心)

struts2与OGNL表达式_第3张图片

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:




	
		
		
			
		
		
		
			/index.jsp
			
			
		
		
		
			/index.jsp
		
		
			/index.jsp
		
	
	


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.       标签介绍


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 {
	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 {
	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:

		
			
				   application/zip
				   is
				   
				   attachment;filename="${fileName}"   
				   10240
			
		
		
在xnl中使用ognl:${filename}:从根中找名为filename的属性
因为根中是struts的值栈,值栈中装了action,所以最终从action中找名为filename的属性
所以在action中提供filename属性,提供get方法


5.       Struts2标签中OGNL表达式()

标签:
两部分:值栈(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:

  
  <%
  		request.setAttribute("name", "requestTom");
  		session.setAttribute("name", "sessionTom");
  		application.setAttribute("name", "applicationTom");
   %>
  	
  		
  		#request.name:
#session.name:
#application.name:
name:
u.name:
#this[1].name:

xml:

				/tag/demo2.jsp
		





你可能感兴趣的:(JavaEE,struts)