JaxbMapper.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
  3. */
  4. package com.jeeplus.common.mapper;
  5. import java.io.StringReader;
  6. import java.io.StringWriter;
  7. import java.util.Collection;
  8. import java.util.concurrent.ConcurrentHashMap;
  9. import java.util.concurrent.ConcurrentMap;
  10. import javax.xml.bind.JAXBContext;
  11. import javax.xml.bind.JAXBElement;
  12. import javax.xml.bind.JAXBException;
  13. import javax.xml.bind.Marshaller;
  14. import javax.xml.bind.Unmarshaller;
  15. import javax.xml.bind.annotation.XmlAnyElement;
  16. import javax.xml.namespace.QName;
  17. import org.springframework.http.converter.HttpMessageConversionException;
  18. import org.springframework.util.Assert;
  19. import com.jeeplus.common.utils.Exceptions;
  20. import com.jeeplus.common.utils.Reflections;
  21. import com.jeeplus.common.utils.StringUtils;
  22. /**
  23. * 使用Jaxb2.0实现XML<->Java Object的Mapper.
  24. *
  25. * 在创建时需要设定所有需要序列化的Root对象的Class.
  26. * 特别支持Root对象是Collection的情形.
  27. *
  28. * @author calvin
  29. * @version 2013-01-15
  30. */
  31. @SuppressWarnings("rawtypes")
  32. public class JaxbMapper {
  33. private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();
  34. /**
  35. * Java Object->Xml without encoding.
  36. */
  37. public static String toXml(Object root) {
  38. Class clazz = Reflections.getUserClass(root);
  39. return toXml(root, clazz, null);
  40. }
  41. /**
  42. * Java Object->Xml with encoding.
  43. */
  44. public static String toXml(Object root, String encoding) {
  45. Class clazz = Reflections.getUserClass(root);
  46. return toXml(root, clazz, encoding);
  47. }
  48. /**
  49. * Java Object->Xml with encoding.
  50. */
  51. public static String toXml(Object root, Class clazz, String encoding) {
  52. try {
  53. StringWriter writer = new StringWriter();
  54. createMarshaller(clazz, encoding).marshal(root, writer);
  55. return writer.toString();
  56. } catch (JAXBException e) {
  57. throw Exceptions.unchecked(e);
  58. }
  59. }
  60. /**
  61. * Java Collection->Xml without encoding, 特别支持Root Element是Collection的情形.
  62. */
  63. public static String toXml(Collection<?> root, String rootName, Class clazz) {
  64. return toXml(root, rootName, clazz, null);
  65. }
  66. /**
  67. * Java Collection->Xml with encoding, 特别支持Root Element是Collection的情形.
  68. */
  69. public static String toXml(Collection<?> root, String rootName, Class clazz, String encoding) {
  70. try {
  71. CollectionWrapper wrapper = new CollectionWrapper();
  72. wrapper.collection = root;
  73. JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrapper>(new QName(rootName),
  74. CollectionWrapper.class, wrapper);
  75. StringWriter writer = new StringWriter();
  76. createMarshaller(clazz, encoding).marshal(wrapperElement, writer);
  77. return writer.toString();
  78. } catch (JAXBException e) {
  79. throw Exceptions.unchecked(e);
  80. }
  81. }
  82. /**
  83. * Xml->Java Object.
  84. */
  85. @SuppressWarnings("unchecked")
  86. public static <T> T fromXml(String xml, Class<T> clazz) {
  87. try {
  88. StringReader reader = new StringReader(xml);
  89. return (T) createUnmarshaller(clazz).unmarshal(reader);
  90. } catch (JAXBException e) {
  91. throw Exceptions.unchecked(e);
  92. }
  93. }
  94. /**
  95. * 创建Marshaller并设定encoding(可为null).
  96. * 线程不安全,需要每次创建或pooling。
  97. */
  98. public static Marshaller createMarshaller(Class clazz, String encoding) {
  99. try {
  100. JAXBContext jaxbContext = getJaxbContext(clazz);
  101. Marshaller marshaller = jaxbContext.createMarshaller();
  102. marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
  103. if (StringUtils.isNotBlank(encoding)) {
  104. marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
  105. }
  106. return marshaller;
  107. } catch (JAXBException e) {
  108. throw Exceptions.unchecked(e);
  109. }
  110. }
  111. /**
  112. * 创建UnMarshaller.
  113. * 线程不安全,需要每次创建或pooling。
  114. */
  115. public static Unmarshaller createUnmarshaller(Class clazz) {
  116. try {
  117. JAXBContext jaxbContext = getJaxbContext(clazz);
  118. return jaxbContext.createUnmarshaller();
  119. } catch (JAXBException e) {
  120. throw Exceptions.unchecked(e);
  121. }
  122. }
  123. protected static JAXBContext getJaxbContext(Class clazz) {
  124. Assert.notNull(clazz, "'clazz' must not be null");
  125. JAXBContext jaxbContext = jaxbContexts.get(clazz);
  126. if (jaxbContext == null) {
  127. try {
  128. jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
  129. jaxbContexts.putIfAbsent(clazz, jaxbContext);
  130. } catch (JAXBException ex) {
  131. throw new HttpMessageConversionException("Could not instantiate JAXBContext for class [" + clazz
  132. + "]: " + ex.getMessage(), ex);
  133. }
  134. }
  135. return jaxbContext;
  136. }
  137. /**
  138. * 封装Root Element 是 Collection的情况.
  139. */
  140. public static class CollectionWrapper {
  141. @XmlAnyElement
  142. protected Collection<?> collection;
  143. }
  144. }