JAXB使用小记

近日在对接接口是报文需要是xml格式,所以今天小小总结下这段时间的收获。

首先介绍下jaxb,是java自带的将java实体类和xml文件转换的工具类。

使用时需要用到注解大致如下:

     @XmlRootElement:根节点注解也是最基本的注解 他有个name属性可以指定根节点的名字; 使用在类上  

     @XmlAccessorType:指明以什么标准生成xml,value的值有意向几种:

      

       1.XmlAccessType.FIELD:java对象中的所有成员变量

  2.XmlAccessType.PROPERTY:java对象中所有通过getter/setter方式访问的成员变量

  3.XmlAccessType.PUBLIC_MEMBER:java对象中所有的public权限的成员变量和通过getter/setter方式访问的成员变量

  4.XmlAccessType.NONE:java对象的所有属性都不映射为xml的元素

  默认值为PUBLIC_MEMBER

     @XmlElement:属性节点的注解 也有name属性可以指定属性节点的名字,在xml中的表现为@XmlElement为

                          @XMLRootElement的子节点;使用在成员字段或者方法上 

   注:在使用@XmlElement的时候需要注意下,当你想在成员变量上使用@XMLElement注解时需要再class

      加上XmlAccessorType,并且声明为FIELD

     @XmlType:当xml报文需要指定节点的循序时,可以通过这个注解他有个proorder属性可以自定义的顺序

                      (自定义时必须所有的字段都指定不然就会报错,而且指定顺序时不时用xml中的标签名而是字段名。)

   例:

@XmlElement(name="na")
private String name;//在XmlType中proOrder指定的是name儿不时na

  @XmlElementWrapper(name="XXX"):用在lis/map上 ,一般都会配合@XmlElement使用,效果就是在xml中有

           一个大标签(XmlElementWrapper)里面好多小标签(XmlElement),加入集合或者Map有数据的话

例:

//该注解适合在list , set  map  的上边使用便利集合生成xml 
@XmlElementWrapper(name="npts:elements")
@XmlElement(name = "npts:element")//该注解指定属性在xml中的标签 , 可以配合上边的注解生成嵌套
public List getElements() {return elements;}
效果:
        
              
                  10
                  天王星
                  nv
              
              
                  10
                  金星
                  nv
              
              
                  10
                  木星
                  nv
              
              
                  10
                  泰坦星
                  nv
              
        

当然如果你的报文中只需要许多的element标签也可以实现,只需要把XmlElementWrapper注释掉

例:

//该注解适合在list , set  map  的上边使用便利集合生成xml 
//@XmlElementWrapper(name="npts:elements")
@XmlElement(name = "npts:element")//该注解指定属性在xml中的标签 , 可以配合上边的注解生成嵌套
public List getElements() {return elements;}

效果:

          
              10
              天王星
              nv
          
          
              10
              天王星
              nv
          
          
              10
              金星
              nv
          
          
              10
              木星
              nv
          
          
              10
              泰坦星
              nv
          

由此之上的使用起来一般不会有什么问题:

下面是我使用的时候遇到的问题:

如果你把上边的注解玩了玩,会发现@XmlElement有一个属性为requare可以设置为true或false; 

网友说这个作用是设置为true是强制生成标签,但实际发现并不行。比如:某个成员变量的类型为String且在转换为xml的时候该变量的值为null 就不会产生该标签 ,但有的报文是需要的怎么办?。

不过有一个折中的方法就是给变量赋初值:"";这样可以完成需求 ,但是不够优雅 。后来我留意到在使用Marshaller转换时可以设置属性:

        Marshaller m = context.createMarshaller();
        // 是否格式化生成的xml串
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        //设置字符集
        m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        // 是否省略xm头声明信息
        m.setProperty(Marshaller.JAXB_FRAGMENT, false);

上边这些都不是解决方法哦。嘿嘿不过看了也不亏哈

Marshaller 还有个属性setListener(Listener listener)

JAXB使用小记_第1张图片

Listener是抽象类,他有两个方法

JAXB使用小记_第2张图片

顾名思义:和两个一个是在转换之前要做什么事情,一个是在转换之后做什么事前。两个方法的参数都是要转换的对象。

但是这两个方法体都是空的。

所以这里是他的实现类,重写这两个方法来完成我们想要做什么所以我就定义了一个类继承Listener。我们需要把刚提到的给为null的字段赋初值的动作方到这不就可以“优雅起来了”哈哈啊哈~

下面是重写方法:

      //反射获取所有字段
        Field[] fieldArr = source.getClass().getDeclaredFields();
        int len = fields.length;
        //遍历为该对象成员字段属性为String的赋初值
        for(int i = 0; i < len; ++i) {
            Field f = fieldArr[i];
            //设置可操控属性
            f.setAccessible(true);
            try {
                if (f.getType() == String.class && f.get(source) == null) {
                    f.set(source, "");
                }
            } catch (IllegalAccessException var8) {
                var8.printStackTrace();
            }
        }

        super.beforeMarshal(source);

然后还没完需要别忘了,我们需要把它用起来。 

            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty("jaxb.encoding", charset);
            marshaller.setProperty("jaxb.formatted.output", true);
            marshaller.setProperty("jaxb.fragment", false);
            //将自定义的Listener设置到Listener中
            marshaller.setListener(new SkeletonMarshallerListener());
            marshaller.marshal(object, nsfFilter);

效果:

前:

    
        10
        nv
    

后:


        
            
            10
            nv
        

ok;如果能帮到您最好不过,当然有什么不对的地方渴求大家指正。现行谢过

 

 

 

你可能感兴趣的:(xml,xml)