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

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


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



 

具体代码如下:

 

后台java生成设置代码

Map<Long,String> map = new HashMap<Long,String>();
         map.put(101L,"aaa");
         map.put(102L,"bbb");
         context.put("longMap",map);
         
         Map<Integer,String> intMap = new HashMap<Integer,String>();
         intMap.put(101,"aaa");
         intMap.put(102,"bbb");
         context.put("intMap",intMap);

vm文件输出代码:

#foreach($item in $longMap.entrySet())
   $item.key $item.value
#end


$longMap.get(101)



#foreach($item in $intMap.entrySet())
   $item.key $item.value
#end

$intMap.get(101)

打印输出如下:

102 bbb 101 aaa $longMap.get(101) 102 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处理整数型的转换的:

public class ASTIntegerLiteral extends SimpleNode
{

    // This may be of type Integer, Long or BigInteger
    private Number value = null;

    /**
     * @param id
     */
    public ASTIntegerLiteral(int id)
    {
        super(id);
    }

    /**
     * @param p
     * @param id
     */
    public ASTIntegerLiteral(Parser p, int id)
    {
        super(p, id);
    }


    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
     */
    public Object jjtAccept(ParserVisitor visitor, Object data)
    {
        return visitor.visit(this, data);
    }

    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
     */
    public Object init( InternalContextAdapter context, Object data)
        throws TemplateInitException
    {
        /*
         *  init the tree correctly
         */

        super.init( context, data );

        /**
         * Determine the size of the item and make it an Integer, Long, or BigInteger as appropriate.
         */
         String str = getFirstToken().image;
         try
         {
             value = new Integer( str );
         }
         catch ( NumberFormatException E1 )
         {
            try
            {

                value = new Long( str );

            }
            catch ( NumberFormatException E2 )
            {

                // if there's still an Exception it will propogate out
                value = new BigInteger( str );
            }
        }

        return data;
    }

    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
     */
    public Object value( InternalContextAdapter context)
    {
        return value;
    }

}

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

 

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

 

同样对于浮点型也一样:

ASTFloatingPointLiteral.java类

public class ASTFloatingPointLiteral extends SimpleNode
{

    // This may be of type Double or BigDecimal
    private Number value = null;

    /**
     * @param id
     */
    public ASTFloatingPointLiteral(int id)
    {
        super(id);
    }

    /**
     * @param p
     * @param id
     */
    public ASTFloatingPointLiteral(Parser p, int id)
    {
        super(p, id);
    }


    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
     */
    public Object jjtAccept(ParserVisitor visitor, Object data)
    {
        return visitor.visit(this, data);
    }

    /**
     *  Initialization method - doesn't do much but do the object
     *  creation.  We only need to do it once.
     * @param context
     * @param data
     * @return The data object.
     * @throws TemplateInitException
     */
    public Object init( InternalContextAdapter context, Object data)
        throws TemplateInitException
    {
        /*
         *  init the tree correctly
         */

        super.init( context, data );

        /**
         * Determine the size of the item and make it a Double or BigDecimal as appropriate.
         */
         String str = getFirstToken().image;
         try
         {
             value = new Double( str );

         } catch ( NumberFormatException E1 )
         {

            // if there's still an Exception it will propogate out
            value = new BigDecimal( str );

        }

        return data;
    }

    /**
     * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
     */
    public Object value( InternalContextAdapter context)
    {
        return value;
    }


}

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

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

 

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


posted @ 2012-08-08 21:08  MXi4oyu  阅读(351)  评论(0编辑  收藏  举报