Comments (7)
数据格式化器[实现类 1/2]
package jetbrick.template.formatter;
/**
*
* 默认对象格式化器,直接调用object.toString()
*
* @author 应卓([email protected])
*
*/
public class DefaultObjectFormatter implements ObjectFormatter {
@Override
public String format(Object object) {
return object != null ? object.toString() : "";
}
@Override
public boolean supports(Class<?> objectType) {
return true;
}
}
数据格式化器[实现类 2/2]
package jetbrick.template.formatter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import jetbrick.template.parser.support.ClassUtils;
/**
*
* 默认的java.util.Date与java.util.Calendar格式化器
*
* @author 应卓([email protected])
*
*/
public class TimeObjectFormatter implements ObjectFormatter {
private static final DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
@Override
public String format(Object object) {
return FORMAT.format(object);
}
@Override
public boolean supports(Class<?> objectType) {
return ClassUtils.isAssignable(Date.class, objectType) ||
ClassUtils.isAssignable(Calendar.class, objectType);
}
}
from jetbrick-template-1x.
数据格式化器的查找器[接口]
package jetbrick.template.formatter;
/**
* 数据格式化器的查找器
*
* @author 应卓([email protected])
*
*/
public interface ObjectFormatterFinder {
/**
* 查找
*
* @param object 要格式化的数据
* @return 相适应的格式化器,如果有多个匹配的,只返回第一个
*/
public ObjectFormatter find(Object object);
}
数据格式化器的查找器实现类
package jetbrick.template.formatter;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import jetbrick.template.JetEngine;
/**
* 默认数据格式化器的查找器,使用缓存机制
*
* @author 应卓([email protected])
*
*/
public class DefaultObjectFormatterFinder implements ObjectFormatterFinder {
private static final ObjectFormatter DEFAULT = new DefaultObjectFormatter();
private final List<ObjectFormatter> objectFormatters;
private final Map<Class<?>, ObjectFormatter> cache = new IdentityHashMap<Class<?>, ObjectFormatter>(4096);
public DefaultObjectFormatterFinder(JetEngine jetEngine) {
super();
this.objectFormatters = jetEngine.getObjectFormatters();
}
@Override
public ObjectFormatter find(Object object) {
if (object == null) {
return DEFAULT;
}
Class<?> klass = object.getClass();
ObjectFormatter cached = cache.get(klass);
if (cached != null) {
return cached;
} else {
for (ObjectFormatter formatter : this.objectFormatters) {
if (formatter.supports(klass)) {
cache.put(klass, formatter);
return formatter;
}
}
}
// 不会到这里来
return DEFAULT;
}
}
from jetbrick-template-1x.
配置项添加object.formatters
相应修改JetConfig和JetEngine
package jetbrick.template;
import java.io.File;
import java.util.List;
import java.util.Properties;
import jetbrick.template.resource.loader.FileSystemResourceLoader;
import jetbrick.template.utils.ConfigSupport;
import jetbrick.template.utils.PathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JetConfig extends ConfigSupport<JetConfig> {
public static final String DEFAULT_CONFIG_FILE = "jetbrick-template.properties";
public static final String IMPORT_PACKAGES = "import.packages";
public static final String IMPORT_CLASSES = "import.classes";
public static final String IMPORT_METHODS = "import.methods";
public static final String IMPORT_FUNCTIONS = "import.functions";
public static final String IMPORT_TAGS = "import.tags";
public static final String IMPORT_VARIABLES = "import.variables";
public static final String INPUT_ENCODING = "input.encoding";
public static final String OUTPUT_ENCODING = "output.encoding";
public static final String TEMPLATE_LOADER = "template.loader";
public static final String TEMPLATE_PATH = "template.path";
public static final String TEMPLATE_SUFFIX = "template.suffix";
public static final String TEMPLATE_RELOADABLE = "template.reloadable";
public static final String COMPILE_ALWAYS = "compile.always";
public static final String COMPILE_DEBUG = "compile.debug";
public static final String COMPILE_PATH = "compile.path";
public static final String TRIM_DIRECTIVE_LINE = "trim.directive.line";
public static final String TRIM_DIRECTIVE_COMMENTS = "trim.directive.comments";
public static final String TRIM_DIRECTIVE_COMMENTS_PREFIX = "trim.directive.comments.prefix";
public static final String TRIM_DIRECTIVE_COMMENTS_SUFFIX = "trim.directive.comments.suffix";
public static final String OBJECT_FORMATTERS = "object.formatters";
private final Logger log = LoggerFactory.getLogger(JetConfig.class);
private List<String> importPackages;
private List<String> importClasses;
private List<String> importMethods;
private List<String> importFunctions;
private List<String> importTags;
private List<String> importVariables;
private String inputEncoding;
private String outputEncoding;
private Class<?> templateLoader;
private String templatePath;
private String templateSuffix;
private boolean templateReloadable;
private boolean compileAlways;
private boolean compileDebug;
private String compilePath;
private boolean trimDirectiveLine;
private boolean trimDirectiveComments;
private String trimDirectiveCommentsPrefix;
private String trimDirectiveCommentsSuffix;
private List<String> objectFormatters;
public JetConfig() {
// default config
String defaultCompilePath = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
Properties config = new Properties();
config.setProperty(INPUT_ENCODING, "utf-8");
config.setProperty(OUTPUT_ENCODING, "utf-8");
config.setProperty(TEMPLATE_LOADER, FileSystemResourceLoader.class.getName());
config.setProperty(TEMPLATE_PATH, PathUtils.getCurrentPath());
config.setProperty(TEMPLATE_SUFFIX, ".jetx");
config.setProperty(TEMPLATE_RELOADABLE, "false");
config.setProperty(COMPILE_ALWAYS, "true");
config.setProperty(COMPILE_DEBUG, "false");
config.setProperty(COMPILE_PATH, defaultCompilePath);
config.setProperty(TRIM_DIRECTIVE_LINE, "true");
config.setProperty(TRIM_DIRECTIVE_COMMENTS, "false");
config.setProperty(TRIM_DIRECTIVE_COMMENTS_PREFIX, "<!--");
config.setProperty(TRIM_DIRECTIVE_COMMENTS_SUFFIX, "-->");
load(config);
}
@Override
public JetConfig build() {
super.build();
// log
if (log.isInfoEnabled()) {
log.info("Load template from \"" + templatePath + "\" by " + templateLoader + ".");
if (templateReloadable) {
log.info("autoload on: template will automatically reload.");
} else {
log.info("autoload off: template will NOT automatically reload.");
}
}
return this;
}
public List<String> getImportPackages() {
return importPackages;
}
public List<String> getImportClasses() {
return importClasses;
}
public List<String> getImportMethods() {
return importMethods;
}
public List<String> getImportFunctions() {
return importFunctions;
}
public List<String> getImportTags() {
return importTags;
}
public List<String> getImportVariables() {
return importVariables;
}
public String getInputEncoding() {
return inputEncoding;
}
public String getOutputEncoding() {
return outputEncoding;
}
public Class<?> getTemplateLoader() {
return templateLoader;
}
public String getTemplatePath() {
return templatePath;
}
public String getTemplateSuffix() {
return templateSuffix;
}
public boolean isTemplateReloadable() {
return templateReloadable;
}
public boolean isCompileAlways() {
return compileAlways;
}
public boolean isCompileDebug() {
return compileDebug;
}
public String getCompilePath() {
return compilePath;
}
public boolean isTrimDirectiveLine() {
return trimDirectiveLine;
}
public boolean isTrimDirectiveComments() {
return trimDirectiveComments;
}
public String getTrimDirectiveCommentsPrefix() {
return trimDirectiveCommentsPrefix;
}
public String getTrimDirectiveCommentsSuffix() {
return trimDirectiveCommentsSuffix;
}
public List<String> getObjectFormatters() {
return objectFormatters;
}
}
package jetbrick.template;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import jetbrick.template.compiler.JavaCompiler;
import jetbrick.template.compiler.JetTemplateClassLoader;
import jetbrick.template.formatter.DefaultObjectFormatter;
import jetbrick.template.formatter.ObjectFormatter;
import jetbrick.template.formatter.TimeObjectFormatter;
import jetbrick.template.parser.VariableResolver;
import jetbrick.template.parser.support.ClassUtils;
import jetbrick.template.resource.Resource;
import jetbrick.template.resource.SourceCodeResource;
import jetbrick.template.resource.loader.ResourceLoader;
import jetbrick.template.utils.ConcurrentCache;
import jetbrick.template.utils.ExceptionUtils;
import jetbrick.template.utils.PathUtils;
import jetbrick.template.utils.Version;
public class JetEngine {
public static final String VERSION = Version.getVersion(JetEngine.class);
private final JetConfig config;
private final ResourceLoader resourceLoader;
private final VariableResolver resolver;
private final JetTemplateClassLoader classLoader;
private final JavaCompiler javaCompiler;
private final ConcurrentResourceCache resourceCache;
private final ConcurrentTemplateCache templateCache;
private final List<ObjectFormatter> objectFormatters;
public static JetEngine create() {
return new JetEngine(new JetConfig().loadClasspath(JetConfig.DEFAULT_CONFIG_FILE));
}
public static JetEngine create(File configFile) {
return new JetEngine(new JetConfig().loadFile(configFile));
}
public static JetEngine create(Properties properties) {
return new JetEngine(new JetConfig().load(properties));
}
protected JetEngine(JetConfig config) {
this.config = config.build();
this.resolver = createVariableResolver();
this.resourceLoader = createResourceLoader();
this.classLoader = new JetTemplateClassLoader(config.getCompilePath(), config.isTemplateReloadable());
this.javaCompiler = JavaCompiler.create(this.classLoader);
this.resourceCache = new ConcurrentResourceCache();
this.templateCache = new ConcurrentTemplateCache();
// 初始化ojectFormatters
List<ObjectFormatter> formatters = new ArrayList<ObjectFormatter>();
for (String klassName : config.getObjectFormatters()) {
Class<?> klass = resolver.resolveClass(klassName);
if (klass == null) continue;
// 用户配置错误,类型并没有实现ObjectFormatter接口
if (! ClassUtils.isAssignable(ObjectFormatter.class, klass)) {
throw new ClassCastException("class '" + klass.getName() + "' is not a implemention of type '" + ObjectFormatter.class.getName() + "'");
}
// 创建对象
try {
formatters.add((ObjectFormatter) klass.newInstance());
} catch (Exception e) {
throw ExceptionUtils.uncheck(e);
}
}
formatters.add(new TimeObjectFormatter());
formatters.add(new DefaultObjectFormatter());
this.objectFormatters = Collections.unmodifiableList(formatters);
}
/**
* 根据一个绝对路径,判断资源文件是否存在
*/
public boolean lookupResource(String name) {
name = PathUtils.getStandardizedName(name);
return resourceCache.get(name) != null;
}
/**
* 根据一个绝对路径,获取一个资源对象
* @throws ResourceNotFoundException
*/
public Resource getResource(String name) throws ResourceNotFoundException {
name = PathUtils.getStandardizedName(name);
Resource resource = resourceCache.get(name);
if (resource == null) {
throw new ResourceNotFoundException(name);
}
return resource;
}
/**
* 根据一个绝对路径,获取一个模板对象
* @throws ResourceNotFoundException
*/
public JetTemplate getTemplate(String name) throws ResourceNotFoundException {
name = PathUtils.getStandardizedName(name);
JetTemplate template = templateCache.get(name);
template.checkLastModified();
return template;
}
/**
* 直接从源代码中创建一个新的模板对象
*/
public JetTemplate createTemplate(String source) {
Resource resource = new SourceCodeResource(source);
return new JetTemplate(this, resource);
}
protected VariableResolver getVariableResolver() {
return resolver;
}
protected JetTemplateClassLoader getClassLoader() {
return classLoader;
}
protected JavaCompiler getJdkCompiler() {
return javaCompiler;
}
/**
* 获取模板配置
*/
public JetConfig getConfig() {
return config;
}
/**
* 获取模板引擎的版本号
*/
public String getVersion() {
return VERSION;
}
private VariableResolver createVariableResolver() {
VariableResolver resolver = new VariableResolver();
for (String pkg : config.getImportPackages()) {
resolver.addImportPackage(pkg);
}
for (String klassName : config.getImportClasses()) {
resolver.addImportClass(klassName);
}
for (String method : config.getImportMethods()) {
resolver.addMethodClass(method);
}
for (String function : config.getImportFunctions()) {
resolver.addFunctionClass(function);
}
for (String tag : config.getImportTags()) {
resolver.addTagClass(tag);
}
for (String variable : config.getImportVariables()) {
int pos = variable.lastIndexOf(" ");
String defination = variable.substring(0, pos);
String id = variable.substring(pos + 1);
resolver.addGlobalVariable(defination, id);
}
return resolver;
}
private ResourceLoader createResourceLoader() {
try {
ResourceLoader resourceLoader = (ResourceLoader) config.getTemplateLoader().newInstance();
resourceLoader.initialize(config.getTemplatePath(), config.getInputEncoding());
return resourceLoader;
} catch (Exception e) {
throw ExceptionUtils.uncheck(e);
}
}
private class ConcurrentResourceCache extends ConcurrentCache<String, Resource> {
@Override
public Resource doGetValue(String name) {
return JetEngine.this.resourceLoader.load(name);
}
}
private class ConcurrentTemplateCache extends ConcurrentCache<String, JetTemplate> {
@Override
public JetTemplate doGetValue(String name) {
Resource resource = JetEngine.this.getResource(name);
return new JetTemplate(JetEngine.this, resource);
}
}
public List<ObjectFormatter> getObjectFormatters() {
return objectFormatters;
}
}
from jetbrick-template-1x.
JetWriter API变更
package jetbrick.template.runtime;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import jetbrick.template.JetEngine;
import jetbrick.template.formatter.DefaultObjectFormatterFinder;
import jetbrick.template.formatter.ObjectFormatter;
import jetbrick.template.formatter.ObjectFormatterFinder;
public abstract class JetWriter {
private ObjectFormatterFinder objectFormatterFinder;
// ========================================================================
// 应卓标记两个方法为过时
@Deprecated
public static JetWriter create(Writer os, String encoding) {
throw new UnsupportedOperationException();
}
@Deprecated
public static JetWriter create(OutputStream os, String encoding) {
throw new UnsupportedOperationException();
}
// ========================================================================
public static JetWriter create(JetEngine jetEngine, Writer os, String encoding) {
return new JetWriterImpl(jetEngine, os, encoding);
}
public static JetWriter create(JetEngine jetEngine, OutputStream os, String encoding) {
return new JetOutputStreamImpl(jetEngine, os, encoding);
}
public JetWriter(JetEngine jetEngine) {
objectFormatterFinder = new DefaultObjectFormatterFinder(jetEngine);
}
public abstract boolean isStreaming();
public abstract void print(String text, byte[] bytes) throws IOException;
public void print(boolean x) throws IOException {
print(x ? "true" : "false");
}
public void print(byte x) throws IOException {
print(String.valueOf(x));
}
public void print(char x) throws IOException {
print(String.valueOf(x));
}
public void print(short x) throws IOException {
print(String.valueOf(x));
}
public void print(int x) throws IOException {
print(String.valueOf(x));
}
public void print(long x) throws IOException {
print(String.valueOf(x));
}
public void print(float x) throws IOException {
print(String.valueOf(x));
}
public void print(double x) throws IOException {
print(String.valueOf(x));
}
public abstract void print(byte x[]) throws IOException;
public abstract void print(char x[]) throws IOException;
public abstract void print(CharSequence x) throws IOException;
public void print(Object x) throws IOException {
if (x != null) {
if (x instanceof byte[]) {
print((byte[]) x);
} else if (x instanceof char[]) {
print((char[]) x);
} else {
ObjectFormatter formatter = this.objectFormatterFinder.find(x);
print(formatter.format(x));
}
}
}
public abstract void println() throws IOException;
public void println(boolean x) throws IOException {
print(x);
println();
}
public void println(byte x) throws IOException {
print(x);
println();
}
public void println(char x) throws IOException {
print(x);
println();
}
public void println(short x) throws IOException {
print(x);
println();
}
public void println(int x) throws IOException {
print(x);
println();
}
public void println(long x) throws IOException {
print(x);
println();
}
public void println(float x) throws IOException {
print(x);
println();
}
public void println(double x) throws IOException {
print(x);
println();
}
public void println(byte x[]) throws IOException {
if (x != null) {
print(x);
println();
}
}
public void println(char x[]) throws IOException {
if (x != null) {
print(x);
println();
}
}
public void println(CharSequence x) throws IOException {
if (x != null) {
print(x);
println();
}
}
public void println(Object x) throws IOException {
if (x != null) {
print(x);
println();
}
}
public abstract void flush() throws IOException;
public abstract void close() throws IOException;
static class JetWriterImpl extends JetWriter {
private static final String NEWLINE = "\r\n";
private final Writer os;
private final String encoding;
public JetWriterImpl(JetEngine jetEngine, Writer os, String encoding) {
super(jetEngine);
this.os = os;
this.encoding = encoding;
}
@Override
public boolean isStreaming() {
return false;
}
@Override
public void print(String text, byte[] bytes) throws IOException {
os.write(text);
}
@Override
public void print(byte x[]) throws IOException {
if (x != null) {
os.write(new String(x, encoding));
}
}
@Override
public void print(char x[]) throws IOException {
if (x != null) {
os.write(x);
}
}
@Override
public void print(CharSequence x) throws IOException {
if (x != null) {
os.write(x.toString());
}
}
@Override
public void println() throws IOException {
os.write(NEWLINE);
}
@Override
public void flush() throws IOException {
os.flush();
}
@Override
public void close() throws IOException {
os.close();
}
}
static class JetOutputStreamImpl extends JetWriter {
private static final byte[] NEWLINE = new byte[] { '\r', '\n' };
private final OutputStream os;
private final String encoding;
public JetOutputStreamImpl(JetEngine jetEngine, OutputStream os, String encoding) {
super(jetEngine);
this.os = os;
this.encoding = encoding;
}
@Override
public boolean isStreaming() {
return true;
}
@Override
public void print(String text, byte[] bytes) throws IOException {
os.write(bytes);
}
@Override
public void print(byte x[]) throws IOException {
if (x != null) {
os.write(x);
}
}
@Override
public void print(char x[]) throws IOException {
if (x != null) {
os.write(new String(x).getBytes(encoding));
}
}
@Override
public void print(CharSequence x) throws IOException {
if (x != null) {
os.write(x.toString().getBytes(encoding));
}
}
@Override
public void println() throws IOException {
os.write(NEWLINE);
}
@Override
public void flush() throws IOException {
os.flush();
}
@Override
public void close() throws IOException {
os.close();
}
}
}
from jetbrick-template-1x.
由于JetWriter.create(...) API变化了,还要修改相应的 JetTemplate 和 JetTagContent
package jetbrick.template.runtime;
import jetbrick.template.JetContext;
import jetbrick.template.JetEngine;
import jetbrick.template.utils.ExceptionUtils;
import jetbrick.template.utils.UnsafeCharArrayWriter;
public abstract class JetTagContext {
public static final Class<?>[] CLASS_ARRAY = { JetTagContext.class };
private final JetPageContext ctx;
public JetTagContext(JetPageContext ctx) {
this.ctx = ctx;
}
public String getBodyContent() {
UnsafeCharArrayWriter out = new UnsafeCharArrayWriter();
String encoding = ctx.getEngine().getConfig().getOutputEncoding();
try {
render(ctx.getContext(), JetWriter.create(ctx.getEngine(), out, encoding));
} catch (Throwable e) {
throw ExceptionUtils.uncheck(e);
}
return out.toString();
}
public void writeBodyContent() {
try {
render(ctx.getContext(), ctx.getWriter());
} catch (Throwable e) {
throw ExceptionUtils.uncheck(e);
}
}
public JetPageContext getPageContext() {
return ctx;
}
public JetEngine getEngine() {
return ctx.getEngine();
}
public JetWriter getWriter() {
return ctx.getWriter();
}
public JetContext getContext() {
return ctx.getContext();
}
protected abstract void render(final JetContext context, final JetWriter out) throws Throwable;
}
package jetbrick.template;
import java.io.*;
import java.util.Map;
import jetbrick.template.parser.*;
import jetbrick.template.parser.code.Code;
import jetbrick.template.parser.grammer.*;
import jetbrick.template.parser.grammer.JetTemplateParser.TemplateContext;
import jetbrick.template.resource.Resource;
import jetbrick.template.runtime.*;
import jetbrick.template.utils.ExceptionUtils;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class JetTemplate {
private static final Logger log = LoggerFactory.getLogger(JetTemplate.class);
private final JetEngine engine;
private final Resource resource;
private final String encoding;
private final boolean reloadable;
private final File javaSourceFile;
private final File javaClassFile;
private JetPage pageObject;
protected JetTemplate(JetEngine engine, Resource resource) {
JetConfig config = engine.getConfig();
this.engine = engine;
this.resource = resource;
this.encoding = config.getOutputEncoding();
this.reloadable = config.isTemplateReloadable();
this.javaSourceFile = engine.getJdkCompiler().getGenerateJavaSourceFile(resource.getQualifiedClassName());
this.javaClassFile = engine.getJdkCompiler().getGenerateJavaClassFile(resource.getQualifiedClassName());
// compile and load
if ((!config.isCompileAlways()) && javaClassFile.lastModified() > resource.lastModified()) {
try {
loadClassFile();
} catch (Throwable e) {
// 无法 load 的话,尝试重新编译
log.warn(e.getClass().getName() + ": " + e.getMessage());
log.warn("Try to recompile the template.");
compileAndLoadClass();
}
} else {
compileAndLoadClass();
}
}
protected void checkLastModified() {
if (reloadable && javaClassFile.lastModified() < resource.lastModified()) {
synchronized (this) {
// double check
if (javaClassFile.lastModified() < resource.lastModified()) {
compileAndLoadClass();
}
}
}
}
// 从 disk 的缓存文件中读取
private void loadClassFile() throws Exception {
log.info("Loading template class file: " + javaClassFile.getAbsolutePath());
Class<?> cls = engine.getClassLoader().loadClass(resource.getQualifiedClassName());
// 判断编码匹配
if (!encoding.equals(cls.getDeclaredField("$ENC").get(null))) {
throw new IllegalStateException("The encoding of last compiled template class is not " + encoding);
}
pageObject = (JetPage) cls.newInstance();
}
// 编译 source 为 class, 然后 load class
private void compileAndLoadClass() {
log.info("Loading template source file: " + resource.getAbsolutePath());
// generateJavaSource
String source = generateJavaSource(resource);
if (log.isInfoEnabled() && engine.getConfig().isCompileDebug()) {
StringBuilder sb = new StringBuilder(source.length() + 128);
sb.append("generateJavaSource: ");
sb.append(javaSourceFile.getAbsolutePath());
sb.append("\n");
sb.append("===========================================================================\n");
sb.append(source);
sb.append("\n");
sb.append("===========================================================================");
log.info(sb.toString());
}
// compile
Class<?> cls = engine.getJdkCompiler().compile(resource.getQualifiedClassName(), source);
log.info("generateJavaClass: " + javaClassFile.getAbsolutePath());
try {
pageObject = (JetPage) cls.newInstance();
} catch (Exception e) {
throw ExceptionUtils.uncheck(e);
}
}
private String generateJavaSource(Resource resource) {
char[] source = resource.getSource();
ANTLRInputStream is = new ANTLRInputStream(source, source.length);
is.name = resource.getAbsolutePath(); // set source file name, it will be displayed in error report.
JetTemplateParser parser = new JetTemplateParser(new CommonTokenStream(new JetTemplateLexer(is)));
parser.removeErrorListeners(); // remove ConsoleErrorListener
parser.addErrorListener(new JetTemplateErrorListener());
parser.setErrorHandler(new JetTemplateErrorStrategy());
TemplateContext templateParseTree = parser.template();
JetTemplateCodeVisitor visitor = new JetTemplateCodeVisitor(engine, engine.getVariableResolver(), parser, resource);
Code code = templateParseTree.accept(visitor);
return code.toString();
}
public void render(Map<String, Object> context, Writer out) {
JetContext ctx = new JetContext(context);
JetWriter writer = JetWriter.create(this.engine, out, encoding);
render(new JetPageContext(this, ctx, writer));
}
public void render(Map<String, Object> context, OutputStream out) {
JetContext ctx = new JetContext(context);
JetWriter writer = JetWriter.create(this.engine, out, encoding);
render(new JetPageContext(this, ctx, writer));
}
public void render(JetContext context, Writer out) {
if (context.isSimpleModel()) {
// simpleModel 的情况代表是用户自己 new 出来的 JetContext
// 为了防止 #set 污染 context,这里重新 new 一个新的。
context = new JetContext(context.getContext());
}
JetWriter writer = JetWriter.create(this.engine, out, encoding);
render(new JetPageContext(this, context, writer));
}
public void render(JetContext context, OutputStream out) {
if (context.isSimpleModel()) {
// simpleModel 的情况代表是用户自己 new 出来的 JetContext
// 为了防止 #set 污染 context,这里重新 new 一个新的。
context = new JetContext(context.getContext());
}
JetWriter writer = JetWriter.create(this.engine, out, encoding);
render(new JetPageContext(this, context, writer));
}
public void render(JetContext context, JetWriter writer) {
render(new JetPageContext(this, context, writer));
}
private void render(JetPageContext ctx) {
try {
pageObject.render(ctx);
} catch (Throwable e) {
throw ExceptionUtils.uncheck(e);
}
}
public JetEngine getEngine() {
return engine;
}
public String getName() {
return resource.getName();
}
}
from jetbrick-template-1x.
Good Job.
不过下次建议用 pull request. 这个直接贴代码,太那个啥...
from jetbrick-template-1x.
我们公司不让我github 我只能用网页版。
from jetbrick-template-1x.
Related Issues (20)
- Map 的泛型类型推导问题
- Map, List 等常用类型访问时自动预判类型 HOT 4
- macro递归调用解析异常
- Mac环境PathUtilsTest单元测试失败
- for.size 对 Iterator 的支持 HOT 1
- define内部类生成错误$ HOT 1
- ClasspathResourceLoader 中文模板名称有问题 HOT 1
- 可否增加对jfinal的Model的get()方法? HOT 1
- servletContext 对象获取改进建议(JFinal 集成) HOT 1
- 引号不对称 造成图片路径被过滤 HOT 2
- 自定义tag的扩展
- 使用jetbrick每次启动时都报错:ClientAbortException 但功能不影响
- WebLogic10.3.x下 ClasspathResourceLoader 无法加载资源 HOT 1
- 除法BUG HOT 3
- JFinal 模板 JetTemplateRender.java 有朋友反馈在 chrome 下 content type 为 text/plain
- Cannot get object in tag within for directive
- 压缩下生成的html HOT 1
- 改善预编译速度,使用多线程编译
- import.classes 相关 log 没有正确输出
- @Permission.view_schoolOrg 静态字段编译错误 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jetbrick-template-1x.