package org.springframework.web.servlet.view.xml;
import java.io.ByteArrayOutputStream; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.stream.StreamResult; import org.springframework.beans.BeansException; import org.springframework.oxm.Marshaller; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; import org.springframework.web.servlet.view.AbstractView; public class XmlMarshallerView extends AbstractView { /** * Default content type. Overridable as bean property. */ public static final String DEFAULT_CONTENT_TYPE = "application/xml"; private Marshaller marshaller; private JibxMarshallerFactory jibxMarshallerFactory; private String modelKey; /** * Constructs a new {@code MarshallingView} with no {@link Marshaller} set. The marshaller must be set after * construction by invoking {@link #setMarshaller(Marshaller)}. */ public XmlMarshallerView() { setContentType(DEFAULT_CONTENT_TYPE); setExposePathVariables(false); } /** * Constructs a new {@code MarshallingView} with the given {@link Marshaller} set. */ public XmlMarshallerView(Marshaller marshaller) { Assert.notNull(marshaller, "'marshaller' must not be null"); setContentType(DEFAULT_CONTENT_TYPE); this.marshaller = marshaller; setExposePathVariables(false); } public void setJibxMarshallerFactory(JibxMarshallerFactory jibxMarshallerFactory) { this.jibxMarshallerFactory = jibxMarshallerFactory; } /** * Sets the {@link Marshaller} to be used by this view. */ public void setMarshaller(Marshaller marshaller) { Assert.notNull(marshaller, "'marshaller' must not be null"); this.marshaller = marshaller; } /** * Set the name of the model key that represents the object to be marshalled. If not specified, the model map will be * searched for a supported value type. * * @see Marshaller#supports(Class) */ public void setModelKey(String modelKey) { this.modelKey = modelKey; } @Override protected void initApplicationContext() throws BeansException { if (marshaller == null && jibxMarshallerFactory == null) { throw new RuntimeException("Property 'marshaller' or 'jibxMarshallerFactory', at least one is required"); } } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { Object toBeMarshalled = locateToBeMarshalled(model); if (toBeMarshalled == null) { throw new ServletException("Unable to locate object to be marshalled in model: " + model); } ByteArrayOutputStream bos = new ByteArrayOutputStream(2048); marshaller.marshal(toBeMarshalled, new StreamResult(bos)); setResponseContentType(request, response); response.setContentLength(bos.size()); FileCopyUtils.copy(bos.toByteArray(), response.getOutputStream()); } /** * Locates the object to be marshalled. The default implementation first attempts to look under the configured * {@linkplain #setModelKey(String) model key}, if any, before attempting to locate an object of {@linkplain * Marshaller#supports(Class) supported type}. * * @param model the model Map * @return the Object to be marshalled (or {@code null} if none found) * @throws ServletException if the model object specified by the {@linkplain #setModelKey(String) model key} is not * supported by the marshaller * @see #setModelKey(String) */ protected Object locateToBeMarshalled(Map<String, Object> model) throws ServletException { if (this.modelKey != null) { Object o = model.get(this.modelKey); if (o == null) { throw new ServletException("Model contains no object with key [" + modelKey + "]"); } checkMarshaller(o); if (!this.marshaller.supports(o.getClass())) { throw new ServletException("Model object [" + o + "] retrieved via key [" + modelKey + "] is not supported by the Marshaller"); } return o; } for (Object o : model.values()) { if (o != null) { checkMarshaller(o); if (this.marshaller.supports(o.getClass())) { return o; } } } return null; } /** * check the marshaller is null or not * @param object if the marshaller is null, will query from jibxMarshallerFactory by object */ protected void checkMarshaller(Object object) { if (marshaller == null) { marshaller = jibxMarshallerFactory.getJibxMarshaller(object.getClass()); } }}
这个类参考了spring mvc的MarshallingView。不同就是引入了JibxMarshallerFactory。因为jibx 要对每个要序列化的类进行字节码增强。如果使用xstream等xml框架则不需要使用这个类。当然使用也是可以的。可以直接使用MarshallingView。
package com.vteba.service.xml.jibx;import java.util.HashMap;import java.util.List;import java.util.Map;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.InitializingBean;import org.springframework.oxm.jibx.JibxMarshaller;/** * JibxMarshaller Factory。 * @author yinlei * date 2013-8-1 下午8:10:45 */publicclassJibxMarshallerFactoryimplementsInitializingBean{ privatestaticLogger logger =LoggerFactory.getLogger(JibxMarshallerFactory.class); privatestaticfinalString BINDING_NAME ="Binding"; privateList> targetClassList; privateMap ,JibxMarshaller> jibxCache =newHashMap ,JibxMarshaller>(); @Override publicvoid afterPropertiesSet()throwsException{ if(targetClassList !=null){ for(Class clazz : targetClassList){ JibxMarshaller jibxMarshaller =newJibxMarshaller(); jibxMarshaller.setTargetClass(clazz); jibxMarshaller.setBindingName(BINDING_NAME); jibxMarshaller.afterPropertiesSet(); jibxCache.put(clazz, jibxMarshaller); } }else{ if(logger.isInfoEnabled()){ logger.info("JiBX映射目标类没有设置。运行时将无法获得JibxMarshaller实例。"); } } } publicList > getTargetClassList(){ return targetClassList; } publicvoid setTargetClassList(List > targetClassList){ this.targetClassList = targetClassList; } publicJibxMarshaller getJibxMarshaller(Class targetClass){ return jibxCache.get(targetClass); }}
因为jibx对所有需要序列化的JavaBean都要事先注册,所以你要事先配置JibxMarshallerFactory,将所有要序列化的类都配置进去。
例如:
com.vteba.service.xml.jibx.Customer
绝对原创,转载请注明出处。