有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaXStream:2如何处理JDK之间的集合?

我在IBMJDK(ibm-Java60-amd64)中生成了一个httpSession,并使用XStream将其解析为xml。 我想在其他jdk(orecle-jdk1.6.0-x86)上重新创建此会话映射,但反序列化时出错

我的Xstream对象:

public static XStream getXStreamConfigured( ){

 final XStream xstream = new XStream(){

  @Override
  protected MapperWrapper wrapMapper( final MapperWrapper next ){

    return new MapperWrapper( next )
    {

      @Override
      public boolean shouldSerializeMember(
           final Class definedIn,
           final String fieldName ){

         if ( definedIn == Object.class ){
            return false;
         }

         return super.shouldSerializeMember( definedIn, fieldName );
      }

    };      
  }

};

 xstream.autodetectAnnotations( true );

 final String dateFormatXmlPattern = FundXmlHandler.DATE_FORMAT_VIEW_AND_XML_FORMAT;
 final DateConverter dateConverter = new XStreamConverterDate( dateFormatXmlPattern );
 xstream.registerConverter( dateConverter );

 return xstream;

}

使用oracle jdk,此输出xml中生成的一些标记如下:

<java.util.TreeMap_-KeySet>
  <m class="tree-map"/>
</java.util.TreeMap_-KeySet>

使用ibm jdk,此输出xml中生成的一些标记如下:

<java.util.TreeMap_-1>
    <outer_class/>
</java.util.TreeMap_-1>

为什么它会为树形图生成这个? 为什么我不能在OracleJDK中加载IBMJDK生成的xml? 如何编写在两个jdk中生成相同输出的转换器

我的堆栈:

---- Debugging information ----
message             : java.util.TreeMap$1
cause-exception     : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message       : java.util.TreeMap$1
class               : java.util.HashMap
required-type       : java.util.HashMap
converter-type      : com.thoughtworks.xstream.converters.collections.MapConverter
path                : /map/entry[92]/java.util.TreeMap$1
line number         : 161079
version             : null
-------------------------------
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
    at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1052)
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1036)
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:912)
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:903)
    at br.com.mindsatwork.vinci.rwf.util.UtilitiesRwf.loadSavedSessionObject(UtilitiesRwf.java:3222)
    at br.com.mindsatwork.vinci.rwf.util.UtilitiesRwf.getFundDataFromSavedSession(UtilitiesRwf.java:1912)
    at br.com.mindsatwork.vinci.rwf.web.action.ActionHandleSavedSession.getFundData(ActionHandleSavedSession.java:86)
    at br.com.mindsatwork.vinci.rwf.web.action.AbstractActionWithFundDataUpload.executeIfLogged(AbstractActionWithFundDataUpload.java:88)
    at br.com.mindsatwork.vinci.rwf.web.action.ActionHandleSavedSession.executeIfLogged(ActionHandleSavedSession.java:64)
    at br.com.mindsatwork.vinci.rwf.web.action.AbstractActionWithLogin.executeAction(AbstractActionWithLogin.java:80)
    at br.com.mindsatwork.vinci.rwf.web.action.AbstractVinciAction.executeAction(AbstractVinciAction.java:148)
    at br.com.utilities.servlet.struts.action.AbstractStrutsActionWithDynaForm.executeAction(AbstractStrutsActionWithDynaForm.java:75)
    at br.com.utilities.servlet.struts.action.AbstractStrutsAction.execute(AbstractStrutsAction.java:57)
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:476)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:239)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1334)
    at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:426)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at br.com.utilities.servlet.struts.AbstractStrutsAppServer.service(AbstractStrutsAppServer.java:344)
    at br.com.mindsatwork.vinci.rwf.web.AppServer.service(AppServer.java:303)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:576)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:306)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:322)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1732)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: java.util.TreeMap$1
    at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:56)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
    at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:45)
    at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29)
    at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readItem(AbstractCollectionConverter.java:70)
    at com.thoughtworks.xstream.converters.collections.MapConverter.putCurrentEntryIntoMap(MapConverter.java:89)
    at com.thoughtworks.xstream.converters.collections.MapConverter.populateMap(MapConverter.java:77)
    at com.thoughtworks.xstream.converters.collections.MapConverter.populateMap(MapConverter.java:71)
    at com.thoughtworks.xstream.converters.collections.MapConverter.unmarshal(MapConverter.java:66)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    ... 42 more

如何将通用集合类型写入这个输出xml中,从而可以将其组装到不同的JDK中

链接http://x-stream.github.io/faq.html显示XStream有两种操作模式,纯Java和增强(默认)。纯Java应该可以与各种JVM一起工作。 我尝试使用纯Java用PureJavaReflectionProvider实例化XStream

在同一JVM中发生以下错误:

 com.thoughtworks.xstream.converters.ConversionException: Cannot construct java.util.TreeMap$KeySet as it does not have a no-args constructor : Cannot construct java.util.TreeMap$KeySet as it does not have a no-args constructor
---- Debugging information ----
message             : Cannot construct java.util.TreeMap$KeySet as it does not have a no-args constructor
cause-exception     : com.thoughtworks.xstream.converters.reflection.ObjectAccessException
cause-message       : Cannot construct java.util.TreeMap$KeySet as it does not have a no-args constructor
class               : java.util.TreeMap$KeySet
required-type       : java.util.TreeMap$KeySet
converter-type      : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path                : /map/entry[93]/java.util.TreeMap$KeySet
line number         : 36154
class[1]            : java.util.HashMap
converter-type[1]   : com.thoughtworks.xstream.converters.collections.MapConverter
version             : null
-------------------------------

共 (2) 个答案

  1. # 1 楼答案

    首先,我要回答你的第一个问题:

    Why it generate this for TreeMaps?

    元素本地名称为java.util.TreeMap_-1,因为XStream试图序列化java.util.TreeMap的匿名内部类

    关于第二个问题:

    How can i write a generic collections types into this output xml, that can be assembled into different jdks?

    您需要发布更完整的代码来演示问题。请参阅SSCCE.org了解需要哪些代码。目前,您没有为其他人提供足够的示例来重现问题

    我将根据您提供的信息对这个问题进行一些有根据的猜测

    XStream开箱即用地提供了a number of converters,包括TreeMapConverterjava.util.TreeMap。在我的环境中对树映射运行XStream的序列化时,我既看不到KeySet内部类,也看不到正在序列化的匿名内部类:

    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.mapper.MapperWrapper;
    import java.util.Date;
    import java.util.TreeMap;
    
    public class App {
    
        public static XStream getXStreamConfigured() {
    
            final XStream xstream = new XStream() {
    
                @Override
                protected MapperWrapper wrapMapper(final MapperWrapper next) {
    
                    return new MapperWrapper(next) {
    
                        @Override
                        public boolean shouldSerializeMember(
                                final Class definedIn,
                                final String fieldName) {
    
                            if (definedIn == Object.class) {
                                return false;
                            }
    
                            return super.shouldSerializeMember(definedIn, fieldName);
                        }
    
                    };
                }
    
            };
    
            xstream.autodetectAnnotations(true);
    
            return xstream;
        }
    
        public static void main(String[] args) {
            XStream xs = getXStreamConfigured();
    
            xs.toXML(new ExampleContainer().fill(), System.out);
        }
    
        public static class ExampleContainer {
    
            private TreeMap<String, Date> map = new TreeMap<>();
    
            public ExampleContainer() {
            }
    
            public ExampleContainer fill() {
    
                map.put("a", new Date());
                map.put("b", new Date());
                map.put("c", new Date());
                map.put("d", new Date());
                return this;
            }
        }
    }
    

    该代码为我提供了以下输出:

    <App_-ExampleContainer>
      <map>
        <entry>
          <string>a</string>
          <date>2014-06-21 22:40:53.598 UTC</date>
        </entry>
        <entry>
          <string>b</string>
          <date>2014-06-21 22:40:53.598 UTC</date>
        </entry>
        <entry>
          <string>c</string>
          <date>2014-06-21 22:40:53.598 UTC</date>
        </entry>
        <entry>
          <string>d</string>
          <date>2014-06-21 22:40:53.598 UTC</date>
        </entry>
      </map>
    </App_-ExampleContainer>
    

    在我看来,这似乎表明XStream正在使用它的默认转换器,它使用反射来检查类的TreeMap成员。出现这种情况的一些可能原因包括对MapperWrapper的不正确修改,或注册了不正确的Converter

    为了更好地进行分析,请提供一份SSCCE证明您的问题

  2. # 2 楼答案

    我找到了解决问题的办法

    首先,我必须删除所有匿名内部类,并将该代码片段放入公共类中。 例如,我将每个匿名比较器移动到一个特定的比较器类中。这也改进了设计

    我需要编写一个MapConverter、一个CollectionConverter和一个ComparatorConverter,以适当地序列化和组装对象。 这些类扩展了XStream API提供的MapConverter、CollectionConverter和JavaBeanConverter

    我创建了一个静态字符串禁止类列表,其中包含确定的jdk实现的所有特定类名。例如,我的列表有:

    Collections.EMPTY_LIST.getClass()

    Collections.singletonList( null ).getClass()

    在这些情况下,我只是在封送处理方法执行中忽略并序列化了一个真正空的集合-new ArrayList()

    我还根据如下列表测试了源类名:

    {"java.util.TreeMap$KeySet","java.util.TreeMap$1"}

    在my CollectionConverter中,不转换对象并将其重定向到正确的转换器,例如my MapConverter

    在那之后,一切都很好!=)

    避免使用所有匿名类,并在此类情况下实现特定类