zoukankan      html  css  js  c++  java
  • Jaxb对xml报文头的小修小改

    前言:
      也是在实际工作中, 借助jaxb来实现xml到java对象的映射转换. 在实际应用中, 也遇到了一些有趣好玩的东西, 权当记录下来.
      本文主要讲解jaxb如何生成约定的xml报文头的实现思路, 点比较小, 而且方法有点trick, 因此导致取博文标题的时候, 也有些小迷茫, ^_^.

    现象:
      我们先来定义一个简单的java类, 并用于生成其对应的xml内容.

        @Getter
        @Setter
        @NoArgsConstructor
        @AllArgsConstructor
        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlRootElement(name="root")
        public static class TNode {
    
            @XmlElement(name="key", required = true)
            private String key;
    
            @XmlElement(name="value", required = true)
            private String value;
    
        }
    
    
        public static void main(String[] args) {
            TNode obj = new TNode("key_1", "val_1");
            try {
                JAXBContext jc = JAXBContext.newInstance(TNode.class);
                Marshaller marshaller = jc.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    
                StringWriter writer = new StringWriter();
                marshaller.marshal(obj, writer);
    
                System.out.println(writer.toString());
            } catch (JAXBException e) {
                e.printStackTrace();
            }
        }

      注: 这是简单的实体类, 以及对应的jaxb生成xml的代码
      具体的生成结果如下:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <root>
        <key>key_1</key>
        <value>val_1</value>
    </root>

      在默认的xml报文头里, 比常见的多了一个standalone="yes" , 有没有办法去掉这个小尾巴呢?

    尝试思路:
      Marshaller类定义了很多属性, 我们先来看一下有没有报文头相关的配置.

    public interface Marshaller {
    
        // *) 指定编码模式
        public static final String JAXB_ENCODING = "jaxb.encoding";
    
        // *) 指定输出时, 是否支持缩进和换行
        public static final String JAXB_FORMATTED_OUTPUT = "jaxb.formatted.output";
    
        /**
         * The name of the property used to specify the xsi:schemaLocation
         * attribute value to place in the marshalled XML output.
         */
        public static final String JAXB_SCHEMA_LOCATION = "jaxb.schemaLocation";
    
        /**
         * The name of the property used to specify the
         * xsi:noNamespaceSchemaLocation attribute value to place in the marshalled
         * XML output.
         */
        public static final String JAXB_NO_NAMESPACE_SCHEMA_LOCATION 
            = "jaxb.noNamespaceSchemaLocation";
    
        // *) 是否生成报文头
        public static final String JAXB_FRAGMENT = "jaxb.fragment";
    
    }

      让人有点小失望, 里面涉及报文头的信息, 只有两个, JAXB_ENCODING控制编码, JAXB_FRAGMENT控制报文头的可见性, 对standalone的可见性没有配置项. 看来这条路是行不通的.

    解决思路:
      本来觉得jaxb提供了一些listener是可以实现这个功能, 不过还没研究. 无意中, 看到网友写了一段输出xml的代码, 突然想到他或许也遇到了同样的问题, 只是没把为什么这样做的目的写出来.
      我们重新修改下生成xml的代码:

        public static void main(String[] args) {
            TNode obj = new TNode("key_1", "val_1");
            try {
                JAXBContext jc = JAXBContext.newInstance(TNode.class);
                Marshaller marshaller = jc.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
                // 1) 隐去报文头的生成, Marshaller.JAXB_FRAGMENT默认为false
                marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
    
                StringWriter writer = new StringWriter();
                // 2) 自定义生成
                writer.write("<?xml version="1.0" encoding="UTF-8" ?>
    ");
                marshaller.marshal(obj, writer);
    
                System.out.println(writer.toString());
            } catch (JAXBException e) {
                e.printStackTrace();
            }
        }

      注: 两个要点, 1. 激活JAXB_FRAGMENT为true, 隐去jaxb自动生成xml报文头. 2. 自定义输出报文头信息
      测试一下, 结果如下:

    <?xml version="1.0" encoding="UTF-8" ?>
    <root>
        <key>key_1</key>
        <value>val_1</value>
    </root>
    

    总结:
      这也算得上一篇博客水文, 这边就当学习笔记, 抛砖引玉. 后续想对jaxb的性能优化, 以及内部的实现机制多多深入研究一下.

  • 相关阅读:
    CSS3实现投影效果
    @font-face使用在线字体
    JS全局对象的属性
    const命令声明变量应注意的几点
    IDEA设置不区分大小写提示
    分布式ID生成-雪花算法
    项目Git分支管理规范
    IDEA使用Mybatis插件 MyBatisCodeHelper-Pro
    解决码云出现git@gitee.com: Permission denied (publickey).
    安装RabbitMQ,一直提示Erlang版本过低
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/8985269.html
Copyright © 2011-2022 走看看