java引入resource下的模板_Beetl自定义ResourceLoader,实现特殊的模板加载需求
一直以来,有个目标是:使用Beetl的时候,如果web root 里有模板文件,则beetl从web root里加载。如果没有,则从jar里加载,或者从Db里加载。
这样,工程里大量相同的模板模板可以共用(当你的应用,有N个客户的时候,特别需要这个,更新一个jar,重启一下即可)。
最后确认CompositeResourceLoader 无法满足自己的需求。于是磕磕碰碰的自己实现了一个ResourceLoader,自定义加载模板。
直接贴代码吧
package com.jfinal.ext.beetl;
import java.io.File;
import java.net.URL;
import java.util.Map;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Resource;
import org.beetl.core.ResourceLoader;
import org.beetl.core.misc.BeetlUtil;
/**
* 自定义的ResourceLoader,用于支持从文件,jar和数据库里加载模板。
* @author Neoman
*/
public class AppResourceLoader implements ResourceLoader{
private String root = null;
boolean autoCheck = false;
//模板来自文件
boolean fromFile = true;
//模板来自Db
boolean fromDb = false;
//模板来自jar包
boolean fromJar = false;
protected String charset = "UTF-8";
String functionRoot = "functions";
GroupTemplate gt = null;
String functionSuffix = "fn";
ClassLoader classLoader = null;
/**
* 使用加载beetl.jar的classloader,以及默认root为根目录
*/
public AppResourceLoader()
{
//保留,用于通过配置构造一个ResouceLoader
classLoader = this.getClass().getClassLoader();
this.root = "";
}
/** 使用指定的classloader
* @param classLoader
*/
public AppResourceLoader(ClassLoader classLoader)
{
this.classLoader = classLoader;
this.root = "";
}
/**使用指定的classloader和root
* @param classLoader
* @param root 模板路径,如/com/templates/
*/
public AppResourceLoader(ClassLoader classLoader, String root)
{
this.classLoader = classLoader;
this.root = root;
}
/**
* @param classLoader
* @param root
* @param charset
*/
public AppResourceLoader(ClassLoader classLoader, String root, String charset)
{
this(classLoader, root);
this.charset = charset;
}
/**
* @param root ,/com/templates/如其后的resourceId对应的路径是root+"/"+resourceId
*/
public AppResourceLoader(String root)
{
this();
if (root.equals("/"))
{
this.root = "";
}
else
{
this.root = root;
}
}
public AppResourceLoader(String root, String charset)
{
this(root);
this.charset = charset;
}
/*
* (non-Javadoc)
*
* @see org.beetl.core.ResourceLoader#getResource(java.lang.String)
*/
@Override
public Resource getResource(String key)
{
AppResource resource = new AppResource(root, key, this);
resource.setFromFile(fromFile);
resource.setFromDb(fromDb);
resource.setFromJar(fromJar);
return resource;
}
/*
* (non-Javadoc)
*
* @see org.beetl.core.ResourceLoader#close()
*/
@Override
public void close()
{
// TODO Auto-generated method stub
}
@Override
public boolean isModified(Resource key)
{
if (this.autoCheck)
{
return key.isModified();
}
else
{
return false;
}
}
public boolean isAutoCheck()
{
return autoCheck;
}
public void setAutoCheck(boolean autoCheck)
{
this.autoCheck = autoCheck;
}
public String getRoot()
{
return root;
}
@Override
public void init(GroupTemplate gt)
{
Map resourceMap = gt.getConf().getResourceMap();
if (resourceMap.get("root") != null)
{
String temp = resourceMap.get("root");
if (temp.equals("/") || temp.length() == 0)
{
}
else
{
if (this.root.endsWith("/"))
{
this.root = this.root + resourceMap.get("root");
}
else
{
this.root = this.root + "/" + resourceMap.get("root");
}
}
}
if (this.charset == null)
{
this.charset = resourceMap.get("charset");
}
this.functionSuffix = resourceMap.get("functionSuffix");
this.autoCheck = Boolean.parseBoolean(resourceMap.get("autoCheck"));
this.functionRoot = resourceMap.get("functionRoot");
//初始化functions
URL url = classLoader.getResource("");
this.gt = gt;
if (url!=null&&url.getProtocol().equals("file"))
{
File fnRoot = new File(url.getFile() + File.separator + root + File.separator + this.functionRoot);
if (fnRoot.exists())
{
String ns = "";
String path = "/".concat(this.functionRoot).concat("/");
BeetlUtil.autoFileFunctionRegister(gt, fnRoot, ns, path, this.functionSuffix);
}
}
}
@Override
public boolean exist(String key)
{
URL url = this.classLoader.getResource(root + key);
if(url==null){
//兼容以前的
url = this.classLoader.getClass().getResource(root + key);
}
return url!=null;
}
public String getCharset()
{
return charset;
}
public void setCharset(String charset)
{
this.charset = charset;
}
@Override
public String getResourceId(Resource resource, String id)
{
if (resource == null)
return id;
else
return BeetlUtil.getRelPath(resource.getId(), id);
}
public ClassLoader getClassLoader() {
return classLoader;
}
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public String getInfo() {
return "ClassLoader:"+this.classLoader+" Path:"+root;
}
public boolean isFromFile() {
return fromFile;
}
public void setFromFile(boolean fromFile) {
this.fromFile = fromFile;
}
public boolean isFromDb() {
return fromDb;
}
public void setFromDb(boolean fromDb) {
this.fromDb = fromDb;
}
public boolean isFromJar() {
return fromJar;
}
public void setFromJar(boolean fromJar) {
this.fromJar = fromJar;
}
}
AppResourceLoader基本复制之前org.beetl.core.resource.WebAppResourceLoader的。init 注册函数的时候,还是仅仅读取web root里的目录。因为我自己的是代码里注册了,所以,也没去实现从jar加载function
package com.jfinal.ext.beetl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import org.beetl.core.Resource;
import org.beetl.core.ResourceLoader;
import org.beetl.core.exception.BeetlException;
import com.jfinal.kit.PathKit;
/**
* 模板资源读取,支持从db,文件,classpath,jar 里读取模板资源:
* 先从webroot的文件里读取,如果没有,则读取数据库,如何还找不到,读取jar或者classpath里的
* @author Neoman
*
*/
public class AppResource extends Resource{
String root = null;
File file = null;
long lastModified = 0;
//模板来自文件
boolean fromFile = true;
//模板来自Db
boolean fromDb = false;
//模板来自jar包
boolean fromJar = false;
public AppResource(String root, String key, ResourceLoader resourceLoader)
{
super(key, resourceLoader);
this.root = root;
}
@Override
public Reader openReader()
{
InputStream is = null;
Reader br;
AppResourceLoader loader = (AppResourceLoader) this.resourceLoader;
try
{//从文件里读取,一般的web root里
file = new File(PathKit.getWebRootPath() + root, id);
if (file.exists() && fromFile) {
is = new FileInputStream(file);
}
//从数据库里读取,暂未实现
if (is == null && fromDb) {
}
//从jar 或者classpath里读取
if (is == null && fromJar) {
ClassLoader cs = loader.getClassLoader();
URL url = cs.getResource(root + id);
if(url==null){
//兼容以前的写法
url = resourceLoader.getClass().getResource(root + id);
}
if (url == null)
{
BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR);
be.resourceId = this.id;
throw be;
}
is = url.openStream();
}
if (is == null) {
BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR, " 模板不存在: " + loader.getInfo());
be.resourceId = this.id;
throw be;
}
br = new BufferedReader(new InputStreamReader(is, loader.charset));
return br;
}
catch (UnsupportedEncodingException e)
{
return null;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR, " 模板根目录为 " + loader.getRoot());
be.resourceId = this.id;
throw be;
} catch (IOException e) {
// TODO Auto-generated catch block
BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR, " 模板根目录为 " + loader.getRoot());
be.resourceId = this.id;
throw be;
}
}
/**
* 目前,只能跟踪文件的变化
*/
@Override
public boolean isModified()
{
if (fromFile && file != null && file.exists())
{
return file.lastModified() != this.lastModified;
}
//String refresh = SysConfig.dao.queryConfig("beetl.template.refresh", "0");
//if (!"0".equals(refresh)) {//不等于0,刷新模板
//SysConfig.dao.updateConfig("beetl.template.refresh", "0");
//return true;
//}
//jar里,肯定要重启了
if (fromJar)
{
return false;
}
//db里 判断时间--暂未 实现
if (fromDb)
{
return false;
}
return false;
}
@Override
public String getId()
{
return id;
}
public boolean isFromFile() {
return fromFile;
}
public void setFromFile(boolean fromFile) {
this.fromFile = fromFile;
}
public boolean isFromDb() {
return fromDb;
}
public void setFromDb(boolean fromDb) {
this.fromDb = fromDb;
}
public boolean isFromJar() {
return fromJar;
}
public void setFromJar(boolean fromJar) {
this.fromJar = fromJar;
}
}
暂时未用到从db加载,所以没去实现了。不过也很简单了。AppResource 主要是 openReader 里面判断资源从哪里加载。
博客粗略记录一下,希望对大家有用,欢迎交流,微信:netsafer
java引入resource下的模板_Beetl自定义ResourceLoader,实现特殊的模板加载需求相关推荐
- android 在自定义的listview(有刷新加载项)列表中,数据过少时不能铺满整个屏幕时,header和footer同时显示问题...
android 在自定义的listview(有刷新加载项)列表中,数据过少时,当刷新时,加载项也会显示,这是很头疼的一个问题,查阅了一些资料,总结了一个比较不错的方法: 原来代码: 1 @Overr ...
- 一个常用的自定义弹框封装(适配 AndroidX),加载 ProgressDialog,状态显示的 StatusDialog 和自定义 Toast,全部支持背景颜色,圆角,边框和文字的自定义,构建者模
MNProgressHUD 项目地址:maning0303/MNProgressHUD 简介: 一个常用的自定义弹框封装(适配 AndroidX),加载 ProgressDialog,状态显示的 S ...
- win7下计划任务schtasks使用详解及错误:无法加载列资源的解决方法1
win7下计划任务schtasks使用详解及"错误:无法加载列资源"的解决方法1 2011-12-10 20:33 schtasks 命令简述: 安排命令和程序,使其定期运行或在指 ...
- Android 自定义WaveProgressView满足你所有水波纹加载需求
自定义WaveProgressView满足你所有水波纹加载需求
- linux配置文件重新加载失败,linux下为什么每次修改完配置文件之后都需要重新加载配置文件...
解释了 linux下为什么每次修改完配置文件之后都需要重新加载配置文件 目录一.关于inode 二.inode的作用 二.为什么每次修改完服务器配置文件之后,都需要重新加载一下配置文件? 一.关于in ...
- [JAVA]引入目录下所有jar包等问题
2019独角兽企业重金招聘Python工程师标准>>> 一.引入目录下所有的包 java命令用可用-cp引入jar包,但是不支持通配符.通常这些jar包都在一个目录下,可用使用-Dj ...
- java 自定义classloader_编写自定义classloader实现类的动态加载
目标:实现类的动态加载 原理:使用java的自定义classloader机制实现类的动态加载. 代码实现://自定义classloader public class StrategyClassLoad ...
- 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)...
AsyncTask使用方法详情:http://www.cnblogs.com/zzw1994/p/4959949.html 下拉开源框架PullToRefresh使用方法和下载详情:http://ww ...
- 如何在MyEclipse中添加 用户自定义类库 以及将自定义的类库加入工程的加载目录...
2019独角兽企业重金招聘Python工程师标准>>> 但真正解决问题的是下面几句而已: 您是不是没有将common.jar文件导入buildPath 如果没有 选中你所在的项目 右 ...
最新文章
- 【Codeforces】967C Stairs and Elevators (二分)。
- CSS使用display:incline与float:left的区别:脱离文档流 参差不齐
- rpm安装的mysql如何数据迁移_linux下mysql数据库的rpm安装步骤及常见问题的解决
- 实验5 编写、调试具有多个段的程序
- php正则学习,php中正则表达式的学习及应用
- php创建mysql分区,MySql创建分区表
- t–sql pl–sql_SQL串联正确完成–第1部分–可疑做法
- Asp.Net Web API 2第十四课——Content Negotiation(内容协商)
- SecureCRT安装与使用
- 计算机操作系统第一章测试题及答案
- 二叉树查找结点及父结点
- 启动优化之一——启动分析及优化方案
- 简单提取iOS13的ipsw固件的内置壁纸(或文件)
- Codeforces Round #521 (Div. 3) 	E - Thematic Contests (二分 + STL)
- 人工智能对医疗和健康产业的冲击和革命——意识上传技术展望
- flea-db使用之JPA接入
- 修改Element UI自带的小图标,替换成自己的(类似自定义Element UI图标)
- 学习笔记:新技术与新趋势(演讲者:王煜全-海银资本合伙人)
- 《如何让你爱的人爱上你》第三部分:自尊
- 营业执照注册编码 15与18位的java实现
热门文章
- grafana授权公司内部邮箱登录 ldap配置
- 基于注解风格的Spring-MVC的拦截器
- 关于竖表转横表的问题
- symbian c++ 开发环境Carbide.c++搭建
- 自己的路 php,生活感悟的句子:走自己的路,做自己的事
- 安川最小巧机器人_2020工博会,安川展品前瞻(机器人篇)
- php5.4 mysql connect_php5.4 Call to undefined function mysql_connect()
- 1461B. Find the Spruce
- php科学计数法转string,php如何将科学计数法转数字
- csp真题 202109-2非零段划分C++代码(100分)