使用JAXB首先要知道它是干什么的
当然,切入正题
很多时候我们需要把认知世界转化为我们熟悉的java对象,以供方便操作。这里,JAXB可以把xml对象转化为我们的java对象,也可以把java对象转化为xml对象。这时候我们就得知道它的两个转化方法。
一个是unmarshal(),一个是marshal()
unmarshal()是把xml对象转化为我们需要的java对象的方法,自然marshal()是把java对象转化为xml对象的一个过程。
我们需要的估计就是这两个方法的精华,只需要用到这么多就可以完成很多的事情了。下面看代码:
private static <T> T unmarshal(File templateFile, JAXBContext context) throws JAXBException { final Unmarshaller unmarshaller = context.createUnmarshaller(); // Unmarshal the XML in the stringWriter back into an object final T chart = (T) unmarshaller.unmarshal(templateFile); return chart; } @SuppressWarnings("unchecked") private static <T> T unmarshal(String template, JAXBContext context) throws JAXBException { final Unmarshaller unmarshaller = context.createUnmarshaller(); // Unmarshal the XML in the stringWriter back into an object final T chart = (T) unmarshaller.unmarshal(new StringReader(template)); return chart; }
这里templateFile 和 template 都是xml文件对象,这样的两个overload method就可以完成由xml对象转化为java对象了。
private static <T> String marshal(JAXBContext context, final T chart) throws JAXBException { // Create the marshaller, this is the nifty little thing that will // actually transform the object into XML final Marshaller marshaller = context.createMarshaller(); // Create a stringWriter to hold the XML final StringWriter stringWriter = new StringWriter(); // Marshal the javaObject and write the XML to the stringWriter marshaller.marshal(chart, stringWriter); String chartXml = stringWriter.toString(); return chartXml; }
marshal()方法也贡献上。
方法都具备了 可以开工了。
public static <T> String process(File templateFile, Class<T> type, ChartFiller<T> filler) { String chartXml = null; try { JAXBContext context = JAXBContext.newInstance(type); final T chart = (T) unmarshal(templateFile, context); filler.fill(chart); chartXml = marshal(context, chart); } catch (JAXBException e) { log.error(e.getMessage(), e); } return chartXml; } public static <T> String process(String template, Class<T> type, ChartFiller<T> filler) { String chartXml = null; try { JAXBContext context = JAXBContext.newInstance(type); final T chart = (T) unmarshal(template, context); filler.fill(chart); chartXml = marshal(context, chart); } catch (JAXBException e) { log.error(e.getMessage(), e); } return chartXml; } public interface ChartFiller<T> { void fill(T chart); }
工具方法都上齐了,你就可以在你需要的地方调用了。当然,我还没讲我们的java操作对象。
下面举个例子,比如上面出现的chart 就是我们需要操纵的对象,它可能是一个xml对象,而我们需要操作的是java对象,晕了吧:
比如我们的chart是在页面需要显示的图形,比如fusioncharts 的某个图,先定义为chart,它会是一个接口类,是所有xxxChart的父类。 比如我的具体chart名叫GaugeChart。
代码如下,别说晕说郁闷了:
public interface Chart { }
@XmlRootElement(name = "chart") public class GaugeChart implements Chart { @XmlAttribute private String lowerLimit; @XmlAttribute private String upperLimit; @XmlAttribute private String lowerLimitDisplay; @XmlAttribute private String upperLimitDisplay; @XmlAttribute private String majorTMNumber; @XmlAttribute private String majorTMColor; @XmlAttribute private String majorTMHeight; @XmlAttribute private String minorTMNumber; @XmlAttribute private String minorTMColor; @XmlAttribute private String minorTMHeight; @XmlAttribute private String displayValueDistance; @XmlAttribute private String tickValueDistance; @XmlAttribute private String gaugeStartAngle; @XmlAttribute private String gaugeEndAngle; @XmlAttribute private String palette; @XmlAttribute private String showValue; @XmlAttribute private String numberSuffix; @XmlElementWrapper(name = "colorRange") @XmlElement(name = "color") private List<Color> colors; @XmlElementWrapper(name = "dials") @XmlElement(name = "dial") private List<Dial> dials; @XmlElementWrapper(name = "annotations") @XmlElement(name = "annotationGroup") private List<AnnotationGroup> annotations; public void addAnnotationGroup(AnnotationGroup annotationGroup) { if (annotations == null) annotations = new LinkedList<AnnotationGroup>(); this.annotations.add(annotationGroup); } public void addDials(Dial dial) { if (dials == null) dials = new LinkedList<Dial>(); this.dials.add(dial); } public void setAnnotations(List<AnnotationGroup> annotations) { this.annotations = annotations; } public void setDials(List<Dial> dials) { this.dials = dials; } public void setColors(List<Color> colors) { this.colors = colors; } public void addColor(Color color) { if (color == null) colors = new LinkedList<Color>(); this.colors.add(color); } public void setLowerLimit(String lowerLimit) { this.lowerLimit = lowerLimit; } public void setUpperLimit(String upperLimit) { this.upperLimit = upperLimit; } public void setLowerLimitDisplay(String lowerLimitDisplay) { this.lowerLimitDisplay = lowerLimitDisplay; } public void setUpperLimitDisplay(String upperLimitDisplay) { this.upperLimitDisplay = upperLimitDisplay; } public void setMajorTMNumber(String majorTMNumber) { this.majorTMNumber = majorTMNumber; } public void setMajorTMColor(String majorTMColor) { this.majorTMColor = majorTMColor; } public void setMajorTMHeight(String majorTMHeight) { this.majorTMHeight = majorTMHeight; } public void setMinorTMNumber(String minorTMNumber) { this.minorTMNumber = minorTMNumber; } public void setMinorTMColor(String minorTMColor) { this.minorTMColor = minorTMColor; } public void setMinorTMHeight(String minorTMHeight) { this.minorTMHeight = minorTMHeight; } public void setDisplayValueDistance(String displayValueDistance) { this.displayValueDistance = displayValueDistance; } public void setTickValueDistance(String tickValueDistance) { this.tickValueDistance = tickValueDistance; } public void setGaugeStartAngle(String gaugeStartAngle) { this.gaugeStartAngle = gaugeStartAngle; } public void setGaugeEndAngle(String gaugeEndAngle) { this.gaugeEndAngle = gaugeEndAngle; } public void setPalette(String palette) { this.palette = palette; } public void setShowValue(String showValue) { this.showValue = showValue; } public void setNumberSuffix(String numberSuffix) { this.numberSuffix = numberSuffix; } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }
上面那一堆的注解来自jaxb的jar包,下哪些包我就不说了。估计应该能看懂个所以然吧,那些属性都是这个gaugeChart所需要的图形显示属性,不必去细究,它需要什么,我们按上面添加就是了,不过貌似没有get()方法,不需要这个。里面注解的像这样的@XmlElement(name = "annotationGroup") ,这个annotationGroup也是像GaugeChart这样的java对象,需要被定义。
接下来我们可以在action中调用了。
private String getXxxXml() { String template = getTemplate(); String chartXml = JAXBUtils.process(template, GaugeChart.class, new JAXBUtils.ChartFiller<GaugeChart>() { public void fill(final GaugeChart chart) { Dial dial1 = new Dial(); dial1.setValue(""); dial1.setRearExtension("10"); chart.addDials(dial1); } }); return chartXml; }
这样的一个方法返回的就是一个xml的string型对象了,我们只需要在页面拿到这个string型的xml ,就可以通过fusioncharts(当然是我这里用了fusioncharts)来调用它并显示相应的图形了。