时间:2017-1-12 12:02

——OGNL

1、OGNL表达式是什么
    OGNL的全称是Object-Graph Navigation Language的缩写,中文名是对象图导航语言,它是一种功能强大的表达式语言。
    比EL表达式功能强大。

    Struts2将OGNL表达式语言集成到Struts2框架中,作为它的默认表达式语言。

2、OGNL表达式的功能
    1)支持对象方法调用,如:xxx.doSomeMethod()
    2)支持类静态的方法调用和值访问。
    3)访问OGNL上下文(OGNL Context)和ActionContext:(重点,操作ValueStack)
    4)支持赋值操作和表达式串联。
    5)操作集合对象。

3、OGNL中“根”与“非根”的区别

    root:只能有一个根,用于存储Action相关数据
    contextMap:用于存储Web相关数据

4、示例代码

在Java代码中使用ognl表达式。

根中数据不需要使用#获取。
非根中数据需要使用#获取。
OGNL叫做对象图导航语言。


Person.java

public class Person {
    private String name;
    private Dog dog;
 
    public Dog getDog() {
        return dog;
    }
 
    public void setDog(Dog dog) {
        this.dog = dog;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}
 

----------------------------------------------------------------------------------------------------------------------------

Dog.java

public class Dog {
    private String name;
    private Person p;
 
    public Person getP() {
        return p;
    }
 
    public void setP(Person p) {
        this.p = p;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

----------------------------------------------------------------------------------------------------------------------------

OgnlDemo1.java

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
 
public class OgnlDemo1 {
    public static void main(String[] args) throws OgnlException{
        // ognl可以通过对象调用方法
        System.out.println("aaa".length());
 
        /*
         * 使用ognl来实现上面操作
         * 1、创建一个ognl上下文对象
         * 2、调用getValue()方法
         */
        OgnlContext context = new OgnlContext();
        Object o1 = Ognl.getValue("'aaa'.length()", context.getRoot());
        System.out.println(o1);
 
 
        // 调用Math的静态方法和静态成员
        System.out.println(Math.max(10, 20));
        System.out.println(Math.PI);
 
        /*
         * 在ognl表达式中调用静态方法
         */
        Object o2 = Ognl.getValue("@java.lang.Math@max(10, 20)", context.getRoot());
        System.out.println(o2);
        Object o3 = Ognl.getValue("@java.lang.Math@PI", context.getRoot());
        System.out.println(o3);
    }
}
 

----------------------------------------------------------------------------------------------------------------------------

OgnlDemo2.java

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
 
public class OgnlDemo2 {
    public static void main(String[] args) throws OgnlException {
        /*
         * 创建一个ognl上下文 OgnlContext是一个Map集合 
         * public class ognl.OnglContext implements java.util.Map
         */
        OgnlContext context = new OgnlContext();
 
        Person p = new Person();
        p.setName("张三");
        Dog dog = new Dog();
        dog.setName("王五");
        p.setDog(dog);
 
        // 设置根
        context.setRoot(p);
 
        Dog d = new Dog();
        d.setName("李四");
        Person p2 = new Person();
        p2.setName("赵六");
        d.setP(p2);
 
        // 设置属性(非根)
        context.put("dog", d);
 
        // 使用ognl来获取根中数据
        // 获取根中数据,不需要加#
        Object o1 = Ognl.getValue("name", context, context.getRoot());
 
        System.out.println(o1);
 
        // 使用ognl来获取非根中的数据
        // 获取非根中数据,需要使用#
        Object o2 = Ognl.getValue("#dog.name", context, context.getRoot());
        System.out.println(o2);
 
        // 获取p中的dog对象
        // p表示根,所以可以省略p
        Object o3 = Ognl.getValue("dog.name", context, context.getRoot());
        System.out.println(o3);
 
        // 获取dog中的person
        Object o4 = Ognl.getValue("#dog.p.name", context, context.getRoot());
        System.out.println(o4);
    }
}
 

——在Struts2中使用ognl表达式

需要结合Struts2的标签使用:<s:property value="" />
    *   value:
        书写ognl表达式
    *   default:
        默认值
    *   escapeHtml
        是否解析HTML
    *   escapeJavaScript
        是否解析JS
    *   escapeXml
        是否解析XML

注意:在Struts的JSP页面中访问静态成员时,必须设置一个常量值:
    struts.ognl.allowStaticMethodAccess=false

示例代码:

  <h1>使用ognl通过对象来调用方法</h1>
  <s:property value="'aaa'.length()"/>
  <hr />
  <!-- 在Struts2中使用静态成员,必须设置一个常量 -->
  <s:property value="@java.lang.Math@max(10,20)"/>

——ValueStack

1、ValueStack是什么
    从技术角度来讲,ValueStack是一个接口(com.opensymphony.xwork2.util.ValueStack)。
    从实用角度来讲,ValueStack是一个容器,用于将数据携带到action数据页面,然后在页面通过ognl表达式来获取。

    ValueStack是Struts2提供的一个接口,实现类是OgnlValueStack。

    OGNL表达式是从ValueStack中获取数据的。

    每个Action实例都有一个ValueStack对象(一个请求对应一个ValueStack对象)
    ValueStack中保存当前Action对象和其他常用Web对象,例如request, session, application, parameters(值栈中是有Action引用的)
    Struts2框架把ValueStack对象保存在key为“struts.valueStack”的request域中(request中值栈对象是request的一个属性)

    一个request一个Action,一个Action一个ValueStack,request - Action - ValueStack是一一对应的。
    ValueStack生命周期就是一个request的生命周期。

    流程(源码分析):
        从第一个请求开始,被StrutsPrepareAndExecuteFilter拦截后执行doFilter()中的execute.executeAction(request, response, mapping);方法,然后一直调用,进入到Dispatcher中的serviceAction()方法,在该方法中通过request获取ValueStack对象:ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);如果是第一次获取,则ValueStack对象为null,然后创建一个新的ValueStack,因为每次请求都是一个新的请求,所以每次请求都会创建一个新的ValueStack。当请求结束后,ValueStack就被释放了,所以ValueStack的生命周期等同于request的生命周期。

        然后通过Dispatcher类中的serviceAction()方法中的:request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());来获取一个新的ValueStack对象,并保存到request域中,保存的key为:ServletActionContext.STRUTS_VALUESTACK_KEY,在ServletActionContext中可以查看,该常量的值为:struts.valueStack。

2、ValueStack的内部结构
    查看ValueStack接口,可以看到两个方法:
        *   public abstract Map<String, Object> getContext();
        *   public abstract CompoundRoot getRoot();
            >   public class CompoundRoot extends ArrayList
            >   CompoundRoot类继承了ArrayList,提供了peek() pop() push()方法,相当于栈。

    ValueStack接口中声明了root属性(CompoundRoot)、context属性(OgnlContext):
        *   CompoundRoot就是ArrayList。
        *   OgnlContext就是Map

    值栈由两部分组成:
        ObjcetStack:Struts2把Action和相关对象压入ObjectStack中,用一个List保存
            保存Action相关信息。
 
        ContextMap:Struts2把各种各样的映射关系(一些Map类型的对象)压入ContextMap中。
            比较常见的映射关系就是常见Web对象。

    Struts2会把下面这些映射压入ContextMap中:
        *   parameters:该Map中包含当前请求的请求参数
        *   request:该Map中包含当前request对象的所有属性
        *   session:该Map中包含当前session对象的所有属性
        *   application:该Map中包含当前application对象的所有属性。
        *   attr:该Map按如下顺序来检索某个属性:request、session、application,相当于全域查找
        *   对象引用
    通过断点可以发现:
        

    其中root在ContextMap中也有一个映射关系:
        ValueStack中包含ContextMap和Root,而在ContextMap中又持有了Root的引用。
    可以在断点调试中发现:
        

    OGNL表达式访问root(List)中数据时,不需要使用#访问。

    访问(Map)request、session、application、attr、parameters、对象引用时,必须写#。

    操作ValueStack时,默认是指操作root元素。

    其实ContextMap就是一个OgnlContext,可以查看ValutStack接口的实现类:OgnlValueStack
        protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticMethodAccess) {

        this.root = compoundRoot;
        this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
        this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);
        context.put(VALUE_STACK, this);
        Ognl.setClassResolver(context, accessor);
        ((OgnlContext) context).setTraceEvaluations(false);
        ((OgnlContext) context).setKeepLastEvaluation(false);
    }

结论:
        ValueStack有两个部分,一个是List,一个是Map。
        在Struts2中List就是Root,Map就是OgnlContext。
        在Struts2中,默认情况下(不加#)从ValueStack中的Root获取数据。

3、ValueStack对象的创建,ValueStack和ActionContext是什么关系?
    当请求发出时,会被doFilter()拦截然后调用Dispatcher类中的serviceAction()方法,方法中可以创建ValueStack对象:
        // 刚开始会到request域中获取

        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        // 如果获取不到ValueStack对象
        boolean nullStack = stack == null;
        if (nullStack) {
            // 会到ActionContext中获取 
            ActionContext ctx = ActionContext.getContext();
            if (ctx != null) {
                stack = ctx.getValueStack();
            }
        }

    ValueStack和ActionContext的关系:
        ActionContext中持有了ValueStack的引用。

4、如何获取ValueStack对象
    有两种方式可以获取ValueStack对象:
        1)通过request获取
        2)通过ActionContext获取
    public class OgnlDemo1Action extends ActionSupport {
 
        @Override
        public String execute() throws Exception {
 
            /*
             * 获取ValueStack
             */
            // 1、通过request获取
            ValueStack stack1 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
 
            System.out.println(stack1);
 
            // 2、通过ActionContext获取(推荐)
            ValueStack stack2 = ActionContext.getContext().getValueStack();
            System.out.println(stack2);
            return null;
        }
}

5、向ValueStack中保存数据(主要针对root)
    在ValueStack接口中有两个方法:
    有两种方式:
        *   push(Object obj)
        *   set(String key, Object obj)

    1)push(Object obj)
        在ValueStack接口的实现类OgnlValueStack中,重写了此方法:

            public void push(Object obj) {
                root.push(obj);
            }
        底层调用的是:root.add(0, obj);
        所以push方法会将对象压入栈顶。
        如果当前位置存在元素,那么当前元素会先后移,然后再在栈顶压入元素。

2)set(String key, Object obj)
        在ValueStack接口的实现类OgnlValueStack中,重写了此方法:
            public void set(String key, Object o) {

                Map setMap = retrieveSetMap();
                setMap.put(key, o);
            }
 
            private Map retrieveSetMap() {
                Map setMap;
                Object topObj = peek();
                if (shouldUseOldMap(topObj)) {
                    setMap = (Map) topObj;
                } else {
                    setMap = new HashMap();
                    // 将数据封装到一个新的HashMap中 
                    setMap.put(MAP_IDENTIFIER_KEY, "");
                    // 将Map集合压入栈顶
                    push(setMap);
                }
                return setMap;
            }
        底层是将数据封装到HashMap中,再将这个HashMap压入栈顶,保存到List集合中。 

示例代码:

        public String execute() throws Exception {
 
            ValueStack stack = ActionContext.getContext().getValueStack();
            stack.push("1");
            stack.push("2");
            stack.push("3");

            stack.set("username", "张三"); 
 
            List list = stack.getRoot();
            System.out.println(list);
 
            return null;
        }

输出结果:
        [3, 2, 1, com.wyc.action.OgnlDemo2Action@320859ec, com.opensymphony.xwork2.DefaultTextProvider@5c1958e7]


6、在JSP页面中使用<s:debug />标签查看ValueStack中的数据

    <body>
        <h1>使用debug标签查看ValueStack数据</h1>
        <!-- 通过debug标签查看ValueStack中存储的数据 -->
        <s:debug />
    </body>



7、在JSP页面中获取ValueStack数据
    获取Root中数据不需要#
    获取ContextMap中数据需要#

获取Root中的数据:

    1)如果栈顶是一个Map集合,那么获取时可以直接通过Map集合的key来获取value。
        <s:property value="username"/>

        如果只写属性名,那么即使栈顶不是Map集合,也会从栈顶开始依次往下查找。

    2)如果栈顶元素不是Map,不能通过key来获取,可以使用下标来获取元素:
        <s:property value="[0] />
            从0位置开始向下查找所有数据。

        <s:property value="[0].top" />
            只查找0位置上的数据。

    JSP页面示例代码:

        1、获取栈顶的Map
        <br />
        <s:property value="username" />
        <hr />
        2、获取栈顶非Map集合数据
        <br />
        <!-- 如果只写[0],表示从0位置开始检索元素 -->
        <s:property value="[0]" />
        <hr />
        <!-- [0].top表示获取栈的顶部元素 -->
        <s:property value="[0].top" />
        <hr />
        <!-- 如果只写[1],表示从1位置开始检索全部元素 -->
        <s:property value="[1]" />
        <hr />
        <!-- [1].top表示获取栈的第二个位置的元素 -->
        <s:property value="[1].top" />
        <hr />

获取OgnlContext中的数据:

    1)request数据
        request.setAttribute()
    2)session数据
        session.setAttribute()
    3)application数据
        application.setAttribute()
    4)attr
        依次从request, session, application域中查找。
        相当于pageContext的全域查找。
    5)parameters数据
        获取请求参数。

    JSP页面代码:
        3、获取OgnlContext中的数据

        <%
            request.setAttribute("rname", "rvalue");
            session.setAttribute("sname", "svalue");
            application.setAttribute("aname", "avalue");
        %>
 
        <s:property value="#request.rname"/><br />
        <s:property value="#session.sname"/><br />
        <s:property value="#application.aname"/><br />
        <s:property value="#attr.sname"/><br />
        <!-- 获取到的是参数的Map集合 -->
        <s:property value="#parameters"/><br />
        <!-- 获取指定参数 -->
        <!-- 当存在checkbox这种一键多值的情况时,#parameters.username会打印一个数组 -->
        <s:property value="#parameters.username"/><br />
        <!-- 获取数组中的第一个元素 -->
        <s:property value="#parameters.username[0]" />

8、ValueStack有什么作用
    使用ValueStack最大的作用就是将Action相关的数据以及Web相关的对象,传递到页面上。
    简单来讲,在Struts2中通过ValueStack将Action中的数据携带到页面上进行展示。

    1)Action向JSP携带的数据都是什么类型的数据?

    *   普通文本(字符串)

            >   fieldError:校验数据错误信息提示(常用于表单校验),this.addFieldError("msg", "字段错误信息")
            >   actionError:关于逻辑操作时的错误信息(普通错误信息,例如登录失败),this.addActionError("Action全局错误信息")
            >   message:通用信息,this.addActionMessage("Action普通消息信息")

            在JSP中使用Struts2标签显示错误信息:
                *   <s: fielderror fieldName="msg" />
                *   <s:actionerror />
                *   <s:actionmessage />

    *   复杂数据

            可以使用ValueStack存储:

            Action中存储数据:

                public String execute() throws Exception {
 
                    ValueStack stack = ActionContext.getContext().getValueStack();
 
                    List<User> users = new ArrayList<User>();
 
                    users.add(new User("zhangsan", "111", 20, "男"));
                    users.add(new User("lisi", "222", 30, "女"));
                    users.add(new User("wangwu", "333", 40, "男"));
 
                    // stack.push(users);
 
                    stack.set("users", users);
 
                    return SUCCESS;
                }

JSP中获取数据:
                <body>

                    <h1>使用ognl表达式来获取ValueStack中复杂数据</h1>
                    1、使用push()存储时获取数据(保存到OgnlContext中,是一个Map集合)
                    <s:property value="[0].top" />
                    <hr />
                    <s:iterator value="[0].top" var="user">
                        username:<s:property value="#user.username" /><br/>
                        password:<s:property value="#user.password" /><br/>
                        sex:<s:property value="#user.sex" /><br/>
                        age:<s:property value="#user.age" /><hr/>
                    </s:iterator>
 
                    <!-- 如果不为当前元素起别名,则默认使用当前元素 -->
                    <!-- 可以不写user,因为ContextMap中是有“user”的 -->
                    <s:iterator value="[0].top">
                        username:<s:property value="username" /><br/>
                        password:<s:property value="password" /><br/>
                        sex:<s:property value="sex" /><br/>
                        age:<s:property value="age" /><hr/>
                    </s:iterator>
 
                    <hr />
                    2、使用set存储数据(保存到List集合中)
                    <s:property value="users"/>
                    <hr />
                    <s:iterator value="users" var="user">
                        username:<s:property value="#user.username" /><br/>
                        password:<s:property value="#user.password" /><br/>
                        sex:<s:property value="#user.sex" /><br/>
                        age:<s:property value="#user.age" /><hr/>
                    </s:iterator>
                </body>

9、关于默认压入到ValueStack中的数据分析
    当前的Action会被默认压入ValueStack

    1)属性驱动
        每次请求访问Action对象,Action对象都会被压入ValueStack,在DefaultActioninvocation的init()方法中:
            stack.push(action);

        DefaultActioninvocation源码:

            public void init(ActionProxy proxy) {
                this.proxy = proxy;
                Map<String, Object> contextMap = createContextMap();
 
                // Setting this so that other classes, like object factories, can use the ActionProxy and other
                // contextual information to operate
                ActionContext actionContext = ActionContext.getContext();
 
                if (actionContext != null) {
                    actionContext.setActionInvocation(this);
                }
 
                createAction(contextMap);
 
                if (pushAction) {
                    stack.push(action);
                    contextMap.put("action", action);
                }
                ......
            } 

在拦截器被调用之前就压入ValueStack了。

        作用:
            当Action被压入ValueStack之后,Action如果向传递数据给JSP,只要将数据保存为成员变量,并且提供get()方法就可以了。

        当Action中声明了一个getXxx()方法后,ValueStack会将get之后的JavaBean的名称放到ValueStack的key中,然后在页面中可以直接使用JavaBean对象的key值来获取value值。

        

        示例代码:
            public class OgnlDemo4Action extends ActionSupport {

                private List<User> users;
 
                public List<User> getUsers() {
                    return users;
                }
                public void setUsers(List<User> users) {
                    this.users = users;
                }
                @Override
                public String execute() throws Exception {
 
                    ValueStack stack = ActionContext.getContext().getValueStack();
 
                    users = new ArrayList<User>();
 
                    users.add(new User("zhangsan", "111", 20, "男"));
                    users.add(new User("lisi", "222", 30, "女"));
                    users.add(new User("wangwu", "333", 40, "男"));
 
                    return SUCCESS;
                }
            }

        JSP代码:
            <s:iterator value="users" var="user">
                <s:property value="#user.username"/>
            </s:iterator>

2)模型驱动
        ModelDriven接口有一个单独的拦截器
            <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />
        在拦截器中,将Model对象压入了ValueStack:stack.push(model);
        如果Action实现了ModelDriven接口,ValueStack默认栈顶对象就是Model对象。
        因为Action对象在拦截器执行前就已经压入,而Model对象在ModelDrivenInterceptor拦截器执行时才会压入。

        ModelDrivenInterceptor源码:
             public String intercept(ActionInvocation invocation) throws Exception {

                Object action = invocation.getAction();

                // 将实现了ModelDriven接口的Action中的getModel()方法的返回值也就是内部封装的JavaBean对象压入到了ValueStack
                if (action instanceof ModelDriven) {
                    ModelDriven modelDriven = (ModelDriven) action;
                    ValueStack stack = invocation.getStack();
                    Object model = modelDriven.getModel();
                    if (model !=  null) {
                        stack.push(model);
                    }
                    if (refreshModelBeforeResult) {
                        invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
                    }
                }
                return invocation.invoke();
            }

在同一个请求中,Action中声明的private User user = new User();和getModel()方法中返回的User是相同的,也就是说在JSP页面中通过ValueStack获取到的User对象是同一个对象。但是,如果在execute()方法中对user重新赋值,那么push到ValueStack中的Action所包含的User就是后赋值的user对象,因为这个User对象是通过getXxx()方法获得的。而Model依然是private User user = new User();对象,因为Model是在execute()方法执行之前被压入的,所以在获取值时需要注意,这是两个对象。(new了两次,是两个对象。)

    ModelDriven中保存的是初始化时压入的对象。
    Action中保存的是execute()方法中赋值的对象。



    示例代码:

        public class OgnlDemo4Action extends ActionSupport implements ModelDriven {
            private User user = new User();
            @Override
            public String execute() throws Exception {
 
                return SUCCESS;
            }
            public Object getModel() {
                return this.user;
            }
        }

10、为什么EL表达式可以访问ValueStack中的数据

    Action中:
        stack.set("username", "张三");
    JSP中:

        ognl获取:<s:property value="username" /><br />
        EL获取:${username }

Struts2框架中所使用的request对象,是增强后的request对象,重写了getAttribute()方法。

    StrutsPreparedAndExecuteFilter的doFilter()方法中:
        request = prepare.wrapRequest(request)
        *   对Request对象进行了包装,包装类:StrutsRequestWrapper
        *   重写了request的getAttribute()方法
        Object attribute = super.getAttribute(key)
        if(attribute == null) {
            attribute = stack.findValue(key);
        }

    增强后的request,会首先在request范围查找,如果查找不到,会到ValueStack中查找。

——OGNL表达式的常见使用

1、#
    1)#相当于ActionContext.getContext()上下文
        <s:property value="#request.name" />
        相当于:ActionContext.getContext().getRequest().get("name");

    2)不写#默认在ValueStack的Root中进行查找

    3)进行投影映射以及过滤操作(结合复杂对象遍历)
        映射:
            <s:property value="ps" /><br />
            1、使用iterator进行遍历<br />

            <s:iterator value="ps" var="p">
                <s:property value="#p.name" /><br />
                <s:property value="#p.price" /><br />
                <s:property value="#p.count" /><br />
                </s:iterator>
            <hr/>
            2、对集合进行投影,只得到指定的属性<br />
            <!-- 只迭代name -->
            <s:iterator value="ps.{name}" var="name">
                <s:property value="#name" />
            </s:iterator>

        过滤: 
            3、对集合进行过滤操作<br />
            <!-- 得到商品价格大于2000的对象 -->
            <s:iterator value="ps.{?#this.price>1999}" var="p">
                名称:<s:property value="#p.name" /><br />
                价格:<s:property value="#p.price" /><br />
                数量:<s:property value="#p.count" /><br />
            </s:iterator>
            <hr />
            4、对集合进行过滤操作<br />
            <!-- 得到商品价格大于2000的商品的名称 -->
            <s:iterator value="ps.{?#this.price>1999}.{name}" var="pname">
                名称:<s:property value="#pname" /><br />
            </s:iterator>

    4)使用#构造Map集合
        经常结合Struts2标签用来生成select、checkbox、radio

        示例代码:
            1、使用#构造一个Map集合<br/>

                <s:iterator value="#{'name':'tom','age':20 }" var="entry">
                    <s:property value="#entry.key" /> --- <s:property value="#entry.value"/><br />
                </s:iterator>
                <hr/>
                2、构造一个List集合<br/>
                <s:iterator value="{'aa', 'bb', 'cc'}" var="list">
                    <s:property value="list" /><br/>
                </s:iterator>
                <hr/>
                3、手动创建一个集合,在Struts2中结合表单标签使用<br/>
                <s:form>
                    <!-- 用List集合创建radio表单标签 -->
                    <s:radio list="{'男', '女'}" name="sex"/><br/>
                    <!-- 用Map集合创建radio表单标签 -->
                    <s:radio list="#{'male':'男', 'female':'女' }" name="sex2"/><br/>
                    <!-- 使用List集合创建select -->
                    <s:select list="{'a', 'b', 'c'}" name="select" />
                </s:form>

2、%

    作用是用来设定当前字符串是否要解析为ognl表达式。

    <h1>演示%用法</h1>
    <%
        request.setAttribute("username", "tom");
    %>
    <s:property value="#request.username" default="null"/><br />
 
    <!-- 当前表达式会被作为ognl表达式解析 -->
    <s:property value="%{#request.username}"/><br/>
    <!-- 当前表达式不会被作为ognl表达式解析 -->
    <s:property value="%{'#request.username'}"/><br/>
    <!-- 如果不解析,则默认显示字符串 -->
    <s:textfield name="username" value="#request.username"/><br/>
    <s:textfield name="username" value="%{#request.username}"/><br/>
 

3、$
    作用是在配置文件中写ognl表达式来获取ValueStack中的数据。

    1)struts.xml
        <result type="stream">
            <param name="contentType">${contentType}</param>
        </result>

    2)在校验文件中使用
        <param min="${min}"></param>
        <param min="${max}"></param>
        <param min="${maxLength}"></param>
        校验文件会引入校验器,校验器会被加载,所以数据也会保存到ValueStack中。

    3)在国际化文件中使用
        在properties文件中:
            username=${#request.username}

        在JSP页面:
            <%

                request.setAttribute("username", "李四");
            %>
            <s:i18n name="com.wyc.resources.my">
                <s:text name="username" />
            </s:i18n>

        在properties文件中也可以使用%获取值:
            username=%{request.username} 

——总结

1、ognl介绍
2、ValueStack介绍
3、什么是ValueStack
4、ValueStack内部结构
5、ValueStack创建以及ActionContext关系
6、如何获取ValueStack
7、如何向ValueStack存储数据(Root)
8、JSP页面中如何获取ValueStack数据
9、关于ValueStack携带数据分析
    *   携带数据类型
    *   如何在页面上获取复杂数据
    *   ValueStack默认压入数据

10、如何使用OGNL表达式
    *   #
    *   %

    *   $

Struts2之OGNL与ValueStack的更多相关文章

  1. 【Struts2】Ognl与ValueStack

    一.OGNL 1.1 概述 1.2 OGNL 五大类功能 1.3 演示 二.ValueStack 2.1 概述 2.2 ValueStack结构 2.3 结论 2.3 一些问题 三.OGNL表达式常见 ...

  2. Struts2【OGNL、valueStack】就是这么简单

    什么是OGNL表达式? OGNL是Object Graphic Navigation Language 是操作对象属性的开源表达式. Struts2框架使用OGNL作为默认的表达式语言. 为什么我们学 ...

  3. struts2.1.6教程四、OGNL与ValueStack(VS)

    1.值栈入门 下面我们建立struts2ognl项目来练习ognl的使用. 步骤一.搭建strust2的开发环境 步骤二.建立LoginAction,主要代码如下: package com.asm; ...

  4. 浅析Struts2中的OGNL和ValueStack

    要了解Struts2与OGNL表达式的关系,我们必须先搞清楚以下三个概念: 1.  ActionContext它是Action运行的上下文环境,Action的多项设置都存放在次,我们每一次Action ...

  5. struts2之OGNL和struts2标签库和ValueStack对象

    OGNL简介: (1)OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.  struts2框架默认就支持Ognl表达式语言(所以 ...

  6. Struts2的OGNL表达式语言

    一.OGNL的概念 OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者 ...

  7. Struts2之OGNL

    一.OGNL是什么? OGNL(Object-Graph Navigation Language)对象图导航语言,是一种表达式语言,它可以 1.遍历对象的结构图 2.存取对象的属性(实例属性和静态属性 ...

  8. Struts2对Ognl的支持

                                                      Struts2对Ognl的支持 一. 写作背景 由于工作性质的变化,最近一直在研究struts2,从 ...

  9. 【struts2】OGNL

    1 OGNL概述 OGNL是对象图导航语言Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通 ...

随机推荐

  1. 备战- Java虚拟机

    备战- Java虚拟机 试问岭南应不好,却道,此心安处是吾乡. 简介:备战- Java虚拟机 一.运行时数据区域 程序计算器.Java 虚拟机栈.本地方法栈.堆.方法区 在Java 运行环境参考链接: ...

  2. Apache atlas liunx环境安装部署手册

    一.        背景 本文使用一台ubuntu虚拟机安装Apache-atlas,使用集成包unzip apache-atlas-2.1.0.zip进行快速安装部署,该集成包高度集成了hadoop ...

  3. YARN调度器(Scheduler)详解

    理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应的资源.在Yarn中,负责给应用分配资 ...

  4. PyVista:一款Python的三维可视化软件

    技术背景 三维可视化是一项在工业领域中非常重要的技术,而Python中最热门的可视化工具matplotlib和plotly,更加倾向于在数据领域的可视化,用于展现数据的结果.类似的还有百度的pyech ...

  5. GraphQL 概念入门

    GraphQL 概念入门 Restful is Great! But GraphQL is Better. -- My Humble Opinion. GraphQL will do to REST ...

  6. 【对线面试官】CountDownLatch和CyclicBarrier的区别

    <对线面试官>系列目前已经连载31篇啦,这是一个讲人话面试系列 [对线面试官]Java注解 [对线面试官]Java泛型 [对线面试官] Java NIO [对线面试官]Java反射 &am ...

  7. fiddler抓取手机模拟器数据

    引自:https://blog.csdn.net/lengdaochuqiao/article/details/88170522 1.下载最新版fiddler ,强烈建议在官网下载:https://w ...

  8. weex打包android apk采坑之旅(windows)

    1. npm install weex-toolkit -g 后weex命令不起作用 ,解决办法把weex.cmd所在的目录添加到环境变量PATH 2.weex命令每次报找不到文件'C:\Progra ...

  9. Laravel Ignition 2.5.1 代码执行漏洞(CVE-2021-3129)

    影响范围 Laravel 框架 < 8.4.3 facade ignition 组件 < 2.5.2 poc git clone https://github.com/simonlee-h ...

  10. ES6新特征

    1.块级作用域 {   }  就是块级作用域,还包括if.else.for.while...下都属于块级作用域. let 声明的变量不存在变量的提升,不允许let反复声明同一个变量:块级作用域下let ...