《Netty学习笔记》:Http+Xml协议栈,Jibx自动绑定使用排坑

最近在学习《netty权威指南》,在第十章搭建http+xml服务器中,使用到了Jibx绑定对象和ant配置。书中对这一部分描述太少,同时我的为maven项目,在代码过程中遇到一些坑。在此记录总结一下。

本文源码已经上传到github,如果对你有用,欢迎star : https://github.com/icecrea/Netty

官方参考文档:http://jibx.sourceforge.net/bindcomp.html

先简单看下jibx相关的介绍:

使用JiBX绑定XML文档与Java对象需要分两步走:第一步是绑定XML文件,也就是映射XML文件与Java对象之间的对应关系;第二步是在运行时,实现XML文件与Java实例之间的互相转换。这时,它已经与绑定文件无关了,可以说是完全脱耦了。
在运行程序之前,需要先配置绑定文件并进行绑定,在绑定过程中它将会动态地修改程序中相应的class文件,主要是生成对应对象实例的方法和添加被绑定标记的属性JiBX_bindingList等。它使用的技术是BCEL(Byte Code Engineering Library),BCEL是Apache Software Foundation的Jakarta项目的一部分,也是目前Java classworking最广泛使用的一种框架,它可以让你深入JVM汇编语言进行类操作。在JiBX运行时,它使用了目前比较流行的一个技术XPP(Xml Pull Parsing),这也正是JiBX如此高效的原因。
JiBx有两个比较重要的概念:Unmarshal(数据分解)和Marshal(数据编排)。从字面意思也很容易理解,Unmarshal是将XML文件转换成Java对象,而Marshal则是将Java对象编排成规范的XML文件。JiBX在Unmarshal/Marshal上如此高效,这要归功于使用了XPP技术,而不是使用基于树型(tree-based)方式,将整个文档写入内存,然后进行操作的DOM(Document Object Model),也不是使用基于事件流(event stream)的SAX(Simple API for Xml)。XPP使用的是不断增加的数据流处理方式,同时允许在解析XML文件时中断。

我们可以概括一下:

JiBX 是一个绑定 XML 数据到 Java 对象的框架。JiBX 用一个绑定定义文挡(binding definition document)来定义 XML 数据与 Java 对象转换的规则,这个文挡就是联系 XML 数据与 Java 对象之间的桥梁。用到了两个数据绑定术语 marshal 和 unmarshal,marshal 是由 Java 对象生成 XML 文挡,unmarshal 是根据 XML 文挡建立 Java 对象。

使用 JiBX 的过程分成两个过程,一个是 binding compiler,另一个是 binding runtime。binding compiler 是一个前期准备过程,包括定义绑定定义文挡,定义与 XML 绑定在一起的 Java 对象,然后编译。binding runtime 是使用 binding compiler 编译好的 Java class 处理 XML 数据。

Step1:使用Jibx工具类,生成binding.xml与pojo.xsd文件

引入jibx-bind 与util包

            <groupId>org.jibx</groupId>
            <artifactId>jibx-bind</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.jibx</groupId>
            <artifactId>jibx-tools</artifactId>
            <version>1.3.1</version>
        </dependency>
  • 此处注意:书中是1.2.5版本,但是Jdk1.8与该版本有bug,在1.3.1已经修复。所以此处需要用高版本

相关issue https://github.com/jibx/jibx/issues/3

自动生成有 两种方式

一、命令行生成

可以通过命令行生成bing.xml和pojo.xsd
注意:要使用官网下载的包,不能用maven仓库中的,该格式会少包。
以下命令会生成 binding.xml和pojo.xsd 文件
进入classes文件目录 cd F:\IdeaProj\Netty\target\classes\

     java -cp E:\jibx\jibx_1_3_1\jibx\lib\jibx-tools.jar org.jibx.binding.generator.BindGen -b binding.xml com.example.cp10http.xml.pojo.Order

二、编写测试类代码生成

使用org.jibx.binding.generator.BindGen

import org.jibx.binding.Compile;
import org.jibx.binding.generator.BindGen;
import org.jibx.runtime.JiBXException;

import java.io.IOException;

  public class GenerateBindXmlUtil {
    public static void main(String[] args) throws JiBXException, IOException {

        genBindFiles();
    }

    private static void genBindFiles() throws JiBXException, IOException {
        String[] args = new String[9];

        // 指定pojo源码路径(指定父包也是可以的)。必须
        args[0] = "-s";
        args[1] = "src";

        // 自定义生成的binding文件名,默认文件名binding.xml。可选
        args[2] = "-b";
        args[3] = "binding.xml";

        // 打印生成过程的一些信息。可选
        args[4] = "-v";

        // 如果目录已经存在,就删除目录。可选
        args[5] = "-w";

        //- t 指定xml和xsd输出路径 路径。默认路径 .(当前目录,即根目录)。
        args[6] = "-t";
        args[7] = "./src/main/java/com/example/cp10http/xml/pojo/order";

        // 告诉 BindGen 使用下面的类作为 root 生成 binding 和 schema。必须
        args[8] = "com.example.cp10http.xml.pojo.Order";

        BindGen.main(args);
    }

}


生成后位置如下,可以再移动到项目目录下


Step2:根据binding.xml文件,生成class文件

此处我们可以使用maven的jibx插件,将Bind绑定到编译时期

    <build>
        <plugins>
            <plugin><!-- 生成jibx class信息 -->
                <groupId>org.jibx</groupId>
                <artifactId>jibx-maven-plugin</artifactId>
                <version>1.3.1</version>
                <configuration>
                    <schemaBindingDirectory>${basedir}/</schemaBindingDirectory>
                    <includeSchemaBindings>
                        <includeSchemaBindings>*binding.xml</includeSchemaBindings>
                    </includeSchemaBindings>
                    <verbose>true</verbose>
                </configuration>
                <executions>
                    <execution>
                        <id>jibx-bind</id>
                        <phase>compile</phase><!--把jibx绑定到了comile编译阶段 -->
                        <goals>
                            <goal>bind</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

通过mvn jibx:bind命令来运行插件 或者直接mvn clean install 均可以生产所需要Class文件,如下图所示:


image.png

同样也可以直接代码编译生成

public class GenerateBindXmlUtil {
    public static void main(String[] args) throws JiBXException, IOException {

        compile();
    }

    private static void compile() {
        String[] args = new String[2];

        // 打印生成过程的详细信息。可选
        args[0] = "-v";

        // 指定 binding 和 schema 文件的路径。必须
        args[1] = "./binding.xml";

        Compile.main(args);
    }

}

Step3:运行测试类验证

上面两步正确,最后一步就是验证测试类了,在控制台成功输出。

public class TestOrder {
    private IBindingFactory factory = null;
    private StringWriter writer = null;
    private StringReader reader = null;
    private final static String CHARSET_NAME = "UTF-8";

    private String encode2Xml(Order order) throws JiBXException, IOException {
        factory = BindingDirectory.getFactory(Order.class);
        writer = new StringWriter();
        IMarshallingContext mctx = factory.createMarshallingContext();
        mctx.setIndent(2);
        mctx.marshalDocument(order, CHARSET_NAME, null, writer);
        String xmlStr = writer.toString();
        writer.close();
        System.out.println(xmlStr.toString());
        return xmlStr;
    }

    private Order decode2Order(String xmlBody) throws JiBXException {
        reader = new StringReader(xmlBody);
        IUnmarshallingContext uctx = factory.createUnmarshallingContext();
        Order order = (Order) uctx.unmarshalDocument(reader);
        return order;
    }

    public static void main(String[] args) throws JiBXException, IOException {
        TestOrder test = new TestOrder();
        Order order = OrderFactory.create(123);
        String body = test.encode2Xml(order);
        Order order2 = test.decode2Order(body);
        System.out.println(order2);

    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容