velocity对set 类型的支持 map get输出问题分析

今天使用velocity在java后台渲染一个map<Long,String>对象到vm模板上,通过get(111)获取不到map的对象的值分析。

 

这是velocity1.6.4的处理,以后版本是不是解决了这个问题可以再查,个人认为在vm文件支持跟java一样加个L表示long之类的处理应该不难。

 

 

 

具体代码如下:

 

后台java生成设置代码

[java] view plaincopy

  1. Map<Long,String> map = new HashMap<Long,String>();  
  2.          map.put(101L,"aaa");  
  3.          map.put(102L,"bbb");  
  4.          context.put("longMap",map);  
  5.            
  6.          Map<Integer,String> intMap = new HashMap<Integer,String>();  
  7.          intMap.put(101,"aaa");  
  8.          intMap.put(102,"bbb");  
  9.          context.put("intMap",intMap);  

 

vm文件输出代码:

[java] view plaincopy

  1. #foreach($item in $longMap.entrySet())  
  2.    $item.key $item.value  
  3. #end  
  4.   
  5.   
  6. $longMap.get(101)  
  7.   
  8.   
  9.   
  10. #foreach($item in $intMap.entrySet())  
  11.    $item.key $item.value  
  12. #end  
  13.   
  14. $intMap.get(101)  

 

打印输出如下:

[java] view plaincopy

  1. 102 bbb 101 aaa $longMap.get(101102 bbb 101 aaa aaa   

 

可以看到使用Map<Long,String>的map类型,通过$longMap.get(101)获取不到值,而使用Map<Integer,String>类型的map,通过$intMap.get(101)能够正常取到值aaa,而通过entrySet来遍历都没有问题,为什么会这样呢?

 

 

那就查看velocity的源码,查看这块的处理了,

 

最终是在velocity中通过#set($a=101)或者直接使用$intMap.get(101)是,会把101生成存储到一个变量中,而变量的类型当然根据这个值来了,不过101当然处理成整数型,而'aaa'则处理成字符串,101.1处理成浮点型。

 

但是整数型有short,int,long,BigInteger,浮点型有float,double,BigDecimal等,那么怎么处理值的类型了。

 

请看velocity的下面两个类就知道了:

 

ASTIntegerLiteral.java处理整数型的转换的:

[java] view plaincopy

  1. public class ASTIntegerLiteral extends SimpleNode  
  2. {  
  3.   
  4.     // This may be of type Integer, Long or BigInteger  
  5.     private Number value = null;  
  6.   
  7.     /** 
  8.      * @param id 
  9.      */  
  10.     public ASTIntegerLiteral(int id)  
  11.     {  
  12.         super(id);  
  13.     }  
  14.   
  15.     /** 
  16.      * @param p 
  17.      * @param id 
  18.      */  
  19.     public ASTIntegerLiteral(Parser p, int id)  
  20.     {  
  21.         super(p, id);  
  22.     }  
  23.   
  24.   
  25.     /** 
  26.      * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object) 
  27.      */  
  28.     public Object jjtAccept(ParserVisitor visitor, Object data)  
  29.     {  
  30.         return visitor.visit(this, data);  
  31.     }  
  32.   
  33.     /** 
  34.      * @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object) 
  35.      */  
  36.     public Object init( InternalContextAdapter context, Object data)  
  37.         throws TemplateInitException  
  38.     {  
  39.         /* 
  40.          *  init the tree correctly 
  41.          */  
  42.   
  43.         super.init( context, data );  
  44.   
  45.         /** 
  46.          * Determine the size of the item and make it an Integer, Long, or BigInteger as appropriate. 
  47.          */  
  48.          String str = getFirstToken().image;  
  49.          try  
  50.          {  
  51.              value = new Integer( str );  
  52.          }  
  53.          catch ( NumberFormatException E1 )  
  54.          {  
  55.             try  
  56.             {  
  57.   
  58.                 value = new Long( str );  
  59.   
  60.             }  
  61.             catch ( NumberFormatException E2 )  
  62.             {  
  63.   
  64.                 // if there's still an Exception it will propogate out  
  65.                 value = new BigInteger( str );  
  66.             }  
  67.         }  
  68.   
  69.         return data;  
  70.     }  
  71.   
  72.     /** 
  73.      * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter) 
  74.      */  
  75.     public Object value( InternalContextAdapter context)  
  76.     {  
  77.         return value;  
  78.     }  
  79.   
  80. }  

 

请看init方法,会尝试先把整数转换成Integer类型,转换失败再尝试转换成Long,再转换失败再转换成BigInteger,所以101肯定先转换成Integer成功了。

 

而且velocity没有语法直接直接设置类型为Long型。

 

同样对于浮点型也一样:

ASTFloatingPointLiteral.java类

[java] view plaincopy

  1. public class ASTFloatingPointLiteral extends SimpleNode  
  2. {  
  3.   
  4.     // This may be of type Double or BigDecimal  
  5.     private Number value = null;  
  6.   
  7.     /** 
  8.      * @param id 
  9.      */  
  10.     public ASTFloatingPointLiteral(int id)  
  11.     {  
  12.         super(id);  
  13.     }  
  14.   
  15.     /** 
  16.      * @param p 
  17.      * @param id 
  18.      */  
  19.     public ASTFloatingPointLiteral(Parser p, int id)  
  20.     {  
  21.         super(p, id);  
  22.     }  
  23.   
  24.   
  25.     /** 
  26.      * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object) 
  27.      */  
  28.     public Object jjtAccept(ParserVisitor visitor, Object data)  
  29.     {  
  30.         return visitor.visit(this, data);  
  31.     }  
  32.   
  33.     /** 
  34.      *  Initialization method - doesn't do much but do the object 
  35.      *  creation.  We only need to do it once. 
  36.      * @param context 
  37.      * @param data 
  38.      * @return The data object. 
  39.      * @throws TemplateInitException 
  40.      */  
  41.     public Object init( InternalContextAdapter context, Object data)  
  42.         throws TemplateInitException  
  43.     {  
  44.         /* 
  45.          *  init the tree correctly 
  46.          */  
  47.   
  48.         super.init( context, data );  
  49.   
  50.         /** 
  51.          * Determine the size of the item and make it a Double or BigDecimal as appropriate. 
  52.          */  
  53.          String str = getFirstToken().image;  
  54.          try  
  55.          {  
  56.              value = new Double( str );  
  57.   
  58.          } catch ( NumberFormatException E1 )  
  59.          {  
  60.   
  61.             // if there's still an Exception it will propogate out  
  62.             value = new BigDecimal( str );  
  63.   
  64.         }  
  65.   
  66.         return data;  
  67.     }  
  68.   
  69.     /** 
  70.      * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter) 
  71.      */  
  72.     public Object value( InternalContextAdapter context)  
  73.     {  
  74.         return value;  
  75.     }  
  76.   
  77.   
  78. }  

 

 先尝试转换成Float,失败再转换成Double,再失败再转换成BigDecimal。

velocity语法也没有设置为double型的设置。

 

所以就会出现上面那个case了,$map.get(101) map存的是long跟string的键值对,用int型取肯定取不到,因为long跟int的hashcode不一样,这个可以查看map的处理。

posted @ 2016-01-08 12:07  蔷薇骑士  阅读(392)  评论(0编辑  收藏  举报