enjoy 3.3 release ^_^

This commit is contained in:
James
2017-11-21 22:43:34 +08:00
parent 28eb105ffa
commit 61aa1d2082
70 changed files with 3378 additions and 299 deletions

View File

@@ -16,24 +16,28 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.io.IOException;
import java.util.Date;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;
/**
* 不带参时,按默认 pattern 输出当前日期
* #date 日期格式化输出指令
*
* #date() 指令支持无参时获取当前指令,第一个参数 string 当成是 pattern
* 三种用法:
* 1#date(createAt) 用默认 datePattern 配置,输出 createAt 变量中的日期值
* 2#date(createAt, "yyyy-MM-dd HH:mm:ss") 用第二个参数指定的 datePattern输出 createAt 变量中的日期值
* 3#date() 用默认 datePattern 配置,输出 “当前” 日期值
*
* 日期输出指令,第一个参数是被输出的 java.util.Date 对象或其子类对象
* 无第二个参数时按默认 patter 输出,第二个参数为 expr 表达式,表示 pattern
* 第二个为 date 时,表示当第一个为 null 时的默认值
* 注意:
* 1#date 指令中的参数可以是变量,例如:#date(d, p) 中的 d 与 p 可以全都是变量
* 2默认 datePattern 可通过 Engine.setDatePattern(...) 进行配置
*/
public class DateDirective extends Directive {
@@ -51,34 +55,32 @@ public class DateDirective extends Directive {
this.valueExpr = null;
this.datePatternExpr = null;
} else if (paraNum == 1) {
this.valueExpr = exprList.getExprArray()[0];
this.valueExpr = exprList.getExpr(0);
this.datePatternExpr = null;
} else if (paraNum == 2) {
this.valueExpr = exprList.getExprArray()[0];
this.datePatternExpr = exprList.getExprArray()[1];
this.valueExpr = exprList.getExpr(0);
this.datePatternExpr = exprList.getExpr(1);
}
}
public void exec(Env env, Scope scope, Writer writer) {
if (paraNum == 0) {
outputToday(env, writer);
} else if (paraNum == 1) {
if (paraNum == 1) {
outputWithoutDatePattern(env, scope, writer);
} else if (paraNum == 2) {
outputWithDatePattern(env, scope, writer);
} else {
outputToday(env, writer);
}
}
private void outputToday(Env env, Writer writer) {
Object value = format(new java.util.Date(), env.getEngineConfig().getDatePattern());
write(writer, value.toString());
write(writer, new Date(), env.getEngineConfig().getDatePattern());
}
private void outputWithoutDatePattern(Env env, Scope scope, Writer writer) {
Object value = valueExpr.eval(scope);
if (value != null) {
value = format(value, env.getEngineConfig().getDatePattern());
write(writer, value.toString());
write(writer, (Date)value, env.getEngineConfig().getDatePattern());
}
}
@@ -88,18 +90,18 @@ public class DateDirective extends Directive {
return ;
}
Object dp = this.datePatternExpr.eval(scope);
if ( !(dp instanceof String) ) {
throw new TemplateException("The sencond parameter dataPattern of #date directive must be String", location);
Object datePattern = this.datePatternExpr.eval(scope);
if ( !(datePattern instanceof String) ) {
throw new TemplateException("The sencond parameter datePattern of #date directive must be String", location);
}
value = format(value, (String)dp);
write(writer, value.toString());
write(writer, (Date)value, (String)datePattern);
}
private String format(Object value, String datePattern) {
private void write(Writer writer, Date date, String datePattern) {
try {
return new SimpleDateFormat(datePattern).format(value);
} catch (Exception e) {
writer.write(date, datePattern);
} catch (IOException e) {
throw new TemplateException(e.getMessage(), location, e);
}
}

View File

@@ -16,9 +16,9 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Scope;
/**

View File

@@ -16,12 +16,13 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.io.IOException;
import java.util.Date;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;
@@ -39,22 +40,21 @@ public class NowDirective extends Directive {
}
public void exec(Env env, Scope scope, Writer writer) {
String dataPattern;
String datePattern;
if (exprList.length() == 0) {
dataPattern = env.getEngineConfig().getDatePattern();
datePattern = env.getEngineConfig().getDatePattern();
} else {
Object dp = exprList.eval(scope);
if (dp instanceof String) {
dataPattern = (String)dp;
datePattern = (String)dp;
} else {
throw new TemplateException("The parameter of #new directive must be String", location);
throw new TemplateException("The parameter of #now directive must be String", location);
}
}
try {
String value = new SimpleDateFormat(dataPattern).format(new java.util.Date());
write(writer, value);
} catch (Exception e) {
writer.write(new Date(), datePattern);
} catch (IOException e) {
throw new TemplateException(e.getMessage(), location, e);
}
}

View File

@@ -0,0 +1,108 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.ext.directive;
import java.text.DecimalFormat;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;
/**
* #number 数字格式化输出指令
*
* 两种用法:
* 1#number(n) 用默认 pattern 输出变量中的值
* 2#number(n, "#.##") 用第二个参数指定的 pattern 输出变量中的值
*
* 注意:
* 1pattern 的使用与 java.text.DecimalFormat 的完全一样
* 在拿不定主意的时候可以在搜索引擎中搜索关键字DecimalFormat
* 2#number 指令中的参数可以是变量,例如:#number(n, p) 中的 n 与 p 可以全都是变量
*
* <pre>
* 示例:
* #number(3.1415926, "#.##")
* #number(0.9518, "#.##%")
* #number(300000, "光速为每秒 ,### 公里。")
*
* #set(n = 1.234)
* #set(p = "#.##")
* #number(n, p)
* </pre>
*/
public class NumberDirective extends Directive {
private Expr valueExpr;
private Expr patternExpr;
private int paraNum;
public void setExprList(ExprList exprList) {
this.paraNum = exprList.length();
if (paraNum == 0) {
throw new ParseException("The parameter of #number directive can not be blank", location);
}
if (paraNum > 2) {
throw new ParseException("Wrong number parameter of #number directive, two parameters allowed at most", location);
}
if (paraNum == 1) {
this.valueExpr = exprList.getExpr(0);
this.patternExpr = null;
} else if (paraNum == 2) {
this.valueExpr = exprList.getExpr(0);
this.patternExpr = exprList.getExpr(1);
}
}
public void exec(Env env, Scope scope, Writer writer) {
Object value = valueExpr.eval(scope);
if (value == null) {
return ;
}
if (paraNum == 1) {
outputWithoutPattern(writer, value);
} else if (paraNum == 2) {
outputWithPattern(scope, writer, value);
}
}
private void outputWithoutPattern(Writer writer, Object value) {
String ret = new DecimalFormat().format(value);
write(writer, ret);
}
private void outputWithPattern(Scope scope, Writer writer, Object value) {
Object pattern = patternExpr.eval(scope);
if ( !(pattern instanceof String) ) {
throw new TemplateException("The sencond parameter pattern of #number directive must be String", location);
}
String ret = new DecimalFormat((String)pattern).format(value);
write(writer, ret);
}
}

View File

@@ -16,9 +16,9 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.Scope;
/**

View File

@@ -16,7 +16,6 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import com.jfinal.template.Directive;
@@ -25,6 +24,7 @@ import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Assign;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.source.ISource;
import com.jfinal.template.stat.Ctrl;
import com.jfinal.template.stat.ParseException;
@@ -33,6 +33,7 @@ import com.jfinal.template.stat.Scope;
import com.jfinal.template.stat.ast.Define;
import com.jfinal.template.stat.ast.Include;
import com.jfinal.template.stat.ast.Stat;
import com.jfinal.template.stat.ast.StatList;
/**
* #render 指令用于动态渲染子模板,作为 include 指令的补充
@@ -111,7 +112,7 @@ public class RenderDirective extends Directive {
if (statInfo == null) {
statInfo = parseStatInfo(env, subFileName);
statInfoCache.put(subFileName, statInfo);
} else if (env.getEngineConfig().isDevMode()) {
} else if (env.isDevMode()) {
// statInfo.env.isSourceListModified() 逻辑可以支持 #render 子模板中的 #include 过来的子模板在 devMode 下在修改后可被重加载
if (statInfo.source.isModified() || statInfo.env.isSourceListModified()) {
statInfo = parseStatInfo(env, subFileName);
@@ -130,8 +131,8 @@ public class RenderDirective extends Directive {
try {
EnvSub envSub = new EnvSub(env);
Stat stat = new Parser(envSub, fileSource.getContent(), subFileName).parse();
return new StatInfo(envSub, stat, fileSource);
StatList statList = new Parser(envSub, fileSource.getContent(), subFileName).parse();
return new StatInfo(envSub, statList.getActualStat(), fileSource);
} catch (Exception e) {
throw new ParseException(e.getMessage(), location, e);
}

View File

@@ -16,10 +16,11 @@
package com.jfinal.template.ext.directive;
import java.io.Writer;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.FastStringWriter;
import com.jfinal.template.io.CharWriter;
import com.jfinal.template.io.FastStringWriter;
import com.jfinal.template.io.Writer;
import com.jfinal.template.expr.ast.Const;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
@@ -68,8 +69,14 @@ public class StringDirective extends Directive {
}
public void exec(Env env, Scope scope, Writer writer) {
CharWriter charWriter = new CharWriter(64);
FastStringWriter fsw = new FastStringWriter();
stat.exec(env, scope, fsw);
charWriter.init(fsw);
try {
stat.exec(env, scope, charWriter);
} finally {
charWriter.close();
}
if (this.isLocalAssignment) {
scope.setLocal(name, fsw.toString());

View File

@@ -0,0 +1,81 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.ext.sharedmethod;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
/**
* SharedMethodLib 共享方法库,逐步添加一些最常用的共享方法
*
* <br>
* 3.3 版本之前的 Logic.isTrue(Object) 方法不再对 Collection、
* Map、数组、Iterator、Iterable 进行为空的判断,这部分逻辑已转移至
* SharedMethodLib.isEmpty(Object)
*/
public class SharedMethodLib {
/**
* 判断 Collection、Map、数组、Iterator、Iterable 类型对象中的元素个数是否为 0
* 规则:
* 1null 返回 true
* 2List、Set 等一切继承自 Collection 的,返回 isEmpty()
* 3Map 返回 isEmpty()
* 4数组返回 length == 0
* 5Iterator 返回 ! hasNext()
* 6Iterable 返回 ! iterator().hasNext()
*
* 注意:原先 Logic.isTrue(Object) 中对集合与数组类型为空的判断转移到此方法中
*/
public Boolean isEmpty(Object v) {
if (v == null) {
return true;
}
if (v instanceof Collection) {
return ((Collection<?>)v).isEmpty();
}
if (v instanceof Map) {
return ((Map<?, ?>)v).isEmpty();
}
if (v.getClass().isArray()) {
return Array.getLength(v) == 0;
}
if (v instanceof Iterator) {
return ! ((Iterator<?>)v).hasNext();
}
if (v instanceof Iterable) {
return ! ((Iterable<?>)v).iterator().hasNext();
}
throw new IllegalArgumentException("isEmpty(...) 方法只能接受 Collection、Map、数组、Iterator、Iterable 类型参数");
}
public Boolean notEmpty(Object v) {
return !isEmpty(v);
}
}

View File

@@ -16,7 +16,7 @@
package com.jfinal.template.ext.spring;
import java.io.Writer;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@@ -56,9 +56,8 @@ public class JFinalView extends AbstractTemplateView {
}
}
Writer writer = response.getWriter();
JFinalViewResolver.engine.getTemplate(getUrl()).render(model, writer);
writer.flush();
OutputStream os = response.getOutputStream();
JFinalViewResolver.engine.getTemplate(getUrl()).render(model, os);
}
}

View File

@@ -18,7 +18,9 @@ package com.jfinal.template.ext.spring;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.servlet.ServletContext;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
import com.jfinal.kit.StrKit;
import com.jfinal.template.Directive;
@@ -54,6 +56,15 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
static boolean sessionInView = false;
static boolean createSession = true;
private static JFinalViewResolver me = null;
/**
* me 会保存在第一次被创建对象
*/
public static JFinalViewResolver me() {
return me;
}
public Engine getEngine() {
return engine;
}
@@ -83,6 +94,24 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
}
}
/**
* 通过 List 配置多个 shared function file
* <pre>
* 配置示例:
* <property name="sharedFunctionList">
* <list>
* <value>_layout.html</value>
* <value>_paginate.html</value>
* </list>
* </property>
* </pre>
*/
public void setSharedFunctionList(List<String> sharedFunctionList) {
if (sharedFunctionList != null) {
JFinalViewResolver.sharedFunctionFiles.addAll(sharedFunctionList);
}
}
/**
* 添加 shared function 文件,可调用多次添加多个文件
*/
@@ -94,8 +123,16 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
/**
* 添加自定义指令
*/
public void addDirective(String directiveName, Class<? extends Directive> directiveClass) {
engine.addDirective(directiveName, directiveClass);
}
/**
* 添加自定义指令,已被 addDirective(String, Class<? extends Directive>) 方法取代
*/
@Deprecated
public void addDirective(String directiveName, Directive directive) {
engine.addDirective(directiveName, directive);
addDirective(directiveName, directive.getClass());
}
/**
@@ -196,6 +233,12 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
// ---------------------------------------------------------------
public JFinalViewResolver() {
synchronized(JFinalViewResolver.class) {
if (me == null) {
me = this;
}
}
setViewClass(requiredViewClass());
setOrder(0);
setContentType("text/html;charset=UTF-8");
@@ -208,12 +251,30 @@ public class JFinalViewResolver extends AbstractTemplateViewResolver {
return JFinalView.class;
}
/**
* 支持 jfinal enjoy、jsp、freemarker、velocity 四类模板共存于一个项目中
*
* 注意:这里采用识别 ".jsp"、".ftl"、".vm" 模板后缀名的方式来实现功能
* 所以 jfinal enjoy 模板不要采用上述三种后缀名,否则功能将失效
* 还要注意与 jsp、freemarker、velocity 以外类型模板共存使用时
* 需要改造该方法
*/
protected View loadView(String viewName, Locale locale) throws Exception {
String suffix = getSuffix();
if (".jsp".equals(suffix) || ".ftl".equals(suffix) || ".vm".equals(suffix)) {
return null;
} else {
return super.loadView(viewName, locale);
}
}
/**
* spring 回调,利用 ServletContext 做必要的初始化工作
*/
@Override
protected void initServletContext(ServletContext servletContext) {
super.initServletContext(servletContext);
super.setExposeRequestAttributes(true);
initBaseTemplatePath(servletContext);
initSharedFunction();