初识模板框架【Velocity】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haoyutc/article/details/83751741

因最近项目中涉及到javabean 2 XML的转换,比较多,但是又不涉及具体的业务逻辑,请求系统与目标系统间进行数据透传,两个系统间的报文字段都不一致,需要进行映射转换,所以考虑再三,xml2bean选择了xpath实现,然后再把bean转换为对应的xml,此过程考虑几个不同的模板引擎:FreeMarker、Thymeleaf、Enjoy、Velocity,对比了几个的优缺点之后,选择了Velocity,比较轻巧,效率高,性能还不错,最重要是满足当前的项目需要。

【xpath】

package com.xx.xxx.api.xml.xpath;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;


/**
 * xml path 映射
 * @author zenghaom
 *
 */
public class XmlPathUtil {
	
	
	/**
	 * xml字符串转换Object
	 * @param xml
	 * @param clz 转换对象class
	 * @return
	 * @throws Exception
	 */
	public static <T> T convert(String xml,Class<T> clz) throws Exception{
		InputStream in = null;
		try {
			in = IOUtils.toInputStream(xml);
			return convert(in,clz);
		}finally {
			IOUtils.closeQuietly(in);
		}
	}
	
	/**
	 * xml字符串转换Object
	 * @param xml xml字符串
	 * @param clz 转换对象class
	 * @param ns 命名空间
	 * @param alisa 别名
	 * @return
	 * @throws Exception
	 */
	public static <T> T convert(String xml,Class<T> clz,String ns,String alisa) throws Exception{
		InputStream in = null;
		try {
			in = IOUtils.toInputStream(xml);
			return convert(in,clz,ns,alisa);
		}finally {
			IOUtils.closeQuietly(in);
		}
	}
	
	/**
	 * inputStream xml转Object
	 * @param in
	 * @param clz
	 * @return
	 * @throws Exception
	 */
	public static <T> T convert(InputStream in,Class<T> clz) throws Exception {
			Document doc = new SAXReader().read(in);
			return convert(doc,clz);
	}
	
	/**
	 * inputStream xml转Object
	 * @param in
	 * @param clz
	 * @param ns 命名空间
	 * @param alisa 别名
	 * @return
	 * @throws Exception
	 */
	
	public static <T> T convert(InputStream in,Class<T> clz,String ns,String alisa) throws Exception {
		SAXReader saxReader = new SAXReader();
		Document doc = saxReader.read(in);
		Map<String,String> map = new HashMap<>();  
	    map.put(alisa,ns); 
	    saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
		return convert(doc,clz);
	}
	
	
	
	/**
	 * document 转 Object
	 * @param doc
	 * @param clz
	 * @return
	 * @throws Exception 
	 */
	public static <T> T convert(Document doc,Class<T> clz) throws Exception {
		T t = clz.newInstance();
		getValue(doc, t, clz,"");
		return t;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void getValue(Document doc,Object obj,Class clz,String parentPath) throws Exception{
		
		Map<Field,XmlField> xmlType = XmlFieldBeanFactory.getForClass(clz);
		
		for(Field field : xmlType.keySet()) {
			XmlField xmlField = xmlType.get(field);
			Object value = field.getType().newInstance();
			BeanUtils.setProperty(obj, field.getName(), value);
			if(!xmlField.haveSon()) {
				if(isCollection(field.getType())) {
					Collection cl = (Collection) value;
					List<Node> nodes = doc.selectNodes(parentPath+xmlField.path());
					if(CollectionUtils.isNotEmpty(nodes)) {
						for (Node node : nodes) {
							cl.add(node.getText());
						}
					}
					
				}else {
					if(xmlField.isText()) {
						Node node = doc.selectSingleNode(parentPath+xmlField.path());
						if(node!=null) {
							BeanUtils.setProperty(obj,field.getName() , node.getText());
						}
					}else {
						BeanUtils.setProperty(obj,field.getName() , doc.valueOf(parentPath+xmlField.path()));
					}
				}
			}else {
				if(isCollection(field.getType())){
					Collection cl = (Collection) value;
					List<Node> nodes = doc.selectNodes(parentPath+xmlField.path());
					if(CollectionUtils.isNotEmpty(nodes)) {
						for (Node node : nodes) {
							 Type genericType = field.getGenericType();                   
							  if(genericType == null) 
								  return;                    // 如果是泛型参数的类型                    
							  if(genericType instanceof ParameterizedType){                        
								  ParameterizedType pt = (ParameterizedType) genericType;//得到泛型里的class类型对象                     
								  Class<?> accountPrincipalApproveClazz = (Class<?>)pt.getActualTypeArguments()[0];
								  Object v = accountPrincipalApproveClazz.newInstance();
								  cl.add(v);
								  getValue(node.getDocument(), v,accountPrincipalApproveClazz,node.getUniquePath());
							  }
						}
					}
				}else {
					  Node node = doc.selectSingleNode(xmlField.path());
					  if(node != null) {
						  Object v = field.getType().newInstance();
						  getValue(doc, v,field.getType(),node.getUniquePath());
					  }
					 
				}
			}
		}

	}
	
	
	 private static boolean isCollection(Class<?> type) {
		    return Collection.class.isAssignableFrom(type);
	 }
	

}

package com.xx.xxx.api.xml.xpath;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
 * 缓存解析过的xmlField
 * @author zenghaom
 *
 */
public class XmlFieldBeanFactory {
	

	private final static ConcurrentMap<Class<?>, Map<Field,XmlField>> xmlTypeMap = new ConcurrentHashMap<Class<?>,Map<Field,XmlField>>();
	
	public static Map<Field,XmlField> getForClass(Class<?> type){
		Map<Field,XmlField> xmlType = xmlTypeMap.get(type);
		if(xmlType == null) {
			xmlType = getXmlType(type);
			xmlTypeMap.put(type, xmlType);
		}
		return xmlType;
	}
	
	private static Map<Field,XmlField> getXmlType(Class<?> type){
		
		Map<Field,XmlField> xmlType = new HashMap<>();
		while (type != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
		      for (Field field : type .getDeclaredFields()) {  
		    	  if(field.isAnnotationPresent(XmlField.class)){//判断成员变量是否有注解
		    		  xmlType.put(field, field.getAnnotation(XmlField.class));
		    	  }
		    	  
		    	 }
		      type = type.getSuperclass(); //得到父类,然后赋给自己
		}

		return xmlType;
	}
	
}

package com.xx.xxx.api.xml.xpath;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * 用于注解字段对应的xpath,进行解析xml
 * @author zenghaom
 *
 */

@Retention(RUNTIME)
@Target(FIELD)
public @interface XmlField {
	/**
	 * xml对应的xPath路径
	 * @return
	 */
	String path();
	/**
	 * 是否嵌套对象
	 * @return
	 */
	boolean haveSon() default false;
	
	/**
	 * 取属性值
	 * @return
	 */
	boolean isText() default true;
}

【Velocity】

package com.xx.xxx.api.xml.velocity;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * <pre>
 * <b>JavaBean convert to xml  by VelocityEngine</b>
 * <b>Description:</b>
 *
 * <b>Author:</b> Mike•Tran
 * <b>Date:</b> 2018年10月10日  17:52
 * <b>Copyright:</b> Copyright 2018 xxx-xxxx.com.cn. All rights reserved.
 * <b>Changelog:</b>
 *   Ver   Date                    Author                Detail
 *   ----------------------------------------------------------------------
 *   1.0   2018年10月10日  17:52   Mike  new file.
 *
 * </pre>
 */
public class VelocityXmlUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(VelocityXmlUtil.class);
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static Properties p = new Properties();
    static {
        p.setProperty(Velocity.RESOURCE_LOADER, "class");
        p.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
        p.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        p.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        p.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        p.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogChute");//关闭日志
    }
    /**
     *  pojo转换成xml 默认编码UTF-8
     *
     * @author Mike
     * @date 2018/10/11 18:03
     * @param map
     * @param templateFilePathAndName 资源文件路径:比如模板放在resources/template/example.vm,则basePath="template/example.vm"
     * @return   java.lang.String
     */
    public static String convertBeanToXml(Map<String, Object> map, String templateFilePathAndName) {
        return convertBeanToXml(map, templateFilePathAndName, DEFAULT_ENCODING);
    }
    /**
     *  pojo转换成xml  自定义编码
     *
     * @author Mike
     * @date 2018/10/11 18:03
     * @param map
     * @param templateFilePathAndName
     * @return   java.lang.String
     */
    public static String convertBeanToXml(Map<String, Object> map, String templateFilePathAndName, String encoding) {

        try {
            //Velocity 引擎初始化(singleton)
            Velocity.init(p);
            //实例化一个VelocityContext
            VelocityContext velocityContext = new VelocityContext(map);

            //实例化一个StringWriter
            StringWriter stringWriter = new StringWriter();

            Template template = Velocity.getTemplate(templateFilePathAndName, encoding);
            template.merge(velocityContext, stringWriter);
            stringWriter.flush();
            stringWriter.close();
            return stringWriter.toString();
        } catch (Exception e) {
            LOGGER.error("VelocityXmlUtil_convertBeanToXml_Exception:{}", e.getMessage());
        }
        return "";
    }
}

  • Velocity依赖
	<!--velocity start-->
	  <dependency>
		  <groupId>org.apache.velocity</groupId>
		  <artifactId>velocity</artifactId>
		  <version>1.7</version>
	  </dependency>
	  <dependency>
		  <groupId>org.apache.velocity</groupId>
		  <artifactId>velocity-tools</artifactId>
		  <version>2.0</version>
	  </dependency>

猜你喜欢

转载自blog.csdn.net/haoyutc/article/details/83751741