使用高性能xml序列化框架jibx作为spring mvc的xml view
发布时间:2020-12-15 23:25:29 所属栏目:百科 来源:网络整理
导读: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
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 */ public class JibxMarshallerFactory implements InitializingBean { private static Logger logger = LoggerFactory.getLogger(JibxMarshallerFactory.class); private static final String BINDING_NAME = "Binding"; private List<Class<?>> targetClassList; private Map<Class<?>, JibxMarshaller> jibxCache = new HashMap<Class<?>, JibxMarshaller>(); @Override public void afterPropertiesSet() throws Exception { if (targetClassList != null) { for (Class<?> clazz : targetClassList) { JibxMarshaller jibxMarshaller = new JibxMarshaller(); jibxMarshaller.setTargetClass(clazz); jibxMarshaller.setBindingName(BINDING_NAME); jibxMarshaller.afterPropertiesSet(); jibxCache.put(clazz, jibxMarshaller); } } else { if (logger.isInfoEnabled()) { logger.info("JiBX映射目标类没有设置。运行时将无法获得JibxMarshaller实例。"); } } } public List<Class<?>> getTargetClassList() { return targetClassList; } public void setTargetClassList(List<Class<?>> targetClassList) { this.targetClassList = targetClassList; } public JibxMarshaller getJibxMarshaller(Class<?> targetClass) { return jibxCache.get(targetClass); } } 因为jibx对所有需要序列化的JavaBean都要事先注册,所以你要事先配置JibxMarshallerFactory,将所有要序列化的类都配置进去。 例如: <bean id="jibxMarshallerFactory" class="com.vteba.service.xml.jibx.JibxMarshallerFactory"> <property name="targetClassList"> <list> <value>com.vteba.service.xml.jibx.Customer</value> </list> </property> </bean> 绝对原创,转载请注明出处。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |