@XmlRootElement@Entity@Table(name = "employee")public class Employee { @Id @GeneratedValue(generator = "uuid2") @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator") //uuid自增 @Column(name = "id", columnDefinition = "BINARY(16)" ,nullable = false) private String id; @XmlElement public String getId() { return id; } public void setId(String id) { this.id = id; } @XmlElement public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElement public int getAge() { return age; } public void setAge(int age) { this.age = age; } @XmlElement public Gen getGen() { return gen; } public void setGen(Gen gen) { this.gen = gen; } @Column(name = "name") private String name; @Column(name = "age") private int age; @Enumerated(EnumType.STRING) @Column(name = "gen") private Gen gen; }
把稳: @XmlElement 标签 会与 lombok 的@Data 和 @Setter 、@Getter 表明发生冲突,大致缘故原由便是@Data产生的表明会使@JAXB认为产生重复的名称。
@XmlRootElement@XmlAccessorType(XmlAccessType.FIELD)public class EmployeeList { @XmlElementWrapper(name = "employees") @XmlElement(name = "employee") private List<Employee> employees; // Getter and setter for employees list public EmployeeList() { this.employees = new ArrayList<>(); } public EmployeeList(List<Employee> employees) { this.employees = employees; } public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; }}
注:如果想返回list凑集类型的数据,则须要利用创建一个专门转换list的工具。不然,jaxb 无法转换具有超类的工具。并且,须要为其工具添加无参布局函数,不然也会涌现缺点。
@Configurationpublic class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 添加XML转换器 MappingJackson2XmlHttpMessageConverter xmlConverter = new MappingJackson2XmlHttpMessageConverter(); // 配置XmlMapper XmlMapper xmlMapper = new XmlMapper(); xmlConverter.setObjectMapper(xmlMapper); converters.add(xmlConverter); // 添加JSON转换器(可选) MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); converters.add(jsonConverter); }}
通过,该转换器就可以实现自定义,返回类型了。

@GetMapping(value = "/findPojo", produces = {"application/xml;charset=UTF-8"}) //通过上面的Xml转换器,我们只须要再次添加返回类型即可,就不须要手动设置header为xml格式的了 @ApiOperation("查询数据") public Result<?> findPojoToXml() { TypedQuery<Employee> query = entityManager.createQuery( "SELECT e FROM Employee e WHERE e.age = :age", Employee.class); query.setParameter("age", 18); List<Employee> resultList = query.getResultList(); entityManager.close(); EmployeeList employeeList = new EmployeeList(resultList); JAXBContext context = null; String xmlString = ""; try { context = JAXBContext.newInstance(EmployeeList.class); // 利用Marshaller将工具转换为XML字符串 Marshaller marshaller = context.createMarshaller(); StringWriter writer = new StringWriter(); marshaller.marshal(employeeList, writer); // 打印XML字符串 xmlString = writer.toString(); log.info(xmlString); } catch (JAXBException e) { throw new RuntimeException(e); } //如果没有添加转换器,那么就须要手动设置,并且无法利用自己定义的返回 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); return new ResponseEntity<>(result, headers, HttpStatus.OK); //return Result.success(xmlString); }
@GetMapping(value = "/findPojo", produces = {"application/xml;charset=UTF-8"}) @ApiOperation("查询数据") public Result<?> findPojoToXml() { TypedQuery<Employee> query = entityManager.createQuery( "SELECT e FROM Employee e WHERE e.age = :age", Employee.class); query.setParameter("age", 18); List<Employee> resultList = query.getResultList(); entityManager.close(); EmployeeList employeeList = new EmployeeList(resultList); JAXBContext context = null; String xmlString = ""; try { context = JAXBContext.newInstance(EmployeeList.class); // 利用Marshaller将工具转换为XML字符串 Marshaller marshaller = context.createMarshaller(); StringWriter writer = new StringWriter(); marshaller.marshal(employeeList, writer); // 打印XML字符串 xmlString = writer.toString(); log.info(xmlString); } catch (JAXBException e) { throw new RuntimeException(e); } return Result.success(xmlString); }
把稳:利用自己编写的返回体和Spring自带的返回体的返回结果是不一样的,看看你须要哪种返回样式,再决定如何选择。详细,请比拟以上两张图片。
Java Xml@GetMapping("/findXml") @ApiOperation("查询数据") public ResponseEntity<?> findXml() { // 创建一个XML文档 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = null; try { dBuilder = dbFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } Document doc = dBuilder.newDocument(); // 创建根元素和子元素 Element rootElement = doc.createElement("data"); doc.appendChild(rootElement); Element nameElement = doc.createElement("name"); nameElement.appendChild(doc.createTextNode("John")); rootElement.appendChild(nameElement); Element ageElement = doc.createElement("age"); ageElement.appendChild(doc.createTextNode("30")); rootElement.appendChild(ageElement); // 将XML文档转换为字符串 TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = null; try { transformer = transformerFactory.newTransformer(); } catch (TransformerConfigurationException e) { throw new RuntimeException(e); } transformer.setOutputProperty(OutputKeys.INDENT, "yes"); DOMSource source = new DOMSource(doc); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); try { transformer.transform(source, result); } catch (TransformerException e) { throw new RuntimeException(e); } String xmlData = writer.toString(); log.info("xmlData:{}", xmlData); // 设置HTTP相应标头为XML return ResponseEntity.status(HttpStatus.OK) .header("Content-Type", "application/xml") .body(xmlData);// return Result.success(xmlData); }
JAXB
当您须要在Java中进行XML和Java工具之间的转换时,JAXB(Java Architecture for XML Binding)是一个非常有用的工具。JAXB供应了一种将Java类映射到XML表示(序列化)以及将XML表示映射回Java工具(反序列化)的机制。
常用的JAXB表明包括:
@XmlRootElement:用于标记根XML元素。@XmlElement:用于标记Java字段或属性,指示将其映射为XML元素。 --- 强调,这个表明浸染在属性上时,会把属性变为一个元素!!
!
这两个涌现的xml样式,差别巨大@XmlAttribute:用于标记Java字段或属性,指示将其映射为XML属性。--- 强调,这个表明浸染在属性上时,会把属性变为一个属性!
!
!
这两个涌现的xml样式,差别巨大@XmlType:用于定义类型信息。@XmlAccessorType:用于指定如何访问Java类的字段或属性。
创建JAXB高下文:要利用JAXB,您须要创建一个JAXB高下文,它卖力处理XML和Java工具之间的映射。常日,您会利用javax.xml.bind.JAXBContext类来创建高下文。例如:
JAXBContext context = JAXBContext.newInstance(Employee.class);
序列化:将Java工具转换为XML表示是JAXB的序列化过程。要实行序列化,您可以创建一个Marshaller实例,然后利用它将Java工具转换为XML。例如:
Employee employee = new Employee("12345", "John Doe", 30);Marshaller marshaller = context.createMarshaller();marshaller.marshal(employee, System.out); // 输出XML表示
反序列化:将XML表示转换回Java工具是JAXB的反序列化过程。要实行反序列化,您可以创建一个Unmarshaller实例,然后利用它将XML转换为Java工具。例如:
Unmarshaller unmarshaller = context.createUnmarshaller();Employee employee = (Employee) unmarshaller.unmarshal(new File("employee.xml"))
JAXB高下文缓存:JAXB高下文创建是一个开销较高的操作,因此常日建议将JAXB高下文缓存起来,以便在全体运用程序中重复利用。
import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import java.util.HashMap;import java.util.Map;public class JAXBContextCache { private static final Map<Class<?>, JAXBContext> contextCache = new HashMap<>(); public static JAXBContext getContext(Class<?> clazz) throws JAXBException { JAXBContext context = contextCache.get(clazz); if (context == null) { context = JAXBContext.newInstance(clazz); contextCache.put(clazz, context); } return context; } public static void main(String[] args) throws JAXBException { // 示例利用 Class<Employee> employeeClass = Employee.class; // 从缓存获取JAXB高下文 JAXBContext context = JAXBContextCache.getContext(employeeClass); // 利用高下文进行序列化或反序列化操作 // ... }}
处理凑集:JAXB还支持处理凑集,例如List或Set,可以将多个工具序列化为XML元素的列表,或者将XML元素列表反序列化为Java凑集。
自定义映射:如果须要更繁芜的映射,可以利用JAXB供应的自定义绑定选项,或者利用外部绑定文件(例如XML绑定措辞文件)来自定义映射规则。
我们有以下XML文档表示一个Book工具
<book> <title>Java Programming</title> <author>John Doe</author></book>
我们的Book类如下
@XmlRootElementpublic class Book { private String title; private String author; // 省略布局函数和访问器方法}
假设我们想要自定义映射规则,以将<title>元素映射到title属性,将<author>元素映射到author属性之外,还要将<publicationYear>元素映射到year属性。我们可以利用XML绑定措辞文件来实现这个自定义映射:
<?xml version="1.0" encoding="UTF-8"?><jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:annox="http://annox.dev.java.net" xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" jaxb:extensionBindingPrefixes="xjc annox namespace inheritance" version="2.1"> <jaxb:bindings schemaLocation="your-schema.xsd"> <jaxb:bindings node="/xs:schema/xs:element[@name='book']"> <jaxb:bindings node="xs:element[@name='title']"> <jaxb:property name="title" /> </jaxb:bindings> <jaxb:bindings node="xs:element[@name='author']"> <jaxb:property name="author" /> </jaxb:bindings> <jaxb:bindings node="xs:element[@name='publicationYear']"> <jaxb:property name="year" /> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings></jaxb:bindings>
利用xjc工具来天生自定义映射的Java类。运行以下命令:
xjc -d src -b customBindings.xml your-schema.xsd
这将天生与自定义映射规则匹配的Book类,包括title、author和year属性。现在,可以利用新天生的Book类来进行序列化和反序列化,JAXB将按照自定义映射规则处理XML数据
来源:https://juejin.cn/post/7274072375964155965