SSH框架之Struts2进阶OGNL与值栈详解(三)

2019-04-15  本文已影响0人  Seapp

第一节:OGNL详解

1.1 OGNL概述:

image.png

OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

1.2 OGNL的作用:

Struts2默认的表达式语言就是OGNL,它具有以下特点:

@[类全名(包括包路径)]@[方法名 | 值名]。
@java.lang.String@format('foo%s','bar')。

1.3 OGNL的要素:

OGNL的操作实际上就是围绕着OGNL结构的三个要素而进行的,分别是表达式(Expression)、根对象(Root Object)、上下文环境(Context),下面分别讲解这三个要素,具体如下:

1.4 OGNL入门实践

 @Test
    public void OgnlDemo() throws OgnlException {
        OgnlContext ognlContext = new OgnlContext();
        Object value = Ognl.getValue("'helloworld'.length()", ognlContext, ognlContext.getRoot());
        System.out.println(value);
    }

上述我们调用了字符串的length方法,其中'helloworld'.length()就是OGNL的表达式,最终的输出结果为9
OGNL除了可以访问对象的方法,还可以访问对象的静态方法。其语法格式如下:

@类的全路径名@方法名称(参数列表)
@类的全路径名@属性名称
//具体示例如下
 @Test
    public void OgnlDemo03() throws OgnlException {
        OgnlContext ognlContext = new OgnlContext();
        ognlContext.put("name","张三");
        String value = (String)Ognl.getValue("#name", ognlContext, ognlContext.getRoot());
        System.out.println(value);
    }

    @Test
    public void OgnlDemo04() throws OgnlException {
        OgnlContext ognlContext = new OgnlContext();
        User user = new User();
        user.setName("李四");
        ognlContext.setRoot(user);
        String name = (String)Ognl.getValue("name", ognlContext, ognlContext.getRoot());
        System.out.println(name);
    }

第二节:值栈的详解

2.1 值栈的概述:

ValueStack是Struts的一个接口,字面意思是值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个请求Struts2框架会创建一个action实例同时创建一个OgnlValueStack值栈实例,OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储的值栈中,并通过OGNL表达式读取值栈中的对象属性值。

2.2 值栈的内部结构:

OgnlContext中的一些引用:
  * parameters:该Map中包含当前请求的请求参数。
  * request:该Map中包含当前Request对象中的所有属性。
  * session:该Map中包含当前Session对象中的所有属性。
  * application:该Map中包含当前application对象中的所有属性
  * attr:该Map按如下顺序来检索某个属性:request,session,application

2.2 ActionContext和ValueStack的关系:

 public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
        Integer counter = 1;
        Integer oldCounter = (Integer)request.getAttribute("__cleanup_recursion_counter");
        if (oldCounter != null) {
            counter = oldCounter + 1;
        }

        ActionContext oldContext = ActionContext.getContext();
        ActionContext ctx;
        if (oldContext != null) {
            ctx = new ActionContext(new HashMap(oldContext.getContextMap()));
        } else {
            ValueStack stack = ((ValueStackFactory)this.dispatcher.getContainer().getInstance(ValueStackFactory.class)).createValueStack();
            stack.getContext().putAll(this.dispatcher.createContextMap(request, response, (ActionMapping)null));
            ctx = new ActionContext(stack.getContext());
        }

        request.setAttribute("__cleanup_recursion_counter", counter);
        ActionContext.setContext(ctx);
        return ctx;
    }

通过上述源码分析:

2.3 获取值栈对象

 //获取值栈对象
        //1。通过ActionContext获取valueStack对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();
        //2。通过request获取valueStack对象
        ValueStack valueStack1 = (ValueStack)ServletActionContext.getRequest()
                .getAttribute(ValueStack.VALUE_STACK);

2.4 操作值栈:

//编写Action类,在方法中获取值栈,并通过set或push方法向值栈中存储数据(这些数据被存储在root区域)
public class ValueStackDemo extends ActionSupport {

    @Override
    public String execute() throws Exception {
        //获取值栈对象
        //1。通过ActionContext获取valueStack对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();
        //2。通过request获取valueStack对象
        ValueStack valueStack1 = (ValueStack)ServletActionContext.getRequest()
                .getAttribute(ValueStack.VALUE_STACK);
        //3。存入数据
        User user = new User();
        user.setName("张三");
        user.setAge(19);
        valueStack.push(user);

        valueStack.set("username","李四");//创建一个Map集合,将该集合存放到栈顶。

        return SUCCESS;
    }
}

返回结果界面中debug查看值栈中的内容,并打印获取到存入值栈中的数据:

<s:debug></s:debug></br>
<s:property value="name"/></br>
<s:property value="age"/></br>
<s:property value="username"/></br>

2.5 获取数据

<s:property value="name"/></br>
<s:property value="age"/></br>
<%--获取集合中的数据--%>
<s:property value="list[0].name"/>
<s:property value="list[0].age"/></br>
<s:property value="list[1].name"/>
<s:property value="list[1].age"/></br>
<s:property value="list[2].name"/>
<s:property value="list[2].age"/></br>
<%--获取Context中的数据--%>
<s:property value="#request.username"/></br>
<s:property value="#session.username"/></br>
<s:property value="#application.username"/></br>
<s:property value="#attr.username"/></br>

对应存储数据的Action类:

public class ValueStackDemo extends ActionSupport {

    @Override
    public String execute() throws Exception {
        //获取值栈对象
        //1。通过ActionContext获取valueStack对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();
        //2。通过request获取valueStack对象
        ValueStack valueStack1 = (ValueStack)ServletActionContext.getRequest()
                .getAttribute(ValueStack.VALUE_STACK);
        //3。存入数据
        User user = new User("张三",19);
        valueStack.push(user);


        //4.创建集合数据将该数据存放到valueStack中
        List<User> list = new ArrayList<User>();
        list.add(new User("王五",5));
        list.add(new User("费六",6));
        list.add(new User("贵七",7));
        valueStack.set("list",list);
        //5.获取域对象,将数据存储到Context区域
        ServletActionContext.getRequest().setAttribute("username","r区域");
        ServletActionContext.getRequest().getSession().setAttribute("username","s区域");
        ServletActionContext.getServletContext().setAttribute("username","a区域");

        return SUCCESS;
    }
}

2.6 EL表达式在值栈中获取数据:

EL表达式之所以能从值栈中获取数据,是因为Struts2框架在底层对request.getAttribute()方法进行了增强。


第三节: OGNL中特殊字符的使用

3.1 #号:

<%--获取Context中的数据--%>
<s:property value="#request.username"/></br>
<s:property value="#session.username"/></br>
<s:property value="#application.username"/></br>
<%--使用#号构建Map集合--%>
<s:iterator var="i" value="{'aa','bb','cc','dd'}">
    <s:property value="i"></s:property> --- <s:property value="#i"></s:property>
</s:iterator>

3.2 %号:

<%--%的使用--%>
<%
    request.setAttribute("key","张三");
%>
<s:textfield  name="name" value="%{#request.key}"/>

3.3 $号:

上一篇 下一篇

猜你喜欢

热点阅读