最近升级团队的代码生成工具,此工具是velocity实现的。

之前习惯使用UTF-8编码,现在团队使用GBK。

所以遇到一种场景,模板文件使用UTF-8(习惯了所有任性),输出文件使用GBK(项目需要)。


Properties props = new Properties();
props.setProperty(Velocity.ENCODING_DEFAULT, "GBK");//全局编码,如果以下编码不设置它就生效
props.setProperty(Velocity.INPUT_ENCODING, "UTF-8");//输入流的编码,其实是打酱油!非模板文件编码
props.setProperty(Velocity.OUTPUT_ENCODING, "GBK");//输入流编码,很关键!
props.setProperty(VelocityEngine.RESOURCE_LOADER,"file");//模板文件加载方式
VelocityEngine engine = new VelocityEngine(props);

下面这段code是解决乱码问题的关键

Template  template = engine.getTemplate("a.vm","UTF-8");//模板文件的编码,很关键!
VelocityContext context = new VelocityContext();
context.put("a","a");
FileWriter fileWriter=new FileWriter("test.java");
template.merge(context, fileWriter);

分析:

String org.apache.velocity.runtime.RuntimeConstants.INPUT_ENCODING = "input.encoding"

The character encoding for the templates. Used by the parser in processing the input streams.

这是velocity中  INPUT_ENCODING 的doc,字面意思理解 "模板文件的编码,用于格式化输入流";

Template org.apache.velocity.app.VelocityEngine.getTemplate(String name, String encoding) throws ResourceNotFoundException, ParseErrorException

Returns a Template from the Velocity resource management system.

Parameters:
name The file name of the desired template.
encoding The character encoding to use for the template.

这是getTemplate(String name, String encoding)的doc,字面意思理解"encoding 参数是设置模板文件的编码"
经过我的多次实践,如果设置了 INPUT_ENCODING 为 UTF-8,直接使用getTemplate(String name)方法,结果就是输出的文件 编码没有问题,但是模板文件的中文到输出文件中就成乱码了!
换成getTemplate(String name, String encoding),传入UTF-8编码,一切正常!

这是一个深深的坑!之前翻遍各大博客及官方doc都无法定位这个问题的原因!因为大家一致使用getTemplate(String name)方法!

接下来谈下Velocity和VelocityEngine的区别

Velocity和VelocityEngine都可以用来读取模板文件和输出文件,宏观上讲,Velocity是单例模式,VelocityEngine是多例模式!

从细节上,Velocity因为是单例的设计模式,所以init方法只能执行一次,这就意味着你在整个应用程序生命周期中Velocity的配置是无法修改的!

再说下Velocity的几种Loader,主要有ClasspathResourceLoader FileResourceLoader (默认),一些不常用的 JarResourceLoader  DataSourceResourceLoader 及 WebappResourceLoader URLResourceLoader

下边再说下另外一个大坑

     /**
* Key used to retrieve the names of the resource loaders to be used. In a properties file they may appear as the following:
*
* <p>resource.loader = file,classpath</p>
*/
String RESOURCE_LOADER = "resource.loader";

从字面意思理解,这里可以设置file/classpath!真实的情况是,当你设置为 classpath 时,Velocity会切换成file,因为classpath是无效设置(这个让人很费解),只有设置为 class 并且设置 class.resource.loader.class 为 org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader,才会使用ClasspathResourceLoader !

综上所述,如果想实现同时支持file和class两种loader,必须使用VelocityEngine!在文件系统中无法读取到模板文件时自动切换为classPathLoader!代码如下

import java.util.Properties;

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.ResourceNotFoundException; public abstract class BaseCode {
{
initVelocity("file");
} private void initVelocity(String loader){
props = new Properties();
props.setProperty(Velocity.ENCODING_DEFAULT, "GBK");
props.setProperty(Velocity.INPUT_ENCODING, "GBK");
props.setProperty(Velocity.OUTPUT_ENCODING, "GBK");
props.setProperty(VelocityEngine.RESOURCE_LOADER,loader);
if(loader.equals("class")){
props.setProperty("class.resource.loader.class","org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
}
engine = new VelocityEngine(props);
} private String templetPath;
private Template template;
protected static VelocityEngine engine; protected static Properties props ; public String getTempletPath() {
return templetPath;
} public void setTempletPath(String templetPath) {
this.templetPath = templetPath;
} protected Template getTemplate(){
if(this.template==null){
try
{
template = engine.getTemplate(this.getTempletPath(),"GBK");
}
catch(ResourceNotFoundException e ){
initVelocity("class");
getTemplate();
}
}
return template; } protected VelocityContext getVelocityContext(){
VelocityContext context = new VelocityContext();
context.put( "nameUtil", NameUtil.get() );
return context;
} }

Velocity VelocityEngine 支持多种loader 乱码问题的更多相关文章

  1. Neutron 如何支持多种 network provider - 每天5分钟玩转 OpenStack(70)

    Neutron 的架构是非常开放的,可以支持多种 network provider,只要遵循一定的设计原则和规范.本节我们将开始讨论这个主题. 先讨论一个简单的场景:在 Neutorn 中使用 lin ...

  2. 创建支持多种屏幕尺寸的Android应用

    Android涉及各种各样的支持不同屏幕尺寸和密度的设备.对于应用程序,Android系统通过设备和句柄提供了统一的开发环境,大部分工作是校正每一个应用程序的用户界面到它显示的屏上.与此同时,系统提供 ...

  3. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  4. 使用AuthDBMType指令支持多种类似DBM的数据库

    Unix线程 在支持POSIX线程的Unix系统上,现在Apache能在混合的多进程.多线程模式下运行,使很多(但非全部)配置的可伸缩性得到了改善. 新的编译系统 重写了编译系统,现在是基于autoc ...

  5. search支持多种标签

    织梦的搜索页面支持dede标签的方法一 打开文件:include/arc.searchview.class.php 找到: require_once(DEDEINC."/taglib/hot ...

  6. 支持多种浏览器的纯css下拉菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. Cassandra在CQL语言层面支持多种数据类型

    Cassandra在CQL语言层面支持多种数据类型. CQL类型 对应Java类型 描述 ascii String ascii字符串 bigint long 64位整数 blob ByteBuffer ...

  8. 【原创】C++链表如何像Python List一样支持多种数据类型

    用过Python的码友都知道,Python中List支持多种数据类型,如下面代码所示链表li内的数据类型可以是整数,同时也可以是字符串,当然也可以是其他数据类型. 1: >>> li ...

  9. android 布局如何支持多种不同屏幕尺寸

    android 布局如何支持多种不同屏幕尺寸 --关于dp.layout-xxx.drawable-xxx作用的小结 转载自:http://blog.csdn.net/vincent_blog/art ...

随机推荐

  1. Qt——用于表格QTableView的模型

    如果想使用表格来呈现数据,Qt提供了一个方便的部件QTableWidget,但是直接用它实现一些功能可能比较困难.这里将介绍一种强大.灵活的方式来操作表格. 一.模型/视图架构 在这个架构中,模型用于 ...

  2. 51nod 1290 Counting Diff Pairs | 莫队 树状数组

    51nod 1290 Counting Diff Pairs | 莫队 树状数组 题面 一个长度为N的正整数数组A,给出一个数K以及Q个查询,每个查询包含2个数l和r,对于每个查询输出从A[i]到A[ ...

  3. MySQL 性能比较测试:MySQL 5.6 GA -vs- MySQL 5.5

    时间:2013年11月07日 ⁄ 分类: 数据库技术文档 ⁄   我要吐槽发评论 MySQL 5.6 GA 发布了,毫无疑问,这是 MySQL 最棒的一个版本. 如果你还不清楚 MySQL 5.6 版 ...

  4. 遇到问题---java---安装新版本jdk后Failed reading value of registry key

    情况 情况是原本安装有jdk1.7,能正常运行,现在要升级到1.8. 直接在oracle的网站下载1.8安装后修改配置为1.8后: 能用javac编译成功,但java命令运行时报错: Failed r ...

  5. xml的相关知识

  6. Eclipse Oxygen(4.7.0)安装插件Eclipse Class Decompiler反编译JAR文件

    引用自官方内容 Eclipse Class Decompiler是一款Eclipse插件,整合了多种反编译器,和Eclipse Class Viewer无缝集成,能够很方便的使用插件查看类库源码,进行 ...

  7. bzoj2441【中山市选】小W的问题

    题目描述 有一天,小W找了一个笛卡尔坐标系,并在上面选取了N个整点.他发现通过这些整点能够画出很多个“W”出来.具体来说,对于五个不同的点(x1, y1), (x2, y2), (x3, y3), ( ...

  8. 二、Linux学习之centOS的的setup

    因为我是在VMware上安装的centOS,网络设置选择的是桥接模式,这样可以和实体机使用同样的网络,但是也使用同样的IP,因此就需要设置一下IP了,否则使用ifconfig查询ip的时候显示的是12 ...

  9. 报错laravel/horizon v1.4.3 requires ext-pcntl * -> the requested PHP extension pcntl is missing from your system.的解决办法

    执行composer install后报以下错误: Problem 1 - laravel/horizon v1.4.3 requires ext-pcntl * -> the requeste ...

  10. Service Fabric —— Actor / Stateless Service 概念

    作者:潘罡 (Van Pan) @ Microsoft 上一节我们谈到了Stateful Service.在Service Fabric中,Stateful Service是理解Micro Servi ...