zoukankan      html  css  js  c++  java
  • OGNL,表达式上下文ContextMap

    1.OGNL表达式

      object graph navigation language:对象图导航语言

      存取对象属性;调用对象方法;字段类型转换等。

    <input type="text" name="user.username" /> 

    2.OGNL表达式的使用场景

    2.1 在jsp中

    s1.导入struts标签库:

    <%@ taglib prefix="s" uri="/struts-tags" %>

    s2. 只能在在struts标签库中使用OGNL表达式,不能再其他地方用

        对于property的value默认使用OGNL表达式。

      对于radio的list属性默认使用OGNL表达式

      纯字符串:

    <s:property value="%{'OGNLExpression'}" />
    <s:property value="'OGNLExpression'" />

      使用OGNL表达式:

    <s:textfield value="%{name}" label="姓名" />

      调用对象方法:

    <s:textfield value="%{'admin'.length()}" label="姓名" />
    <s:textfield value="%{'admin'.split('m')}" label="姓名" />

      调用静态类的静态成员:

    <s:property value="@java.lang.Math@PI" /><br />  静态成员
    <constant name="struts.ognl.allowStaticMethodAccess" value="true" />  开启允许调用OGNL静态方法【struts.xml中配置】
    <s:property value="@java.lang.Math@random()" />  静态方法

      操作List对象:{'',''}  -->ArrayList-->['','']

    <s:radio name="gender" list="{'male','female'}" label="性别"></s:radio>  list属性默认使用OGNL表达式

      操作Map对象:#{'':'' , '':''} -->Map -->{'':'', '':''}

    <s:radio name="sex" list="#{'1':'男','2':'女'}" label="性别2"></s:radio>

     

     3.OGNL表达式上下文:ContextMap

      contextMap是struts2封装好的一次请求可能出现的最大的数据容器。

      结构:是一个Map结构 {String:Object}

      里面存的数据:

    • application:ServletContext应用对象
    • session:HttpSession
    • valueStack:值栈    List类型
    • action:当前执行的动作类相关数据  【不是Map类型】
    • request:HttpServletRequest
    • parameters:请求参数
    • attr:四大域的属性数据

     除了ValueStack和action不是Map类型的,其他的都是Map类型{String : Object}

    4.ActionContext和ContextMap的关系

      ActionContext可以获取四大域对象,他是个工具类。

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.opensymphony.xwork2;
    
    import com.opensymphony.xwork2.inject.Container;
    import com.opensymphony.xwork2.util.ValueStack;
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Map;
    
    public class ActionContext implements Serializable {
        static ThreadLocal<ActionContext> actionContext = new ThreadLocal();
        public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";
        public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
        public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";
        public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application";
        public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters";
        public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";
        public static final String TYPE_CONVERTER = "com.opensymphony.xwork2.ActionContext.typeConverter";
        public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation";
        public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors";
        public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container";
        private Map<String, Object> context;
    
        public ActionContext(Map<String, Object> context) {
            this.context = context;
        }
    
        public void setActionInvocation(ActionInvocation actionInvocation) {
            this.put("com.opensymphony.xwork2.ActionContext.actionInvocation", actionInvocation);
        }
    
        public ActionInvocation getActionInvocation() {
            return (ActionInvocation)this.get("com.opensymphony.xwork2.ActionContext.actionInvocation");
        }
    
        public void setApplication(Map<String, Object> application) {
            this.put("com.opensymphony.xwork2.ActionContext.application", application);
        }
    
        public Map<String, Object> getApplication() {
            return (Map)this.get("com.opensymphony.xwork2.ActionContext.application");
        }
    
        public static void setContext(ActionContext context) {
            actionContext.set(context);
        }
    
        public static ActionContext getContext() {
            return (ActionContext)actionContext.get();
        }
    
        public void setContextMap(Map<String, Object> contextMap) {
            getContext().context = contextMap;
        }
    
        public Map<String, Object> getContextMap() {
            return this.context;
        }
    
        public void setConversionErrors(Map<String, Object> conversionErrors) {
            this.put("com.opensymphony.xwork2.ActionContext.conversionErrors", conversionErrors);
        }
    
        public Map<String, Object> getConversionErrors() {
            Map<String, Object> errors = (Map)this.get("com.opensymphony.xwork2.ActionContext.conversionErrors");
            if (errors == null) {
                errors = new HashMap();
                this.setConversionErrors((Map)errors);
            }
    
            return (Map)errors;
        }
    
        public void setLocale(Locale locale) {
            this.put("com.opensymphony.xwork2.ActionContext.locale", locale);
        }
    
        public Locale getLocale() {
            Locale locale = (Locale)this.get("com.opensymphony.xwork2.ActionContext.locale");
            if (locale == null) {
                locale = Locale.getDefault();
                this.setLocale(locale);
            }
    
            return locale;
        }
    
        public void setName(String name) {
            this.put("com.opensymphony.xwork2.ActionContext.name", name);
        }
    
        public String getName() {
            return (String)this.get("com.opensymphony.xwork2.ActionContext.name");
        }
    
        public void setParameters(Map<String, Object> parameters) {
            this.put("com.opensymphony.xwork2.ActionContext.parameters", parameters);
        }
    
        public Map<String, Object> getParameters() {
            return (Map)this.get("com.opensymphony.xwork2.ActionContext.parameters");
        }
    
        public void setSession(Map<String, Object> session) {
            this.put("com.opensymphony.xwork2.ActionContext.session", session);
        }
    
        public Map<String, Object> getSession() {
            return (Map)this.get("com.opensymphony.xwork2.ActionContext.session");
        }
    
        public void setValueStack(ValueStack stack) {
            this.put("com.opensymphony.xwork2.util.ValueStack.ValueStack", stack);
        }
    
        public ValueStack getValueStack() {
            return (ValueStack)this.get("com.opensymphony.xwork2.util.ValueStack.ValueStack");
        }
    
        public void setContainer(Container cont) {
            this.put("com.opensymphony.xwork2.ActionContext.container", cont);
        }
    
        public Container getContainer() {
            return (Container)this.get("com.opensymphony.xwork2.ActionContext.container");
        }
    
        public <T> T getInstance(Class<T> type) {
            Container cont = this.getContainer();
            if (cont != null) {
                return cont.getInstance(type);
            } else {
                throw new XWorkException("Cannot find an initialized container for this request.");
            }
        }
    
        public Object get(String key) {
            return this.context.get(key);
        }
    
        public void put(String key, Object value) {
            this.context.put(key, value);
        }
    }
    ActionContext

      ContextMap是一个Map类型的对象,key为application等,value为Map类型的数据,但是通过ContextMap.get(application)返回的是Object类型的对象。因此可以通过ActionContext工具类直接获取Map对象。

     

      域对象:

    com.opensymphony.xwork2.dispatcher.HttpServletxxx

      ContextMap中的数据:

    com.opensymphony.xwork2.ActionContext.application

      源码分析:ActionContext.java  

       static ThreadLocal<ActionContext> actionContext = new ThreadLocal();
       private Map<String, Object> context;   //传说中的ContextMap
      public static ActionContext getContext() {
    return (ActionContext)actionContext.get();
        }

    获取线程安全的ActionContext对象

       ServletActionContext.java

        public static HttpServletRequest getRequest() {
            return (HttpServletRequest)ActionContext.getContext().get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
        }

      通过ActionContext.getContext()静态方法可以获取一个线程安全的ActionContext对象,然后再调用里面的get方法:

      由此可知:域对象(ServletContext)、域对象数据(Map)都是存在context(Map<String, Object>)属性中的

       注意:ActionContext的声明周期为一次请求。

      ContextMap: {key: value}

    application:Map

    ActionContext.application:Map

    servlet.ServletContext:ServletContext

      往ContextMap中存入数据:

    public class UserAction extends ActionSupport {
        public String index(){
            ActionContext actionContext = ActionContext.getContext();
            actionContext.put("contextMapKey","this is ContextMap value");  //底层:ActionContext.context.put() 
            return SUCCESS;
        }
    }

      往ServletContext域中存入数据:application,

      取值:#ContextMap的key.key

    <s:property value="#application.application1" />

    5.ValueStack

      值栈中的数据不需要使用#访问。而ContextMap中的Value需要使用#Key

      valueStack是一个List集合

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.opensymphony.xwork2.util;
    
    import java.util.Map;
    
    public interface ValueStack {
        String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
        String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
    
        Map<String, Object> getContext();
    
        void setDefaultType(Class var1);
    
        void setExprOverrides(Map<Object, Object> var1);
    
        Map<Object, Object> getExprOverrides();
    
        CompoundRoot getRoot();
    
        void setValue(String var1, Object var2);
    
        void setParameter(String var1, Object var2);
    
        void setValue(String var1, Object var2, boolean var3);
    
        String findString(String var1);
    
        String findString(String var1, boolean var2);
    
        Object findValue(String var1);
    
        Object findValue(String var1, boolean var2);
    
        Object findValue(String var1, Class var2);
    
        Object findValue(String var1, Class var2, boolean var3);
    
        Object peek();
    
        Object pop();
    
        void push(Object var1);
    
        void set(String var1, Object var2);
    
        int size();
    }
    ValueStack.java

    方法:

      

      OGNLValueStack:继承ValueStack

       CompoundRoot root;    
       public Object peek() {
            return this.root.peek();
        }
    
        public Object pop() {
            return this.root.pop();
        }
    
        public void push(Object o) {
            this.root.push(o);
        }

      使用valueStack存入数据:User1Action.java

    public class User1Action extends ActionSupport {
        public String login(){
            ActionContext actionContext = ActionContext.getContext();
            //valueStack
            ValueStack valueStack = actionContext.getValueStack();
            Student student = new Student();
            student.setId(1);
            student.setUsername("张三");
            student.setAge(21);
            valueStack.push(student);
            return SUCCESS;
        }
    }
    View Code

      不建议把Map和List加到值栈中,建议存入到ContextMap。对于POJO建议存入到值栈中

    取值:先从栈顶找,有没有username的对象,再看有没有username的属性

     <s:property value="username" />
    栈顶:
    <s:property value="[0].username" />
    <s:property value="[1].username" />
    OGNL通过ValueStack.findValue方法找值

     6.struts2中使用EL

      (1)struts2中的EL :由于request对象被增强了,valueStack和ContextMap本质上是存入到request对象中,因此ActionContext是每次请求实例化一次。

    page --> request  --> valueStack -->  ContextMap --> session --> application

    案例:

    public class User2Action extends ActionSupport {
        public String index(){
            ActionContext actionContext = ActionContext.getContext();
            //valueStack
            Student student1 = new Student();
            student1.setId(1);
            student1.setUsername("张三");
            student1.setAge(21);
    
            Student student2 = new Student();
            student2.setId(3);
            student2.setUsername("张三2");
            student2.setAge(23);
    
            Map<String, Object> contextMap = actionContext.getContextMap();
            List<Student> list = new ArrayList<Student>();
            list.add(student1);
            list.add(student2);
            contextMap.put("students", list);
            return SUCCESS;
        }
    }
    User2Action

    EL :查找顺序 page>request>valueStack>ContextMap>session >application

     <table border="1">
          <tr>
              <th>姓名</th>
              <th>年龄</th>
          </tr>
          <c:forEach items="${students}" var="s">
              <tr>
                  <td>${s.username}</td>
                  <td>${s.age}</td>
              </tr>
          </c:forEach>
    
      </table>

      

    end

  • 相关阅读:
    android Context 持有导致的内存泄漏
    android PreferenceFragment
    android 修改 SwitchPreferenceCompat 高度,内边距,字体大小
    Android MPAndroidChart RadarChart (蜘蛛网图)
    Bugtags 测试平台(支持ios、android)
    BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)
    RecyclerView item 状态错乱
    RecyclerView android:layout_width="match_parent" 无效
    android-async-http cancelRequests
    Android MultiDex
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/9718446.html
Copyright © 2011-2022 走看看