当前位置: 移动技术网 > IT编程>开发语言>Java > Java xml数据格式返回实现操作

Java xml数据格式返回实现操作

2020年08月25日  | 移动技术网IT编程  | 我要评论
前言:对于服务器后端开发,接口返回的数据格式一般要求都是json,但是也有使用xml格式requestbody注解对于springmvc,很多人会认为接口方法使用@controller搭配@respo

前言:对于服务器后端开发,接口返回的数据格式一般要求都是json,但是也有使用xml格式

requestbody注解

对于springmvc,很多人会认为接口方法使用@controller搭配@responsebody和@requestmapping注解后,java对象会转换成json格式返回。

但实际上配合@responsebody注解后,接口返回的数据类型是根据http request header中的accept属性来确定的,可以是xml或者json数据

通过适当的httpmessageconverter对java对象进行格式转换,常用的有:

bytearrayhttpmessageconverter

负责读取二进制格式的数据和写出二进制格式的数据;

stringhttpmessageconverter

负责读取字符串格式的数据和写出二进制格式的数据;

resourcehttpmessageconverter

负责读取资源文件和写出资源文件数据;

formhttpmessageconverter

负责读取form提交的数据;

mappingjacksonhttpmessageconverter

负责读取和写入json格式的数据;

soucehttpmessageconverter

负责读取和写入 xml 中javax.xml.transform.source定义的数据;

jaxb2rootelementhttpmessageconverter

负责读取和写入xml 标签格式的数据;

atomfeedhttpmessageconverter

负责读取和写入atom格式的数据;

rsschannelhttpmessageconverter

负责读取和写入rss格式的数据

具体使用哪个怎么判断这里就不细讲了,我们关心的是jaxb2rootelementhttpmessageconverter这个方法,后面会讲为啥会提

java对象与xml之间互相转换

使用java自带注解的方式实现(@xmlrootelement,@xmlaccessortype,@xmlelement,@xmlattribute),具体使用方法网上有很多

这里直接代码举例

import javax.xml.bind.annotation.xmlelement;
import javax.xml.bind.annotation.xmlrootelement;
import javax.xml.bind.annotation.xmltype;

@xmlrootelement(name = "city")
@xmltype(proporder = { "name","province"})
public class city {
  private string name;
  private string province;

  public city() {
  }

  public city(string name, string province) {
    this.name = name;
    this.province = province;
  }

  public string getname() {
    return name;
  }

  @xmlelement
  public void setname(string name) {
    this.name = name;
  }

  public string getprovince() {
    return province;
  }

  @xmlelement
  public void setprovince(string province) {
    this.province = province;
  }
}

controller

import org.springframework.stereotype.controller;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.responsebody;

@controller
public class indexcontroller {

  @requestmapping(path = "/get")
  @responsebody
  public city getxml(){
    city city= new city("太原","山西");
    return city;
  }
}

请求http://www.lhsxpumps.com/_localhost:8080/get 返回结果如下

是不很容易就实现接口返回xml格式

使用<![cdata[]]>

对象属性中有可能存在计算逻辑'<‘或'>',而在xml文件中这两个符号是不合法的,会转换为&lt和&gt,这样数据就'坏'了,所以<![cdata[]]>的加入是非常有必要的!

一般实现:使用xmladapter定义一个cdataadapter类,网上也有很多代码

大概的实现如下

public class cdataadapter extends xmladapter<string, string> {
 
  @override
  public string unmarshal(string v) throws exception {
   // 我们这里没有xml转java对象,这里就不具体实现了
    return v;
  }
 
  @override
  public string marshal(string v) throws exception {
    return new stringbuilder("<![cdata[").append(v).append("]]>").tostring();
  }
 
}

然后使用注解xmljavatypeadapter作用于属性变量上

@xmljavatypeadapter(value=cdataadapter.class)
  @xmlelement
  public void setprovince(string province) {
    this.province = province;
  }

结果

但是实际上看源码

这个不是我们希望的,产生原因是jaxb默认会把字符'<', '>'进行转义, 下面解决这个问题

我们使用org.eclipse.persistence.oxm.annotations.xmlcdata注解来解决

使用eclipselink jaxb (moxy)

pom文件增加

<dependency>
  <groupid>org.eclipse.persistence</groupid>
  <artifactid>org.eclipse.persistence.moxy</artifactid>
  <version>xx版本</version>
</dependency>

上一节中的属性使用注解

...
import org.eclipse.persistence.oxm.annotations.xmlcdata;

  ...
  ...
 @xmlcdata 
  @xmlelement
  public void setprovince(string province) {
    this.province = province;
  }

注意:一定要设置jaxb.properties文件,并且要放在要转换成xml的java对象所在目录,并且要编译到target中,不然xmlcdata注解不生效

jaxb.properties文件内容,就是指定创建jaxbcontext对象的工长

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.jaxbcontextfactory

到这里配置完成!

补充知识:java document生成和解析xml

一)document介绍

api来源:在jdk中javax.xml.*包下

使用场景:

1、需要知道xml文档所有结构

2、需要把文档一些元素排序

3、文档中的信息被多次使用的情况

优势:由于document是java中自带的解析器,兼容性强

缺点:由于document是一次性加载文档信息,如果文档太大,加载耗时长,不太适用

二)document生成xml

实现步骤:

第一步:初始化一个xml解析工厂

documentbuilderfactory factory = documentbuilderfactory.newinstance();

第二步:创建一个documentbuilder实例

documentbuilder builder = factory.newdocumentbuilder();

第三步:构建一个document实例

document doc = builder.newdocument();

doc.setxmlstandalone(true);

standalone用来表示该文件是否呼叫其它外部的文件。若值是 ”yes” 表示没有呼叫外部文件

第四步:创建一个根节点,名称为root,并设置一些基本属性

element element = doc.createelement("root");

element.setattribute("attr", "root");//设置节点属性

childtwotwo.settextcontent("root attr");//设置标签之间的内容

第五步:把节点添加到document中,再创建一些子节点加入

doc.appendchild(element);

第六步:把构造的xml结构,写入到具体的文件中

实现源码:

package com.oysept.xml; 
import java.io.file; 
import javax.xml.parsers.documentbuilder;
import javax.xml.parsers.documentbuilderfactory;
import javax.xml.parsers.parserconfigurationexception;
import javax.xml.transform.outputkeys;
import javax.xml.transform.transformer;
import javax.xml.transform.transformerconfigurationexception;
import javax.xml.transform.transformerexception;
import javax.xml.transform.transformerfactory;
import javax.xml.transform.dom.domsource;
import javax.xml.transform.stream.streamresult;
 
import org.w3c.dom.document;
import org.w3c.dom.element;
 
/**
 * document生成xml
 * @author ouyangjun
 */
public class createdocument {
 
  public static void main(string[] args) {
    // 执行document生成xml方法
    createdocument(new file("e:\\person.xml"));
  }
 
  public static void createdocument(file file) {
    try {
      // 初始化一个xml解析工厂
      documentbuilderfactory factory = documentbuilderfactory.newinstance();
  
      // 创建一个documentbuilder实例
      documentbuilder builder = factory.newdocumentbuilder();
  
      // 构建一个document实例
      document doc = builder.newdocument();
      doc.setxmlstandalone(true);
      // standalone用来表示该文件是否呼叫其它外部的文件。若值是 ”yes” 表示没有呼叫外部文件
  
      // 创建一个根节点
      // 说明: doc.createelement("元素名")、element.setattribute("属性名","属性值")、element.settextcontent("标签间内容")
      element element = doc.createelement("root");
      element.setattribute("attr", "root");
  
      // 创建根节点第一个子节点
      element elementchildone = doc.createelement("person");
      elementchildone.setattribute("attr", "personone");
      element.appendchild(elementchildone);
  
      // 第一个子节点的第一个子节点
      element childoneone = doc.createelement("people");
      childoneone.setattribute("attr", "peopleone");
      childoneone.settextcontent("attr peopleone");
      elementchildone.appendchild(childoneone);
  
      // 第一个子节点的第二个子节点
      element childonetwo = doc.createelement("people");
      childonetwo.setattribute("attr", "peopletwo");
      childonetwo.settextcontent("attr peopletwo");
      elementchildone.appendchild(childonetwo);
  
      // 创建根节点第二个子节点
      element elementchildtwo = doc.createelement("person");
      elementchildtwo.setattribute("attr", "persontwo");
      element.appendchild(elementchildtwo);
  
      // 第二个子节点的第一个子节点
      element childtwoone = doc.createelement("people");
      childtwoone.setattribute("attr", "peopleone");
      childtwoone.settextcontent("attr peopleone");
      elementchildtwo.appendchild(childtwoone);
  
      // 第二个子节点的第二个子节点
      element childtwotwo = doc.createelement("people");
      childtwotwo.setattribute("attr", "peopletwo");
      childtwotwo.settextcontent("attr peopletwo");
      elementchildtwo.appendchild(childtwotwo);
  
      // 添加根节点
      doc.appendchild(element);
  
      // 把构造的xml结构,写入到具体的文件中
      transformerfactory formerfactory=transformerfactory.newinstance();
      transformer transformer=formerfactory.newtransformer();
      // 换行
      transformer.setoutputproperty(outputkeys.indent, "yes");
      // 文档字符编码
      transformer.setoutputproperty(outputkeys.encoding, "utf-8");
  
      // 可随意指定文件的后缀,效果一样,但xml比较好解析,比如: e:\\person.txt等
      transformer.transform(new domsource(doc),new streamresult(file));
  
      system.out.println("xml createdocument success!");
    } catch (parserconfigurationexception e) {
      e.printstacktrace();
    } catch (transformerconfigurationexception e) {
      e.printstacktrace();
    } catch (transformerexception e) {
      e.printstacktrace();
    }
  }
}

xml文件效果图:

三)document解析xml

实现步骤:

第一步:先获取需要解析的文件,判断文件是否已经存在或有效

第二步:初始化一个xml解析工厂

documentbuilderfactory factory = documentbuilderfactory.newinstance();

第三步:创建一个documentbuilder实例

documentbuilder builder = factory.newdocumentbuilder();

第四步:创建一个解析xml的document实例

document doc = builder.parse(file);

第五步:先获取根节点的信息,然后根据根节点递归一层层解析xml

实现源码:

package com.oysept.xml;
 
import java.io.file;
import java.io.ioexception; 
import javax.xml.parsers.documentbuilder;
import javax.xml.parsers.documentbuilderfactory;
import javax.xml.parsers.parserconfigurationexception;
 
import org.w3c.dom.attr;
import org.w3c.dom.document;
import org.w3c.dom.element;
import org.w3c.dom.namednodemap;
import org.w3c.dom.node;
import org.w3c.dom.nodelist;
import org.xml.sax.saxexception;
 
/**
 * document解析xml
 * @author ouyangjun
 */
public class parsedocument {
 
  public static void main(string[] args){
    file file = new file("e:\\person.xml");
    if (!file.exists()) {
      system.out.println("xml文件不存在,请确认!");
    } else {
      parsedocument(file);
    }
  }
 
  public static void parsedocument(file file) {
    try{
      // 初始化一个xml解析工厂
      documentbuilderfactory factory = documentbuilderfactory.newinstance();
  
      // 创建一个documentbuilder实例
      documentbuilder builder = factory.newdocumentbuilder();
  
      // 创建一个解析xml的document实例
      document doc = builder.parse(file);
  
      // 获取根节点名称
      string rootname = doc.getdocumentelement().gettagname();
      system.out.println("根节点: " + rootname);
  
      system.out.println("递归解析--------------begin------------------");
      // 递归解析element
      element element = doc.getdocumentelement();
      parseelement(element);
      system.out.println("递归解析--------------end------------------");
    } catch (parserconfigurationexception e) {
      e.printstacktrace();
    } catch (saxexception e) {
      e.printstacktrace();
    } catch (ioexception e) {
      e.printstacktrace();
    }
  }
 
  // 递归方法
  public static void parseelement(element element) {
    system.out.print("<" + element.gettagname());
    namednodemap attris = element.getattributes();
    for (int i = 0; i < attris.getlength(); i++) {
      attr attr = (attr) attris.item(i);
      system.out.print(" " + attr.getname() + "=\"" + attr.getvalue() + "\"");
    }
    system.out.println(">");
 
    nodelist nodelist = element.getchildnodes();
    node childnode;
    for (int temp = 0; temp < nodelist.getlength(); temp++) {
      childnode = nodelist.item(temp);
  
      // 判断是否属于节点
      if (childnode.getnodetype() == node.element_node) {
        // 判断是否还有子节点
        if(childnode.haschildnodes()){
          parseelement((element) childnode);
        } else if (childnode.getnodetype() != node.comment_node) {
          system.out.print(childnode.gettextcontent());
        }
      }
    }
    system.out.println("</" + element.gettagname() + ">");
  }
}

xml解析效果图:

以上这篇java xml数据格式返回实现操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网