struts2与OGNL表达式

来源:互联网 发布:中国中医药数据库 编辑:程序博客网 时间:2024/06/03 09:24

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;}@Overridepublic 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根是javabeanpublic  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<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.2Map中取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);}@Testpublic  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);}@Testpublic  void  fun5() throws Exception{//演示赋值1User u = new User(); Ognl.getValue("name='tom'", new HashMap(), u);  System.out.println(u.getName()); //tom}@Testpublic  void  fun6() throws Exception{//演示赋值2User u = new User(); Ognl.setValue("name", new HashMap(), u,"jerry");  System.out.println(u.getName());  //jerry}@Testpublic  void  fun7() throws Exception{//演示方法调用(方法需要存在于根对象中)User u = new User();Ognl.getValue("setName('jack')", new HashMap(), u); System.out.println(u.getName()); //jack}@Testpublic  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/27System.out.println(echo);  //hiahia~~}@Testpublic  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);}@Testpublic  void  fun10() throws Exception{//演示数学运算符User u = new User();int result= (Integer) Ognl.getValue("1+1", new HashMap(), u); System.out.println(result);}@Testpublic  void  fun11() throws Exception{//演示","连接符User u = new User();String name = (String) Ognl.getValue("name='tom',name", new HashMap(), u); System.out.println(name);  //tom}@Testpublic  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]}@Testpublic  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}}@Testpublic  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]}@Testpublic  void  fun15() throws Exception{//演示 inUser 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); //trueSystem.out.println(c); //false}@Testpublic  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]}@Testpublic  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;}@Overridepublic 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 {@Overridepublic String intercept(ActionInvocation invocation) throws Exception {//1 得到ActionContext数据中心ActionContext ac = ActionContext.getContext();//2 获得 ValueStack(List)ValueStack vs = ac.getValueStack();//3 取出栈中的第一个对象验证是否是ActionObject 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=tomSystem.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=tomSystem.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=tomSystem.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;}@Overridepublic 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=tomSystem.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 获得ServletContextServletContext 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;}}@Overridepublic 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%F73. 在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;}@Overridepublic 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>





1 0
原创粉丝点击