Java模板引擎 FreeMarker

概念

介绍

特性

优势

不足

一个小Demo

概念

FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。它是为Java程序员提供的一个开发包。它不是面向最终用户的,而是为程序员提供的一款可以嵌入他们所开发产品的应用程序。

介绍

那么,FreeMarker是一款怎样的工具呢?FreeMarker实际上是被设计用来生成HTML Web页面,尤其是通过实现了基于MVC模式的Java Servlet应用程序。使用MVC模式的动态页面的设计构思使得你可以将前端设计师从程序员中分离出来。所有人各司其职,发挥其最擅长的一面。

网页设计师可以改写页面的显示效果而不受程序员编译代码的影响,因为应该程序的逻辑和页面设计已经被分开了。页面模板代码不会收到复杂程序代码的影响。这种分离的思想即便对一个程序员和页面设计师是同一个人的项目来说也都是非常有用的,因为分离使得代码保持简洁而且易于维护。

尽管FreeMarker也拥有一些编程能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)。

FreeMarker不是一个Web应用框架,而适合作为Web应用框架的一个组件,但是FreeMarker引擎本身并不知道HTTP协议或Java Servlet的存在。它仅仅来生成文本内容。既然是这样,它也非常适用于非Web应用程序的开发环境。知识要注意的是,我们使用FreeMarker作为视图层的组件,是为了给诸如Struts这样的Model2应用框架提供现成的解决方案,你也可以在模板中使用JSP标记库。

特性

通用目标

易于嵌入到你的产品中,轻量级,不需要Servlet环境

能够生成各种文本:HTML、XML、RTF、Java源代码等等

插件式模板载入器,可以从任何源载入模板,如本地文件、数据库等等

你可以按自己所需生成文本,保存到本地文件,作为Email发送,从Web应用程序发送它返回给Web浏览器

强大的模板语言

在模板中创建和改变变量

命名的宏,可以具有位置参数和嵌套内容

几乎在任何地方都可以使用复杂表达式来指定值

所有常用的指令,include、if/elseif/else、循环结构

名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突

输出转换块,在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等,你可以定义自己的转换

通用数据模型

FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示

你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等),告诉模板开发者使用方法,使其不受技术细节的打扰

为Web准备

支持JSP标记库

能够集成到Model2 Web应用框架中作为JSP的替代

在模板语言中内建处理典型Web相关任务(如HTML转义)的结构

为MVC模式设计,分离可视化设计和应用程序逻辑,分离页面设计师和程序员

智能的国际化和本地化

数字格式本地化敏感

多种不同语言的相同模板

日期和时间格式本地化敏感

字符集智能化(内部使用UNICODE)

非US字符集可以用作标识(如变量名)

强大的XML处理能力

在模板中清楚和直觉的访问XML对象模型

<#recurse>和<#visit>指令用于递归遍历XML树

优势

可以彻底的分离表现层和业务逻辑

使用JSP开发过程中,在页面中大量的存在业务逻辑代码,使得页面的内容非常混乱,在后期大量的修改维护过程中就变得非常的困难。

FreeMarker不支持Java脚本代码,FreeMarker的原理是,模板+数据模型=输出。模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。

可以提高开发效率

在以往的开发中,使用的都是JSP页面来展示数据的,即所谓的表现层。我们都知道,JSP在第一次执行的时候需要转换成Servlet类,开发阶段进行功能调试时,需要频繁的修改JSP,每次修改都要编译和转换,那么试想一下,一天中我们浪费在程序编译的时间有多少。

相对于JSP来说,FreeMarker模板技术不存在编译和转换的问题,所以就不会存在上述问题。而且开发过程中,我们再不必等待界面设计开发人员完成页面原型后,我们再来开发程序。

而且,一些特定的系统,比如OA工作流系统中,就需要动态生成表单技术,这就为其提供了很好的实现依据。使得在整个流程的进行中,生成不同的表单就简单了很多。

使得开发过程中的人员分工更加明确

以往用JSP显示数据时,一些程序员并不熟悉界面设计技术,反之界面开发人员,也并不熟悉程序语言。对两者而言,交替性的工作本身就有难度。有时候稍有不慎,可能会将整个页面元素删除或去掉了某个程序符号,使得页面走样或程序错误,这样就需要双方相互沟通协作,解决出现的问题。有时候因为项目中的时间、任务量等因素的存在,可能这个工作就由一个人来完成,这样就可能加大某一方开发人员的工作量。

使用FreeMarker后,作为界面开发人员,只专心创建HTML文件、图像以及Web页面的其他可视化方面,不用理会数据;而程序开发人员则专注于系统实现,负责为页面准备要显示的数据。

不足

在修改模板后,可能会看到已经过期的数据

使用FreeMarker模板技术,生成静态的HTML页面后,如果一旦模板改变,而没有及时更新模板生成的HTML页面的话,用户看到的就是过期的数据。 

FreeMarker的变量必须有值

FreeMarker模板技术在应用过程中,FreeMarker中的变量必须要赋值,如果不赋值,那么就会抛出异常。FreeMarker没有一个默认的null处理,甚至也不接受一个null值。想避免错误就要应用if/elseif/else 指令进行判段,如果对每一个变量都判断的话,那么则反而增加了编程的麻烦。 

FreeMarker的Map限定Key必须是String,其他数据类型无法操作

Map问题,即FreeMarker中不能支持非String的Key值,这样在进行一些复杂迭代时就需要作一些其他的转换,如将一个Map拆分为两个或多个Map。

FreeMarker不支持集群应用

为了编成的方便性,把序列化的东西都放到了Session中,如Session,request等,在开发的过程中确实方便,但如果将应用放到集群中,就会出现错误。 

一个小Demo

首先,需要下载FreeMarker的jar包,这里提供一个下载链接:freemarker.jar

然后,将这个freemarker.jar放到Web项目的 WebRoot\WEB-INF\lib 目录下

最后,我把自己写的测试类贴出来,分享一下。

FreemarkerTest类 代码

import java.io.BufferedWriter;  
import java.io.File;  
import java.io.FileWriter;  
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.HashMap;  
import java.util.Map;  
  
import freemarker.template.Configuration;  
import freemarker.template.DefaultObjectWrapper;  
import freemarker.template.Template;  
import freemarker.template.TemplateException;  
import freemarker.template.TemplateExceptionHandler;  
import junit.framework.TestCase;  
  
public class FreemarkerTest extends TestCase {  
  
    private String dir = "E:/.../OA/TestTotal/src/com/bjsxt/oa/freemarker";  
  
    public void testFreemarker() {  
        Configuration cfg = new Configuration();  
  
        try {  
            // 从哪里加载模板文件  
            cfg.setDirectoryForTemplateLoading(new File(dir));  
              
            // 定义模版的位置,从类路径中,相对于FreemarkerManager所在的路径加载模版  
            // cfg.setTemplateLoader(new ClassTemplateLoader(FreemarkerManager.class, "templates"))  
  
            // 设置对象包装器  
            cfg.setObjectWrapper(new DefaultObjectWrapper());  
  
            // 设置异常处理器  
            cfg  
                    .setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);  
  
            // 定义数据模型  
            Map root = new HashMap();  
            root.put("abc", "世界,你好");  
  
            // 通过freemarker解释模板,首先需要获得Template对象  
            Template template = cfg.getTemplate("test.ftl");  
  
            // 定义模板解释完成之后的输出  
            PrintWriter out = new PrintWriter(new BufferedWriter(  
                    new FileWriter(dir+"/out.txt")));  
              
            try {  
                // 解释模板  
                template.process(root, out);  
            } catch (TemplateException e) {  
                e.printStackTrace();  
            }  
  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

下面是定义的模板 test.ftl

test.flt 代码

[html]

<span style="font-family:Microsoft YaHei;">第一个测试程序:${abc}</span>  

最后运行的结果如下

输出了out.txt文件,out.txt文件中的内容如下:

[html]

<span style="font-family:Microsoft YaHei;">第一个测试程序:世界,你好</span> 

========

Velocity入门示例

一、前言                          

  Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力。而且Velocity被移植到不同的平台上,如.Net的NVelocity和js的Velocity.js,虽然各平台在使用和实现上略有差别,但大部分语法和引擎核心的实现是一致的,因此学习成本降低不少哦。

  最好的学习资源——官网:http://velocity.apache.org/

  本系列打算采用如下结构对Velocity进行较为全面的学习,若有不妥或欠缺望大家提出,谢谢。

  1. 入门示例

  2. VTL语法详解

  3. 模板与宿主环境通信

  4. 基础配置项

  5. 深入模板引擎及调优配置

二、入门示例                        

  示例结果是生成如下的html表单:

<form action="./submit">
<div>
  <label for="title">标题:</label>
  <input type="text" id="title" name="title"/>
</div>
<div>
  <label for="brief">摘要:</label>
  <input type="text" id="brief" name="brief"/>
</div>
<div>
  <label for="sex">性别:</label>
  <select id="sex" name="sex">
    <option value="0">男</option>
    <option value="1">女</option>
  </select>
</div>
<div>
  <label for="job">职业:</label>
  <select id="job" name="job">
    <option value="0">Java工程师</option>
    <option value="1">Net工程师</option>
  </select>
</div>
</form>

   引入依赖项——velocity-1.7-dep.jar

   模板文件frm.vm

##表单模板
##@author fsjohnhuang
##@version 1.0
## 引入外部模板文件
#parse('macro.vm')
## 主逻辑
<form action="$action">
#foreach($input in $inputs)
#input($input.title $input.id)
#end
#foreach($select in $selects)
#select($select.title $select.id $select.items)
#end
</form>

   模板文件macro.vm

## 生成input表单元素区域的宏
#macro(input $title $id)
<div>
  <label for="$id">$title</label>
  <input type="text" id="$id" name="$id"/>
</div>
#end
## 生成select表单元素区域的宏
#macro(select $title $id $items)
<div>
  <label for="$id">$title</label>
  <select id="$id" name="$id">
## VTL指令紧贴左侧才能确保结果的排版正常(不会有多余空格)
#foreach($key in $items.keySet())
    <option value="$key">$items.get($key)</option>
#end
  </select>
</div>
#end

   Java代码:

public static void main(String[] args) {
        // 初始化模板引擎
        Properties props = new Properties();
        props.put("file.resource.loader.path", ".\\vm");
        VelocityEngine ve = new VelocityEngine(props);
        // 配置引擎上下文对象
        VelocityContext ctx = new VelocityContext();
        ctx.put("action", "./submit");
        ArrayList<HashMap<String, String>> inputs = new ArrayList<HashMap<String,String>>();
        HashMap<String, String> input1 = new HashMap<String, String>();
        input1.put("id", "title");
        input1.put("title", "标题:");
        inputs.add(input1);
        HashMap<String, String> input2 = new HashMap<String, String>();
        input2.put("id", "brief");
        input2.put("title", "摘要:");
        inputs.add(input2);
        ctx.put("inputs", inputs);
        ArrayList<HashMap<String, Object>> selects = new ArrayList<HashMap<String,Object>>();
        HashMap<String, Object> select1 = new HashMap<String, Object>();
        selects.add(select1);
        select1.put("id", "sex");
        select1.put("title", "性别:");
        HashMap<Integer, String> kv1 = new HashMap<Integer, String>();
        kv1.put(0, "男");
        kv1.put(1, "女");
        select1.put("items", kv1);
        HashMap<String, Object> select2 = new HashMap<String, Object>();
        selects.add(select2);
        select2.put("id", "job");
        select2.put("title", "职业:");
        HashMap<Integer, String> kv2 = new HashMap<Integer, String>();
        kv2.put(0, "Java工程师");
        kv2.put(1, "Net工程师");
        select2.put("items", kv2);
        ctx.put("selects", selects);
        // 加载模板文件
        Template t = ve.getTemplate("test.vm");
        StringWriter sw = new StringWriter();
        // 渲染模板
        t.merge(ctx, sw);
        System.out.print(sw.toString());
    }

 Velocity模板引擎使用时的关注点分别为以外部文件形式存在的Velocity模板和Java代码调用。

 Velocity模板由VTL(Velocity Template Language)和引擎上下文对象构成;Java代码调用部分则负责初始Velocity引擎、构建引擎上下文对象、加载Velocity模板和启动模版渲染。而Velocity模板与Java代码调用部分通信的纽带就是引擎上下文对象了。

三、总结                              

 现在我们对Velocity引擎应该有个大概的了解,后续内容将对上述内容逐一深入。

 如上述示例,若想改成如下格式就要重新设计模板形式了:

<form action="./submit">

  <div>

    .................

  </div>

  <div>

    .................

  </div>

  <div>

    .................

  </div>

  <div>

    .................

  </div>

</form>

========

加速Java应用开发速度4-使用模板技术加速项目开发速度

templateintellij idea代码生成 

《加速Java应用开发速度》系列目录:

加速Java应用开发速度1——加速spring/hibernate应用调试时启动速度

加速Java应用开发速度2——加速项目调试启动速度

加速Java应用开发速度3——单元/集成测试+CI

加速Java应用开发速度4——使用模板技术加速项目开发速度

加速Java应用开发速度5——使用脚本自动化日常操作 

 

模板,一个我们天天使用的技术, 比如:

Java类就是创建Java对象实例的模板;

泛型,参数化类型的模板,如List<User>;常见的如泛型DAO、泛型Service等;

Arrays.sort() 一个排序的模板;

Spring中的DAO支持设计;可参考《我对SpringDAO层支持的总结》;

HttpServlet设计,如service根据http method转发给各个do开头的方法(doGet、doPost等);

还有如Struts2的ActionSupport设计,我们继承后能自动得到如国际化、验证的支持;

JSP、Velocity、Freemarker等模板页面技术;

等等。。

 

模板带给我们的好处很明显:约束+重用。通过模板我们可以把变与不变分离,重用不变,变可以交给子类/通过回调机制完成,而且还具有约束作用,防止乱写代码。

 

那我们应该利用好这个技术,加速项目的开发速度。接下来我们看看如何利用模板技术来加速我们的开发速度。

 

接下来,我将介绍下如何利用模板技术加速开发速度,但不会接受如何利用模板技术开发可复用的代码;本文以IntelliJ IDEA为原型介绍:

1、代码生成

2、Live Template

3、File and code Templates

4、自动代码生成

 

1、代码生成

如我们要求 i + j,可以先:

int k = add(i, j); 

然后按Alt+enter自动生成相关代码;而不是自己去敲;其会自动生成相应的变量和方法体;如图

 

1、按Alt+Enter弹出如创建方法/创建本地变量的提示

2、可以根据生成的模板方法,修改模板参数;

 

3、还有典型的如生成构造器、getter/setter等,按Alt+Insert得到如下图:

比如在生成构造器时,可以选择相关字段,会自动生成相应的赋值操作:

 

4、Ctrl+O/Alt+Insert生成覆盖方法;ctrl+I/Alt+Insert生成实现方法的

5、选中代码后,Ctrl+Alt+T弹出Surround with,生成包围代码的的代码,如if/else:

6、在如JSP标签页面中,按Ctrl+Alt+J,生成环绕的标签:

等等。。具体可以参考jetbrains.官网的《Generating Code》部分。

 

2、Live Template

如果用过idea,肯定用过如输入 psvm 然后按Tab键,会自动生成public static void main方法,使我们少输入很多字符。这个功能在idea中叫做Live Template;接下来让我们看看有哪些Live Template和如何自定义Live Template。

 

最常见的功能:

1、psvm----->public static void main(String[] args) {}

2、psfi ------->public static final int 

3、ifn   会自动生成如下图

……

 

大家可以通过 File--->Settings---->Live Templates找到所有模板,如:

如 lazy 生成延迟初始化的代码,inn生成if (** != null)

 

如fori --->for (int j = 0; j < ; j++) {}    

List list;  itli  ----> for (int i = 0; i < list.size(); i++) { Object o =  list.get(i);}

    

等等,这个可以去Settings里查看。

 

接下来我们看看如何自定义自己的Live Template:

 

1、输入“缩写前缀”,即在代码中输入的前缀;

2、模板文本;

3、Change:选择在哪使用;

 

接下来在Java文件中,输入test会生成 hello world;

 

此处看到 $END$ 这种变量,接下来解释下:

1、格式是$变量名$

2、$END$ : 表示展开模板后光标停留的位置,比如我们的test,生成模板后,光标停留在hello world 前边;

3、$SELECTION$ : 表示对选中的代码应用模板;如我们定义test为:

 

 

此处选中“int i = 1;”,然后按Ctrl+Alt+T 弹出“Surround With” 然后输入test前缀,自动生成:--->hello int i = 1; world 

 

还有如 输入 if for等前缀 按Ctrl+Shift+Enter会自动生成 带()和{} 的形式,非常方便。

 

如果想定义自己的变量,可以直接点击在编写模板时,模板文本右边的:“Edit variables” 编写:如得到返回的变量,方法名,类名等等。

 

大家可以参考官网的《Live Templates》。

 

3、File and code Templates

到此我们使用的都是代码块级别的模板,在工作中我们常见的还需要:

1、生成如Copyright头;

2、生成类头Javadoc,如用户、时间、版本;

3、创建如spring配置文件,每次可能都是从别的地方复制一份;

4、如我们做企业项目时,都先写一个CRUD的DAO、Service、Controller等等,但是几乎每一个模块都是类似的,但是我们每次可能都要重复写一遍;

 

因为IDEA使用的是velocity模板,所以语法相对来说是比较灵活的,而Eclipse看了下是自创的,所以在创建时没有IDEA灵活。

 

File---->Settings--->File and Code Templates 打开模板设置页面

 

3.1、给Class生成Copyright头

1、创建Include文件

1、首先选择Includes标签,然后点击创建创建一个;

2、接着Name处输入名字;

3、Extension部分输入扩展名;

4、文件正文;

此文件包含了我的copyright

 

2、添加到类模板中

1、 首先选中Class;

2、在页面顶部使用 @parse("Coyright.java")把刚才写的文件包含进来

 

接着新建一个Java Class,在页面的顶部会出现这个copyright;

 

3.3、自定义Service模板 

以KeyValueService.java为例。

 

1、首先File--->Settings---->File and Code Templates进入模板设置页面

2、创建模板,如图所示

 

1、点击Templates标签,点击新增按钮

2、Name处输入名字

3、Extension处输入扩展名

4、输入模板正文,此处我们可以使用${NAME}和${PACKAGE_NAME}分别获取输入的文件名和包名

5、语法是velocity语法,所以很强大,按理说很复杂的需求也可以实现

 

3、新增Class

3.1、在包处Alt+Enter弹出新建列表,选择Java  Class

 

3.2、 接着在弹出的界面中输入 Service的前缀,并选择Service类型:

 

4、接着类就创建好了:

Java代码

/** 

 * Copyright (c) 2005-2012 https://github.com/zhangkaitao 

 * 

 * Licensed under the Apache License, Version 2.0 (the "License"); 

 */  

package com.sishuok.es.maintain.keyvalue.service;  

  

import com.sishuok.es.common.inject.annotation.BaseComponent;  

import com.sishuok.es.common.service.BaseService;  

import com.sishuok.es.maintain.keyvalue.entity.HelloValue;  

import com.sishuok.es.maintain.keyvalue.repository.HelloRepository;  

import org.springframework.beans.factory.annotation.Autowired;  

import org.springframework.stereotype.Service;  

  

/** 

 * <p>User: Zhang Kaitao 

 * <p>Date: 13-6-20 下午4:31 

 * <p>Version: 1.0 

 */  

@Service  

public class HelloService extends BaseService<Hello, Long> {  

  

    @Autowired  

    @BaseComponent  

    private HelloRepository helloRepository;  

  

}  

非常方便。

 

除此之外,我们还可以定义如 jsp模板、html模板、配置文件模板等等,消除开发中的重复工作。

 

但是此种方式的主要缺点就是:一次只能一个文件。比如,我们生成Service时,其实DAO、Contoller等最好也自动生成。 接下来就需要自动代码生成了。

 

4、自动代码生成

估计很多朋友都使用/开发过代码生成器;其实开发一个简单的代码生成器花不了多长时间,核心指导思想是:变与不变分离:

不变的是结构;

变的是包名、类名及实体数据。

所以根据这个思想可以很容易写一个代码生成器,可以按照如下步骤完成:

1、自动生成一个模块的DAO、Service、Controller;

2、根据数据库自动生成一个模块的Entity、DAO、Service、Controller;

3、自动生成一对一、一对多关系的模块代码;

4、自动生成公司中常用的代码的模块代码,如树;

目前见到的主要有这些类型的自动代码生成。

 

代码生成的模板文件可以使用纯文本(即纯粹的字符串替换),更高级点的可以使用如velocity这种模板语言,更加强大。

 

如果有朋友不会写代码生成器,可以先建一个Example的示例代码,接着做复制、粘帖、修改实体名等等完成,估计30秒钟也能出一个基本的模块代码。但是如果交给代码生成器,速度更快。

 

比如笔者刚开发的新项目,还没时间开发代码生成器,就写一个一些示例,这样如果写新模块就直接复制一份改改即可,尤其树这块节省不少时间,点击showcase前往查看。

 

代码生成器也不是万能的,如果你做过互联网项目,不像企业应用那样有许多的增删改查,所以这个时候,纯粹生成CRUD的代码生成器没有任何意义。

 

到此我们介绍完了模板,使用模板能提升不少开发速度,但是模板不是万能的,只有发现有些代码是由:变与不变组成,那我们就可以把不变的做成模板,变的部分通过占位符(即变量)填入。

 

参考资料:

30 Days with IntelliJ IDEA. Quick Popups

IntelliJ IDEA 12.1.0 Web Help

不变的做成模板,变的部分用变量表示。

是的,这个要自己识别,我们天天在用模板这玩意  ,但是如何识别出现这才是关键。如spring jdbc template就是一个绝好的例子。

说实话,我们今年的项目中我大胆的用了spring jdbctemplate,可惜,被Manager否定了,说着东西有诸多弊端,没怎么花时间去研究这东西,真心不知道怎么样...楼主能说说看吗,关于原生的JDBC和spring jdbctemplate到底有什么差别么...

原始的就是写代码多,什么都要自己去写; 

1、代码冗余

2、映射部分 

   给PreparedStatement赋值、取值

   ResultSet取值映射到model

3、事务传播麻烦

jdbc template就是来干:

1、消除冗余代码

2、简化映射

3、得到spring事务管理的好处

spring jdbc template 封装的很薄, 其实可以看出个工具, 上手简单、为嘛不用。

所以直接写jdbc 开发效率慢 而且诸如事务传播等都是很麻烦的。

你可以参考

http://jinnianshilongnian.iteye.com/blog/1685963

你们现在架构是什么样的

架构,呵呵,谈什么架构哦,以前印度人写的框架给拿过来,算是在此版本上重新开放,基本就是Struts2, Spring(用的很少,基本是我来之后我用的多些), ORM没用框架,基本是自己手写的原生jdbc,经常能看到静态代码监测不通过的,看到数据库连接,resultSet,PreparedStatement未释放的,我当时就像用spring的模板方法肯定剩下很多时间,而且很方便就搞定了,

可以不用spring/hibernate等框架 但是得借用相关的思想; 所以你说的那些根本没 “不重复自己”。楼主可以写一套重构 给经理看: 节省了代码就节省了开发时间;代码少了 bug自然就会少

jdbc template就是来干:

1、消除冗余代码

2、简化映射

3、得到spring事务管理的好处

所以直接写jdbc 开发效率慢 而且诸如事务传播等都是很麻烦的。

是少了个On frame deactivation 这个设置

我现在都是maven+jetty运行,还真没有这么用过,刚查了下

http://stackoverflow.com/questions/9117844/publish-changes-to-server-from-intellij-idea-11

意思就是当idea窗口失去焦点焦点时 更新 

哦 我刚才在Build Artifacts 添加上项目artifacts的就出现窗口和hot swap classes选项了

和现在我还不知道这个Artifacts 是干什么的?? 现在每次更新都需要按下反人类的快捷键CTRL+SHIFT+F9更新 如果有跟ECLIPSE的保存自动更新就方便了 目前没找到

Artifacts 就是制品,可以理解为打包好的产品;比如打成war包 / 直接的web项目目录 / jar包

不过按你说的On frame deactivation,配置这个应该是可以的; 如果maven内嵌 我现在也是CTRL+SHIFT+F9更新

哦 我刚才在Build Artifacts 添加上项目artifacts的就出现窗口和hot swap classes选项了

和现在我还不知道这个Artifacts 是干什么的?? 现在每次更新都需要按下反人类的快捷键CTRL+SHIFT+F9更新 如果有跟ECLIPSE的保存自动更新就方便了 目前没找到

如果是非debug模式下

http://jinnianshilongnian.iteye.com/blog/1887788

如在执行tomcat/jetty时的VM参数中指定如上配置即可。无需在debug模式下执行。如果使用的是如idea可以按Ctrl+Shift+F9编译当前类/Ctrl+F9编译所有更改的类。

我之前调试成功过一次 就是在TOMCAT 设置那有2个On 'Update' action xx 的选项

都选择hotswap class 然后在每次修改代码后在Deployment选项卡点Deploy All就完成你说的热替换效果 但是现在不知道为什么现在On 'Update' action只有1个地方设置 选项里面也只有Restart server选项 咋也变不回去了

如在执行tomcat/jetty时的VM参数中指定如上配置即可。无需在debug模式下执行。如果使用的是如idea可以按Ctrl+Shift+F9编译当前类/Ctrl+F9编译所有更改的类。

所以你可以参考这篇 直接上字节码热替换 

我09年接触过,那时候也是抵触,直到最近一年 尤其maven集成这块 eclipse比较弱,使用idea真心方便不少。

========

eclipse开发velocity实例

开发环境

        Eclipse Java EE IDE for Web Developers.(Version: Helios Service Release 1)

        jdk1.6.0_07

        apache-tomcat-6.0.10

        首先需要为eclipse安装velocity编辑插件:

                在Eclipse的Help->Install New Software...

                点击“Add加 Veloeclipse,值:http://veloeclipse.googlecode.com/svn/trunk/update/

                备注:如果无法安装,在安装插件的界面中把 Group Items by Catagory 前打钩去掉

创建项目

        打开eclipse,File -> New -> Other... -> Web -> Dynamic Web Projec  之后按照提示一路next;

        注意1:修改代码文件输出路径,默认是build\classes;这个不符合tomcat的要求,需要改成WebContent\WEB-INF\classes 如下:

        

        注意2:勾选 Generate web.xml deployment descriptor

        添加velocity依赖包

                velocity相关的包有十多个,下载解压后复制全部,粘贴到项目WebContent -> WEB-INF ->lib文件夹中

                项目名右键菜单选择build path -> configure build path ->java build path ->libraries -> add jars 选择项目lib文件夹,选择全部jar最后点确认按钮

                备注:velocity所需的jar包下载地址

        添加velocity模板文件

                在WebContent下添加一个文件夹,我起名叫templates。在该文件下添加一个hello.vm文件,里面内容如下:

           

<html> 
                         <head><title>Sample velocity page</title></head> 
                         <body bgcolor="#ffffff"> 
                                 <center> 
                                         <h2>Hello My First Velocity</h2> 
                                         <table width="100" cellpadding="5" cellspacing="1" bordercolor="#333333"> 
                                                 <tr><td bgcolor="#eeeeee" align="center">name list</td></tr> 
                                                 #foreach ($name in $theList) 
                                                 <tr><td bgcolor="#6666FF" align="center">$name</td></tr> 
                                                 #end 
                                         </table> 
                                 </center> 
                         </body> 
                 </html>

        添加java类文件

                在Java Resource -> src下新建一个包,包名com.velocitydemo.velocityhandler,名称随意,后面配置文件里要用到,前后需要一致

                在该包下添加一个类,类名HelloHandler,名称随意,道理同上

                类的代码如下:

         

package com.velocitydemo.velocityhandler; 
                 import java.util.Properties; 
                 import java.util.Vector; 
                 import javax.servlet.ServletException; 
                 import javax.servlet.http.HttpServletRequest; 
                 import javax.servlet.http.HttpServletResponse; 
                 import org.apache.velocity.Template; 
                 import org.apache.velocity.app.Velocity; 
                 import org.apache.velocity.app.VelocityEngine; 
                 import org.apache.velocity.context.Context; 
                 import org.apache.velocity.tools.view.VelocityViewServlet; 
                 public class HelloHandler extends VelocityViewServlet { 
                         private static final long serialVersionUID = 1L; 
                         private VelocityEngine velo; 
                         public void init() throws ServletException { 
                                 velo = new VelocityEngine();// velocity引擎对象 
                                 Properties prop = new Properties();// 设置vm模板的装载路径 
                                 String path = this.getServletContext().getRealPath("/"); 
                                 prop.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, path + "templates/"); 
                                 try { 
                                         velo.init(prop);// 初始化设置,下面用到getTemplate("*.vm")输出时;一定要调用velo对象去做,即velo.getTemplate("*.vm") 
                                 } catch (Exception e1) { 
                                         e1.printStackTrace(); 
                                 } 
                         } 
                         protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx) { 
                                 String p1 = "Charles"; 
                                 String p2 = "Michael"; 
                                 Vector personList = new Vector(); 
                                 personList.addElement(p1); 
                                 personList.addElement(p2); 
                                 ctx.put("theList", personList); // 将模板数据 list放置到上下文环境context中 
                                 Template template = velo.getTemplate("hello.vm"); 
                                 return template; 
                         } 
                 }

            

        配置web.xml

                打开WEB-INF下的web.xml文件,内容如下:

             

<?xml version="1.0" encoding="UTF-8"?> 
                 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                                    xmlns="http://java.sun.com/xml/ns/javaee" 
                                    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
                                    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
                                    id="WebApp_ID" version="3.0"> 
                         <display-name>velocity-demo</display-name> 
                         <servlet> 
                                 <servlet-name>velocity</servlet-name> 
                                 <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class> 
                         </servlet> 
                         <servlet-mapping> 
                                 <servlet-name>velocity</servlet-name> 
                                 <url-pattern>*.vm</url-pattern> 
                         </servlet-mapping> 
                         <servlet> 
                                 <servlet-name>hello</servlet-name> 
                                 <servlet-class>com.velocitydemo.velocityhandler.HelloHandler</servlet-class> 
                         </servlet> 
                         <servlet-mapping> 
                                 <servlet-name>hello</servlet-name> 
                                 <url-pattern>/hello</url-pattern> 
                         </servlet-mapping> 
                         <welcome-file-list> 
                                 <welcome-file>/hello</welcome-file> 
                         </welcome-file-list> 
                 </web-app>

        至此一个最简单的velocity项目创建完毕

                注意:WEB-INF下的classes文件夹并不显示在项目结构图中

                

        发布项目

                到这里可以把项目文件夹中的WebContent发布到Tomcat中进行测试了

                发布的方式参考地址()

        启动tomcat访问一个最简单的velocity项目

========