spring mvc 集成velocity模板

spring mvc 集成velocity模板

 

  • spring mvc 

我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置。spring3 mvc可以认为已经100%零配置了(除了配置spring mvc-servlet.xml外)。

Spring MVC和Struts2的区别:
1. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。

2. 性能:spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。

3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。

4. 设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。

5. intercepter的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高。spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

6. 另外,spring3 mvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便,只需一个注解@ResponseBody ,然后直接返回响应文本即可。

等等。。。。。。

原文找不到了 ,找到再链接过去,这不过不是介绍的重点。
  • velocity模板

对 Java 程序员来说,最优秀的模版引擎无外乎 Velocity 和 FreeMarker 了。但是对一个尚未接触过这两个项目的人来说,就不知道该选择哪个,哪个才是最适合自己的。下面的内容来自 FreeMarker 网站上一个比较中肯的比较,尽管更多的是倾向于 FreeMarker :
相比较 FreeMarker 而言,Velocity 更加简单、轻量级,但它的功能却没有 FreeMarker 那么强大。
对于大部分的应用来说,使用 FreeMarker 比 Velocity 更简单,因为 Velocity 还必须编写一些自定义的toolbox类以及一遍遍重复的编写一些比较通用的模版代码,因此也就丧失了刚开始开发时更多的宝贵时间。另外使用工具类和变通的方法在模版引擎中似乎不是一个非常有效的做法。同时,Velocity 的做法使得在Velocity的模版中大量的跟 Java 对象进行交互,这违反了简单的原则,尽管你也可以将代码转入控制器中实现。当然,如果你像使用 Velocity 一样来使用 FreeMarker ,那么 FreeMarker 也可以跟 Velocity 一样简单。

等等。。。。。。

详细请看 这个也不是介绍的重点。

所需要包文件

spring mvc 集成velocity模板

  1. spring mvc 只是用到mvc所以只需要那8个包;
  2. velocity 用到2个包。
  • web.xml
<servlet>
    <servlet-name>mvc3</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/main-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc3</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

  

  • main-servlet.xml
<!-- velocity模板配置 -->
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath" value="WEB-INF/velocity/" />
        <property name="velocityProperties">
            <props>
                <prop key="input.encoding">UTF-8</prop><!-- 指定模板引擎进行模板处理的编码 -->
                <prop key="output.encoding">UTF-8</prop><!-- 指定输出流的编码 -->
                <prop key="contentType">text/html;charset=UTF-8</prop><!-- contentType -->
                <prop key="userdirective">com.tonyplan.web.velocity.CacheDirective</prop> <!--自定义标签 -->
            </props>
        </property>
    </bean>
 
    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="cache" value="false"></property><!--是否缓存模板-->
        <property name="order" value="10" />
        <property name="suffix" value=".vm"/>
        <property name="prefix" value="/screen/" />
        <property name="layoutUrl" value="layout/default.vm" />
        <property name="exposeSpringMacroHelpers" value="true" />
        <property name="dateToolAttribute" value="dateTool"/>
        <property name="numberToolAttribute" value="numberTool"/>
        <property name="toolboxConfigLocation" value="WEB-INF/velocity-tools.xml" />
        <property name="contentType" value="text/html;charset=UTF-8"></property>
    </bean>
  • 自定义标签 :com.tonyplan.web.velocity.CacheDirective
package com.tonyplan.web.velocity;
 
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Hashtable;
 
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.util.StringUtils;
 
import com.tonyplan.cache.CacheManager;
 
public class CacheDirective extends Directive {
 
    final static Hashtable<String,String> body_tpls = new Hashtable<String, String>();
     
    @Override
    public String getName() {
        return "cache";
    }
 
    @Override
    public int getType() {
        return BLOCK;
    }
 
    @Override
    public boolean render(InternalContextAdapter context, Writer writer, Node node)
            throws IOException, ResourceNotFoundException, ParseErrorException,
            MethodInvocationException {
        //获得缓存信息               
        Node body = node.jjtGetChild(2);   
        StringWriter sw = new StringWriter();         
        body.render(context, sw);       
        writer.write(sw.toString());
        return true;
        //获得缓存信息     
        /*SimpleNode sn_region = (SimpleNode) node.jjtGetChild(0);     
        String region = (String)sn_region.value(context);     
        SimpleNode sn_key = (SimpleNode) node.jjtGetChild(1);     
        Serializable key = (Serializable)sn_key.value(context);           
        Node body = node.jjtGetChild(2);*/ 
        //检查内容是否有变化    
        /*String tpl_key = key+"@"+region;     
        String body_tpl = body.literal();     
        String old_body_tpl = body_tpls.get(tpl_key);     
        String cache_html = null;//= CacheManager.get(String.class, region, key);     
        if(cache_html == null || !StringUtils.equals(body_tpl, old_body_tpl)){         
            StringWriter sw = new StringWriter();         
            body.render(context, sw);
            cache_html = sw.toString();         
            CacheHelper.set(region, key, cache_html);         
            body_tpls.put(tpl_key, body_tpl);     
        }     
        writer.write(cache_html);
        return true;*/     
 
    }
 
}
  • velocity-tools.xml
<?xml version="1.0" encoding="UTF-8"?>
<toolbox>
    <tool>
        <key>newstool</key>
        <class>com.tonyplan.web.velocity.NewsTool</class>
    </tool>
</toolbox>
  • com.tonyplan.web.velocity.NewsTool
package com.tonyplan.web.velocity;
 
import java.util.List;
 
import com.tonyplan.beans.CourseBean;
import com.tonyplan.dao.CourseDao;
 
public class NewsTool {
     
    public List<CourseBean> ListTopNews(int top){
        return CourseDao.getInstance().getList(1, top);
    }
     
    /** To test exception handling in templates. */
    public boolean whine() {
        throw new IllegalArgumentException();
    }
} 
  • velocity 宏定义 macro
#macro (writeTable $productList)  
    #set ($rowCount = 1)              
    #foreach($product in $productList)            
    #if ($rowCount % 2 == 0)  
        #set ($bgcolor = "#FFFFFF")  
    #else  
        #set ($bgcolor = "#CCCCCC")           
    #end  
        <tr> 
            <td bgcolor="$bgcolor">$product</td>
            <td bgcolor="$bgcolor">$product</td>
        </tr>                         
        #set ($rowCount = $rowCount + 1)  
    #end  
#end  
  • layout.vm  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
     <HEAD>
      <TITLE>$!page_title 测试layout页面</TITLE>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
      <meta http-equiv="Content-Language" content="zh-CN"/>
      <META NAME="Generator" CONTENT="EditPlus">
      <META NAME="Author" CONTENT="">
      <META NAME="Keywords" CONTENT="">
      <META NAME="Description" CONTENT="">
    $script
     </HEAD>
     <BODY>
        ------------------------------------
        <br>
        $screen_content
 
     </BODY>
</HTML>
  • pageFooter.vm
Copyright © 2012
  • pageFooter1.vm
#set ($innerVar = "This is an inner variable")
Copyright © $companyName 2012
  • index.vm
#set($layout="layout/layout.vm")
#set($page_title="测试首页")
#set($products = ["one", "two", "three"]) 
#set($companyName = "Tony Law")
#parse("macro/writeTable.vm")
#define($script)
## custom script here
<script src="script/jquery.js" type="text/javascript"></script> 
#end
    Here we use a custom tool: $toytool.message
    <div>
         <ul>  
            #foreach($CourseBean in $newstool.ListTopNews(10)) 
            <li>      
                ${CourseBean.name}
            </li>  
            #end  
         </ul>
    </div>
    #set($region = "news")
    #set($key = "home")
    #cache("CACHE_$region",$key)
    #end
    <div>
    #cache("News","home")
    ## 读取数据库中最新新闻并显示
    <ul>  
        #foreach($CourseBean in $newstool.ListTopNews(10)) 
        <li>      
            ${CourseBean.name}
        </li>  
        #end  
    </ul>
    #end
    </div>
 
<table>
#writeTable($products) 
</table>
<br>
#parse("layout/pageFooter1.vm")
<br>
$innerVar
<br>
#include("layout/pageFooter.vm")

以上说明

  1. $layout 变量默认配置是<property name="layoutUrl" value="layout/default.vm" />;改变布局模板#set($layout="layout/layout.vm")
  2. #parse 加入动态vm
  3. #include 加入静态vm
  4. #cache自定义标签,配置<prop key="userdirective">com.tonyplan.web.velocity.CacheDirective</prop> <!--自定义标签 -->
  5. #set设置变量
  6. #define

等等。。。。。。

更多参考velocity 文档!