`

struts2对Ognl的封装--PropertyAccessor

 
阅读更多

Ognl 中PropertyAccessor 用于从类实例中获取或设置属性值

Ognl中已有的PropertyAccessor :
因为不同的类的获取属性值和赋值方式不同,如Map、List、javabean,因此有多个子类,第一个子类对应一种类型。

 

Struts 对PropertyAccessor  的扩展

   Struts 加载扩展的PropertyAccessor 

            Struts 中在OgnlValueStackFactory中调用OgnlRuntime.setPropertyAccessor(Class class,PropertyAccessor  实例)方法来加载Struts中定义的PropertyAccess。

             在OgnlValueStackFactory 实例化之后,注入Containter时:

 

@Inject
    public void setContainer(Container container) throws ClassNotFoundException {
        Set<String> names = container.getInstanceNames(PropertyAccessor.class);
        for (String name : names) {
            Class cls = Class.forName(name);
            if (cls != null) {
                if (Map.class.isAssignableFrom(cls)) {
                    PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name);
                }
                OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name));
                if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) {
                    compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name);
                }
            }
        }
//省略其它代码
}

 

   那么Container中的PropertyAccessor类是从哪加载进来的呢??

   是由Struts-default.xml中bean定义中加载的:

 

    <bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.ObjectAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.Iterator" class="com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.Enumeration" class="com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.List" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.Set" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.Map" class="com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor" />
    <bean type="ognl.PropertyAccessor" name="java.util.Collection" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
    <bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.ognl.ObjectProxy" class="com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor" />

    xml中    type=ognl.PropertyAccessor,说明Class描述的类是一个PropertyAccessor类型

                class=com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor,说明此类是PropertyAccessor类型的实现类

                name=java.util.Map,说明PropertyAccessor实现类是对Map取值或赋值的。

 

 

             

 一、ObjectAccessor

    它把setProperty和getProperty的职责委托给父类,父类getProerty取值之后,ObjectAccessor会在Context上下文中记录当前处理的类及属性名。

     对于自定义类的属性的存取,首先会调用ObjectAccessor,获取属性,再从该属性中获取值时才用到其它PropertyAccessor,所以在ObjectAccessor记录类名及属性名,之后其它PropertyAccessor才会得到。

 

 

@Override
    public Object getProperty(Map map, Object o, Object o1) throws OgnlException {
        Object obj = super.getProperty(map, o, o1);

        map.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, o.getClass());
        map.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED, o1.toString());
        ReflectionContextState.updateCurrentPropertyPath(map, o1);
        return obj;
    }

    @Override
    public void setProperty(Map map, Object o, Object o1, Object o2) throws OgnlException {
        super.setProperty(map, o, o1, o2);
    }

 二、 XWorkEnumerationAccessor

     它扩展了EnumerationPropertyAccessor,EnumerationPropertyAccessor的setPropert方法直接抛出异常,因为Enumeration接口没有赋值方法,XWorkEnumerationAccessor的扩展,将setProperty功能委托给ObjectPropertyAccessor,去查找可能有的set方法,如果有就调用。原因是操作的实例可能不是一个单纯的Enumeration.

 

ObjectPropertyAccessor opa = new ObjectPropertyAccessor();
    @Override
    public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
        opa.setProperty(context, target, name, value);
    }

  Enumeration对象,表达式可用属性: next|nextElement,hasNext|hasMoreElements

 

三、XWorkIteratorPropertyAccessor

   它扩展了IteratorPropertyAccessor,父类IteratorPropertyAccessor的setProperty方法直接抛出异常,因为Iterator接口没有赋值方法,XWorkIteratorPropertyAccessor的扩展,将setProperty功能委托给ObjectPropertyAccessor,去查找可能有的set方法,如果有就调用。原因是操作的实例可能不是一个单纯的Iterator

 

    ObjectPropertyAccessor opa = new ObjectPropertyAccessor();
    @Override
    public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
        opa.setProperty(context, target, name, value);
    }

    Iterator对象,表达式可用属性: next,hasNext

 

四、XWorkCollectionPropertyAccessor

    它扩展了SetPropertyAccessor,一般情况下,表达式格式:collectionName['index'], 那么getPropertya和setProperty都交给父类处理。

 

特殊情况:表达式格式为collectionName.get('id'),即把collection当成Map,key=Collection中元素的主键属性值,通过“元素的主键属性值”对比"id"值而获取Collection中的元素。

   

   前提是:

   1.配置Collection中元素中哪一个属性做为主键属性?有如下几种方式:
       a.Collection属性、Collection属性的set/get方法上标注的KeyProperty annotation

       b.配置properties文件,文件名为“Collection属性所在类的全名 -conversion.properties”,文件位置: Collection属性所在类的类路径下,文件格式:KeyProperty_Collection属性名=Collection中元素的主键属性名

         c.在Collection所在类上标注Annotation: 

              

@Conversion(conversions={  
        @TypeConversion(rule=ConversionRule.KEY_PROPERTY,key = "KeyProperty_Collection属性名", value= "Collection中元素的主键属性名")  
        }  
) 
      d.在Collection属性的get/set方法上标注TypeConversion Annotation

 

     

 @TypeConversion(rule=ConversionRule.KEY_PROPERTY,key = "KeyProperty_Collection属性名", value= "Collection中元素的主键属性名") 
  

 

   2.配置Collection中元素类型(通过元素类型+主键属性名反射出主键属性类型,把值转换为主键属性的正确类型,以便比较),有如下几种配置方式:

     a.Collection属性、Collection属性的set/get方法上标注的Element annotation

       b.配置properties文件,文件名为“Collection属性所在类的全名 -conversion.properties”,文件位置: Collection属性所在类的类路径下,文件格式:Element_Collection属性名=Collection中元素类全名

      c.在Collection所在类上标注Annotation: 

         

@Conversion(conversions={  
        @TypeConversion(rule=ConversionRule.ELEMENT,key = "Element_Collection属性名", converter= "Collection中元素类的全名")  
        }  
)  
     d.在Collection属性的get/set方法上标注TypeConversion Annotation 

 

    

   

 @TypeConversion(rule=ConversionRule.ELEMENT,key = "Element_Collection属性名", converter= "Collection中元素类的全名") 
 

 

 

如果给定值与元素中的主键值对比过,没有匹配的,如何新建这样的一元素??

       1.首先需要允许新建对象ReflectionContextState.isCreatingNullObjects(context)==true

              这个在哪设定,得看完拦截器源码再写。

       2.配置了类中Collection中元素允许新建,有如下几种配置方式:

           a.Collection属性、Collection属性的set/get方法上标注的CreateIfNullannotation

           b..配置properties文件,文件名为“Collection属性所在类的全名 -conversion.properties”,文件位置: Collection属性所在类的类路径下,文件格式:CreateIfNull_Collection属性名=true

              c.在Collection属性所在的类上标注Annotation:

 

@Conversion(conversions={  
        @TypeConversion(rule=ConversionRule.CREATE_IF_NULL,key = "CreateIfNull__Collection属性名", value= "true")  
        }  
)  
                d.在Collection属性的get/set方法上标注TypeConversion Annotation  

 

 @TypeConversion(rule=ConversionRule.CREATE_IF_NULL,key = "CreateIfNull__Collection属性名", value= "true") 

 Collection 对象,表达式可用属性:size、iteratorisEmpty

   

 五、XWorkListPropertyAccessor

  它扩展了ListPropertyAccessor,

从List获取对象(getProperty):

  如果ReflectionContextState.isGettingByKeyProperty(context)==true,即根据List中元素的主键属性获取元素,则交给XWorkCollectionPropertyAccessor处理。

  其它情况直接交给父类ListPropertyAccessor获取,返回值不为空则直接返回。

 返回值为空则且以索引号方式取值,且配置了取值==null时,新建对象时,创建新对象并存入List,再返回。

 

如何配置取值为空时,新建对象?见上面XWorkCollectionPropertyAccessor说明的前提部分

   List 对象,表达式可用属性:size、iteratorisEmpty|empty、list对象属性名[‘索引号’]

 

 六、XWorkMapPropertyAccessor

  它扩展了MapPropertyAccessor,

 从Map获取对象(getProperty):

   委托父类MapPropertyAccessor获取值,如果取值为null且以Key值获取值方式,则把key转换为Map中Key元素的实际类型,再调用Map.get(key元素的正确类型),前提是需要配置key元素的类型,有几中配置方式:

         a.Map属性、Map属性的set/get方法上标注的Key annotation

       b.配置properties文件,文件名为“Map属性所在类的全名 -conversion.properties”,文件位置: Map属性所在类的类路径下,文件格式:Key_Map属性名=Map中Key元素的实际类型全名

         c.在Map所在类上标注Annotation: 

              

@Conversion(conversions={  
        @TypeConversion(rule=ConversionRule.KEY,key = "Key__Map属性名", converter="Map中key元素类型的全名")  
        }  
)  
      d.在Map属性的get/set方法上标注TypeConversion Annotation

 

     

 @TypeConversion(rule=ConversionRule.KEY,key = "Key__Map属性名", converter="Map中key元素类型的全名") 
   Map对象,表达式可用属性:size、keys|keySetisEmpt、values、Map对象属性名.key值
 
七、ObjectProxyPropertyAccessor
  它直接实现了PropertyAccessor,委托给其它的PropertyAccessor进行属性的存取:获取被代理的实际类型,由实际类型查找它的PropertyAccessor并调用存取属性方法:
return OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass()).getProperty(context, target, name);
  • 大小: 720.9 KB
分享到:
评论

相关推荐

    struts2对Ognl的封装--TypeConverter

    这篇博客文章"Struts2对Ognl的封装--TypeConverter"探讨了Struts2如何通过TypeConverter机制来增强OGNL的功能。 首先,我们来看一下OGNL。OGNL允许开发者用简洁的语法来获取和设置对象的属性,甚至可以进行复杂的...

    Struts2核心包ognl-2的源代码

    总之,这个压缩包提供的OGNL-2源代码是一份宝贵的教育资源,对于Java web开发人员,特别是那些专注于Struts2框架的开发者来说,是提高技能和解决实际问题的宝贵资源。通过阅读和分析这些源代码,我们可以深入理解...

    struts2 最新漏洞 S2-016、S2-017修补方案 .docx

    同时,需要注意的是,这两个漏洞的修补需要对 Struts2 的配置文件进行修改,因此需要对 Struts2 的配置文件有充分的了解和掌握。 Struts2 的 S2-016 和 S2-017 漏洞的修补需要对 Struts2 的源代码和配置文件进行...

    开发工具 ognl-3.1.12

    开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12开发工具 ognl-3.1.12...

    ognl.jar资源包

    camel-ognl-1.6.4.jar, camel-ognl-2.8.1.jar, com.springsource.org.ognl-2.6.9.jar, com.springsource.org.ognl-sources-2.6.9.jar, ognl-2.5.1.jar, ognl-2.6.11.jar, ognl-2.6.3.jar, ognl-2.6.5.jar, ognl-...

    Struts2_s2-016&017&ognl2.6.11_patch漏洞补丁

    struts.xml文件中新增以下内容: &lt;!-- 为修复struts2 s2-016、s2-017漏洞,重写DefaultActionMapper --&gt; ...ognl-2.6.11.jar直接覆盖掉原有文件。 使用工具进行测试漏洞是否依然存在。 2013年7月25日

    struts2中的OGNL的源码

    其中,OGNL(Object-Graph Navigation Language)是Struts2中的核心表达语言,用于在视图层与模型层之间传递数据。在深入理解OGNL的源码之前,我们首先需要了解OGNL的基本概念和用法。 OGNL是一种强大的表达式语言...

    JavaEE源代码 ognl-2.6.11

    JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.6.11...ognl-2.6.11JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.6.11JavaEE源代码 ognl-2.

    ognl-3.0.5-sources.jar

    ognl-3.0.5源码 本人最近在研究s2sh源码,如有需要请留言。 在使用过程中如果有问题可联系,让我们开始学习s2sh源码总动员吧!

    struts2-xwork-ognl的源文件(jar包)

    `ognl-3.0.6-sources.jar` 包含了OGNL的源代码,这是一门强大的表达式语言,用于在Struts2中访问和操作对象图。OGNL可以用来在视图层动态地获取或设置模型对象的属性,也可以在控制器层执行复杂的表达式来控制流程。...

    struts2_OGNL Demo

    Struts2_OGNL Demo 是一个用于演示Struts2框架中OGNL(Object-Graph Navigation Language)表达式语言的实例。这个项目旨在帮助开发者理解和学习如何在Struts2中使用OGNL来操纵对象和数据。OGNL是Struts2中一个重要的...

    ognl-3.1.12-API文档-中文版.zip

    赠送jar包:ognl-3.1.12.jar; 赠送原API文档:ognl-3.1.12-javadoc.jar; 赠送源代码:ognl-3.1.12-sources.jar; 赠送Maven依赖信息文件:ognl-3.1.12.pom; 包含翻译后的API文档:ognl-3.1.12-javadoc-API文档-...

    ognl-2.6.11.jar

    **描述:“struts2中ognl-2.6.11.jar源码文件”** **标签:“ognl”,“ognl-2.6.11”** 在Java Web开发领域,`ognl-2.6.11.jar`是一个关键的组件,它属于OGNL(Object-Graph Navigation Language)库的版本2.6.11...

    Struts2深入学习----OGNL表达式原理

    其中,OGNL(Object-Graph Navigation Language)是Struts2中的核心表达式语言,用于数据绑定和表示层的数据操作。这篇深入学习的文章主要探讨了OGNL表达式的原理和使用。 首先,我们来理解一下OGNL是什么。OGNL是...

    Struts2_OGNL

    OGNL(Object-Graph Navigation Language)是Struts2框架中的一个重要组件,用于在Web应用中访问和操作Java对象的属性,调用其方法,以及执行类型转换等操作。 OGNL是对象图导航语言的缩写,它是一种功能强大的...

    Struts2 OGNL标签详解析实例

    Struts2 OGNL---标签详解析 都有实例 适合初学者

    struts2.3.32修补S2-045漏洞所有核心jar包及依赖的jar(含core包)

    `ognl-3.2.jar`是Object-Graph Navigation Language的最新版本,它是Struts2中用于动态数据绑定和表达式语言的关键组件。在S2-045修复中,OGNL的表达式解析和执行机制得到了加强,增强了安全性,避免了恶意代码的...

    ognl-2.6.11.jar 官方源码

    **ognl-2.6.11.jar 官方源码详解** OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。它被广泛应用于许多Java框架,如Struts2,因为它允许动态地访问和操作对象的...

    ognl-3.2.21-API文档-中文版.zip

    赠送jar包:ognl-3.2.21.jar; 赠送原API文档:ognl-3.2.21-javadoc.jar; 赠送源代码:ognl-3.2.21-sources.jar; 赠送Maven依赖信息文件:ognl-3.2.21.pom; 包含翻译后的API文档:ognl-3.2.21-javadoc-API文档-...

Global site tag (gtag.js) - Google Analytics