struts2默认ognl,值栈
来源:互联网 发布:d810调焦软件 编辑:程序博客网 时间:2024/05/22 15:49
1.OGNL概述
1.1 什么是OGNL?
OGNL(object graph Navigation language) 对象图形导航语言,它是一款简单便捷的语言,通过它的表达式,可以轻松的存取对象的属性和调用对象的方法,遍历整个对象的结构图(说白了就是可以用’对象.属性’获取值)
1.2 它是struts2开发的吗?
OGNL是一个开源项目,并不是struts2开发的,struts2只是使用OGNL作为默认的表达式语言而已.
1.3 OGNL 有什么作用?
- OGNL可以获取对象的成员(支持对象方法的调用,支持对象对象属性访问,支持静态方法的调用,支持集合对象操作)
- 进行运算
2.OGNL三要素
- 基本语法
我们通常通过对象.属性名就可以拿到对应的值 - 根元素(Root)
OGNL表述的是对象导航语言,那么必须指明根元素 - 上下文(Context)
上下文跟Root存放在一个map里面,Map里面存放了很多的User对象, 那么我们必须指明是在哪一个根上面找这些user对象。
我们通过一个例子来讲述三者之间的区别,
Eg:
就好比如一个果农在果园摘苹果
果园里有很多的树,除了果农在摘苹果的那颗树,其它都是都是上下文(Context),而果农摘的那棵树就相当于根元素(Root),而决定果农摘什么样的苹果(大的,小的,还是熟的) 就是Ognl的语法
3.OGNL入门
3.1表达式与根对象
- 访问根对象属性
准备工作,创建一个JavaBean
既然提到了JavaBean,那么我们来讲讲什么是JavaBean?
javaBean 不是大公司定的规范,也不是一种功能,而是程序员之间的一种规则,只要按照这种规则就,就能实现某种功能等,
JavaBean 编写规则
- 提供空参构造方法
- 提供set/get 方法
- 实现序列化接口
那么大家知道什么是属性么?属性是成员变量吗?
答案 如果使用工具生成set/get方法,就可以理解成属性.如果不是,那么属性就是set,get方法去掉 set , get 并且开头字母小写,那么这个字符串就是属性.好了回归正题,来看我们的代码
public class User { private String name; private int age; //提供set/get 方法 属性 去掉get 开头小写 name public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public User(String name, int age) { super(); this.name = name; this.age = age; } public User() { }}
然后创建一个测试类
public class demo1 { @Test public void fun_01(){ try { User user = new User("zs",18); //使用ognl User root = user; //根元素 String expression = "name"; //ognl 表达式 Object value = Ognl.getValue(expression,root); System.out.println(value); } catch (OgnlException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
输出结果如下
zs
3.2 访问根对象中的方法
@Test public void fun_02(){ try { User user = new User("zs",18); //使用ognl User root = user; //根元素 String expression = "getName()"; //ognl 表达式 Object value = Ognl.getValue(expression,root); System.out.println(value); } catch (OgnlException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出结果 zs
只要表达式跟方法名一致就能调用,不要少了括号
3.调用静态方法
静态方法相信大家都有用过吧,比如Runtime,嘿嘿嘿你懂的
我们就随便使用一个Math来演示好了
@Test public void fun_03(){ try { //调用静态方法不需要根元素,直接传null就行 //调用静态方法 规则 需要 @号开头,接上静态方法的全局类路径 列如(cn.itcast.demo2.demo2) 然后再接一个@最后接上需要调用的方法 String expression = "@java.lang.Math@random()"; //ognl 表达式 Math 的类路径 Object value = Ognl.getValue(expression,null); System.out.println(value); } catch (OgnlException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出结果 0.5854924290246956
模拟上下文访问根对象属性
@Test public void fun_04(){ try { //创建一个map Context 实际上就是一个map Map<String,User> context = new HashMap<String,User>(); User user = new User("zs",18); //根元素 User user1 = new User("ls",19); context.put("user", user); context.put("user1", user1); String expression = "name"; //ognl 表达式 取根元素的值 Object value=Ognl.getValue(expression,context, user); System.out.println(value); } catch (OgnlException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出结果 zs
那么问题来了,我们要怎么获取非根元素的值呢?
使用”#对象.属性”的方法就可以获取
@Test public void fun_05(){ try { //创建一个map Context 实际上就是一个map Map<String,User> context = new HashMap<String,User>(); User user = new User("zs",18); //根元素 User user1 = new User("ls",19); context.put("user", user); context.put("user1", user1); String expression = "#user1.name"; //ognl 表达式 取非根元素的值 user1 Object value=Ognl.getValue(expression,context, user); System.out.println(value); } catch (OgnlException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
这就是OGNL的基本使用,
ValueStack值栈
下面我们来讲讲Struts2中的值栈,ValueStack 翻译过来就是值栈的意思,经常使用servlet的人会知道,我们通过传递给页面数据时通常会使用作用域. 既然讲到了作用域,那我就再来再插一嘴把 ….
请求转发,重定向介绍
大家知道什么样的情况下使用请求转发,什么使用重定向么?
我在网上翻了很多帖子,很多人都是这样认为的.
只要有数据传递,那么就是用请求转发,没有数据就使用重定向
如果你是这样,那么我告诉你,你错了,而且错的很离谱
开发中如果这样使用,那么会出大问题的
请求转发应该只在查询中使用,切记 update insert delete 千万不能用转发,因为转发后的路径不会变,想必大家都知道的把 , 那么如果我们是insert 转发的,那么我们只要一刷新,就又插入一条数据,那么不就炸锅了?
查询如果使用重定向,那么只能把值存在session域中.session的默认生命是三十分钟,那么在三十分钟类,用户拿到的数据都不会改变,
影响用户体验 ,,
我们回到value stack 值栈中
值栈创建的时机
1.Servlet 跟 action 的区别
- Servlet 是 单例多线程 但是 Action是多例的,相对会安全些,可以使用成员变量,
- Servlet 只会创建一次,Action 每次请求到达都会创建一个新的实例
2.值栈什么时候创建 ?
请求到的时候值栈就会创建 当来了请求,会执行前端控制器的doFilter方法,在doFilter方法里面,有如下代码 89行
prepare.createActionContext(request, response);//下面是createActionContext()这个方法的内部//从ThreadLocal里面获取ActionContext实例,一开始是没有的,所以该对象是 null ActionContext oldContext = ActionContext.getContext(); if (oldContext != null) { // detected existing context, so we are probably in a forward ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap())); } else { //创建值栈对象 是OgnlValueStack 对象 ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack(); //给值栈里面的上下文区域存东西 。 存request \ response \session \application... stack.getContext().putAll(dispatcher.createContextMap(request, response, null)); //创建ActionContext的对象。 然后跟值栈关联上 ctx = new ActionContext(stack.getContext());}
3.值栈的内部结构
其实值栈的内部 就是一个list根元素 Root 一个Map 上下文Context
CompoundRoot root; //这其实是一个集合 listtransient Map<String, Object> context; //这是OGNL上下文 OGNLContext//底下还有一行代码 context.setRoot(root);//也就是设置了OGNL上下文的根其实就是一个list集合 。 说的具体一点。 就是那个CompoundRoot对象。
需要注意的是,当我们往值栈存值的时候,值存到了root里面,当我们往request ,等中存值,存入的是上下文, 取值的方式不一样.
还要很重要的一点就是 ,Context 上下文里面 又包含了值栈, 没有死循环,互相持有各种的引用,也就意味着我们只要拿到任何一个,都能取到对方. 在开发中,我们通常会使用Context 来获取值栈
我们取值是从上下文里面取的,因为上下文包含值栈,而 值栈 里有根元素,上下文 ,也就相当于有了全部数据 下面是值栈分析图
最后我们来讲讲获取值栈的方式
1.通过request获取,固定写法 方法参数源码里有
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);相应源码 :Dispatcher类中的serviceAction方法 , 位于568行request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());/*所以后续我们也只要使用request对象然后结合对应的STRUTS_VALUESTACK_KEY 这个key即可获取到值栈*/
2.通过ActionContext
ValueStack valueStack = ActionContext.getContext().getValueStack();
好啦,今天就到这里啦,如果有什么不对欢迎留言指出,蟹蟹
- struts2默认ognl,值栈
- Struts2 值栈/OGNL
- Struts2值栈/OGNL表达式
- struts2 ognl
- struts2 OGNL # % $
- struts2 OGNL # % $
- struts2 OGNL
- OGNL struts2
- struts2 OGNL
- Struts2 OGNL
- struts2 OGNL # % $
- Struts2---->OGNL
- Struts2 OGNL
- struts2 OGNL
- Struts2-OGNL
- struts2 OGNL
- STRUTS2 OGNL
- struts2 OGNL # % $
- 设计模式之禅2
- Google SDE 面经
- 【软考之旅】总结
- 选择排序实现
- 代码检视工具Gerrit的日常使用
- struts2默认ognl,值栈
- Scrapy学习笔记(5)---Item Loader
- [Unity插件]PlayMaker状态机
- 虚拟机中 CentOS 无法上网(connect: network is unreachable)
- ElasticSearch 常用的查询过滤语句
- CheckStyle使用手册
- Linux一些常用命令
- 重写重载区别
- 2节点类型