Coder Social home page Coder Social logo

jetbrick-template-1x's People

Contributors

subchen avatar wendal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jetbrick-template-1x's Issues

增加选项: compile.always 第一次访问模板强制编译

如果模板对应的 outputEncoding 变了,如果 jdk 版本变了,如果模板内引用的对象实现变了...

针对这些问题,增加一个选项 compile.always ,第一次访问模板的时候,强制编译,而不是尝试从磁盘中读取以前编译的 class。

默认 compile.alwaystrue

增加 annotation 自动扫描查找 Methods / Functions / Tags

提供 Annotation Class

@JetMethods
@JetFunctions
@JetTags

然后在对应的 Class 上面增加 Annotation 就会生效。

@JetMethods
public class StringMethods {

     public static String link(String text, String url) {
          return "<a href=\"" + url + "\">" + text + "</a>";
     }

     ...
}

不过由于扫描 classpath 需要一些时间,准备加一个配置选项是否开启,默认是关闭的。

import.autoscan = false

对于 ${bean.property},优先使用 getXXX()

getXXX() 方法比直接读取 Field 更通用,所以优先级应该更高。

调整如下:

  1. 查找 obj.getFoo() 方法
  2. 查找 obj.isFoo() 方法
  3. 查找 obj class 的 foo 字段
  4. 查找 obj.get(name) 方法 (如果是 Map 或者 JetContext)

启用 trim.directive.comments 的时候,出现 NullPointerException

模板:

<!-- #set(String title = "") -->

开启

trim.directive.comments = true

出现 NullPointerException

java.lang.NullPointerException: null
    at jetbrick.template.parser.code.TextCode.trimEmptyLine(TextCode.java:62) ~[bin/:na]
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:201) ~[bin/:na]
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:1) ~[bin/:na]
    at jetbrick.template.parser.grammer.JetTemplateParser$BlockContext.accept(JetTemplateParser.java:154) ~[bin/:na]
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:148) ~[bin/:na]
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:1) ~[bin/:na]
    at jetbrick.template.parser.grammer.JetTemplateParser$TemplateContext.accept(JetTemplateParser.java:104) ~[bin/:na]
    at jetbrick.template.JetTemplate.generateJavaSource(JetTemplate.java:135) ~[bin/:na]
    at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:101) ~[bin/:na]
    at jetbrick.template.JetTemplate.<init>(JetTemplate.java:68) ~[bin/:na]
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:179) ~[bin/:na]
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:1) ~[bin/:na]
    at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:44) ~[bin/:na]
    at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92) ~[bin/:na]

#if #else #end 语句后面貌似丢了一个换行

java code:

JetContext context = new JetContext();
context.put("flag", Boolean.FALSE);

jetx:

========
IF语句:#if(flag)flag为true#else()flag为false#end
========

output

========
IF语句:flag为false========

version

1.1.0

不支持 servlet 2.x 版本,目前只支持 servlet 3.x (from songlei)

谢谢你贡献了jetbrick,函数/方法扩展特性思路很棒。

不过在试用时,出现 java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getServletContext 异常
(可见附件内详细信息)。我试着将依赖改为servlet-api-3.0.1,还是有这个异常。不知是否和容器有关?!
(我用的是jetty-maven-plugin 7.2.0).

期待您的回复。

songlei.

java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getServletContext()Ljavax/servlet/ServletContext;
at jetbrick.template.web.JetWebContext.(JetWebContext.java:65)
at jetbrick.template.web.springmvc.JetTemplateView.renderMergedTemplateModel(JetTemplateView.java:36)
at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:533)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:475)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:514)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:920)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:403)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:184)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:856)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:247)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:151)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:114)
at org.eclipse.jetty.server.Server.handle(Server.java:352)
at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:596)
at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1049)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:590)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:212)
at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:426)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:510)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.access$000(SelectChannelEndPoint.java:34)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:40)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:450)
at java.lang.Thread.run(Thread.java:662)

从 request uri 中获取模板路径存在问题,会出现404错误

主要是这几个方法的返回值的使用方式问题:

request.getServletPath()
request.getPathInfo()
request.getRequestURI()

其中 request.getRequestURI() 的返回值包含了 request.getContextPath(),所以是相对于网站的根目录的。

下面我们分析 request.getServletPath()request.getPathInfo()

  1. 如果我们的 servlet-mapping 如下配置:

    <servlet-mapping>
      <servlet-name>jetbrick-template</servlet-name>
      <url-pattern>*.jetx</url-pattern>
    </servlet-mapping>

    那么访问: /context/templates/index.jetx

    request.getServletPath() == "/templates/index.jetx"
    request.getPathInfo() == <null>
  2. 如果我们的 servlet-mapping 如下配置:

    <servlet-mapping>
      <servlet-name>jetbrick-template</servlet-name>
      <url-pattern>/*</url-pattern>
    </servlet-mapping>

    那么访问: /context/templates/index.jetx

    request.getServletPath() == ""
    request.getPathInfo() == "/templates/index.jetx"
  3. 如果我们的 servlet-mapping 如下配置:

    <servlet-mapping>
      <servlet-name>jetbrick-template</servlet-name>
      <url-pattern>/template/*</url-pattern>
    </servlet-mapping>

    那么访问: /context/templates/index.jetx

    request.getServletPath() == "/templates"
    request.getPathInfo() == "/index.jetx"

总结

所以,我们要获取相对于 request.getContextPath() 的路径,我们可以使用如下的代码:

String uri = request.getServletPath();
String pathInfo = request.getPathInfo();
if (pathInfo != null && pathInfo.length() > 0) {
    uri = uri + pathInfo;
}

或者:

String uri = request.getRequestURI();
String contextPath = request.getContextPath();
if (contextPath != null && contextPath.length() > 0) {
    uri = uri.substring(contextPath.length());
}

compile.path 配置路径移除 jetx_x_x_x 的路径后缀

目前在用户配置的 compile.path 后面会新建一个 jetx_x_x_x 的目录来存放编译的 java 和 class 文件

目前由于默认开启了 compile.always = true,不会存在 class 版本的冲突问题,可以移除这个默认添加的 jetx_x_x_x 的目录。

用户配置什么目录,就是什么目录。

当然默认的还是在 System.getProperty("java.io.temp") + "/" + "jetx_" + version

tomcat 目录中带空格,template 编译失败

===========================================================================
2013-12-13 16:56:00,054 com.jfinal.core.ActionHandler.handle(ActionHandler.java:123) com.jfinal.core.ActionHandler
ERROR: /
jetbrick.template.compiler.CompileErrorException: Compilation failed.
package jetbrick.template does not exist
   2:
   3: import java.util.*;
   4: import jetbrick.template.JetContext;
                              ^
package jetbrick.template.runtime does not exist
   3: import java.util.*;
   4: import jetbrick.template.JetContext;
   5: import jetbrick.template.runtime.*;
      ^
cannot find symbol
  symbol: class JetPage
   6:
   7: @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
   8: public final class a_html extends JetPage {
                                        ^
cannot find symbol
  symbol:   class JetPageContext
  location: class default_.a_html
   9:
  10:   @Override
  11:   public void render(final JetPageContext $ctx) throws Throwable {
                                 ^
cannot find symbol
  symbol:   class JetContext
  location: class default_.a_html
  10:   @Override
  11:   public void render(final JetPageContext $ctx) throws Throwable {
  12:     final JetContext context = $ctx.getContext();
                ^
cannot find symbol
  symbol:   class JetWriter
  location: class default_.a_html
  11:   public void render(final JetPageContext $ctx) throws Throwable {
  12:     final JetContext context = $ctx.getContext();
  13:     final JetWriter $out = $ctx.getWriter();
                ^
cannot find symbol
  symbol:   variable JetUtils
  location: class default_.a_html
  23:   public static final String $ENC = "UTF-8";
  24:   private static final String $txt_1 = "<!DOCTYPE html>\r\n<meta http-equiv=\"content-type\" content=\"text/h
harset=utf-8\">\r\n<body>\r\n为什么受伤的总是我~~~~(>_<)~~~~\r\n</body>";
  25:   private static final byte[] $txt_1_bytes = JetUtils.asBytes($txt_1, $ENC);
                                                   ^
method does not override or implement a method from a supertype
   8: public final class a_html extends JetPage {
   9:
  10:   @Override
        ^
method does not override or implement a method from a supertype
  16:   }
  17:
  18:   @Override
        ^
9 error(s)

        at jetbrick.template.compiler.jdk.JdkCompiler.generateJavaClass(JdkCompiler.java:146)
        at jetbrick.template.compiler.jdk.JdkCompiler.compile(JdkCompiler.java:117)
        at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:114)
        at jetbrick.template.JetTemplate.<init>(JetTemplate.java:68)
        at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:179)
        at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:175)
        at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:44)
        at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92)
        at jetbrick.template.web.jfinal.JetTemplateRender.render(JetTemplateRender.java:44)
        at com.jfinal.core.ActionHandler.handle(ActionHandler.java:92)
        at com.jfinal.ext.handler.ContextPathHandler.handle(ContextPathHandler.java:47)
        at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:72)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)

增加模板预编译工具/选项

增加一个工具

可以在外部通过命令行调用,将所有的模板进行预编译,这样生成环境可以直接使用预编译好的 Class 文件,减少首次访问时候的延迟。

shell # JetxGenerateApp -all \
              -src /webapp/templates \
              -d /webapp/generatedClasses \
              -config /webapp/WEB-INF/jetbrick-template.properties

options:
  -all: compile all templates even if errors
  -src <path>: template root directory
  -d <path>: output directory
  -config <file>: config file

增加一个选项

允许 JetEngine 在初始化的时候,将所有的模板全部进行预编译(在独立线程中),同样是为了减少首次访问时候的延迟。

选项:

compile.strategy = [precompile, always, auto, none]

默认 always

说明:

  1. precompile: 第一次初始化 JetEngine 的时候,启动一个独立的线程把 template.path 下面的模板全部进行预编译。根据 template.suffix 过滤模板。
  2. always:第一次访问模板的时候,进行编译
  3. auto:在首次访问模板的时候,如果已经存在以前编译好的 class,那么直接加载,否则进行编译。
  4. none:从不编译,只加载 classpath 下用户预先用工具编译好的模板 class,这种模式甚至可以不提供 jetx 源码。

同时 compile.always 选项将被废弃。

增加 Spring FactoryBean 的集成支持

配置如下:

<bean id="jetEngine" class="jetbrick.template.JetEngineFactoryBean" />

<bean id="jetEngine" class="jetbrick.template.JetEngineFactoryBean">
  <property name="configFile" value="classpath:META-INF/jetbrick-template.properties" />
</bean>

<bean id="jetEngine" class="jetbrick.template.JetEngineFactoryBean">
   <property name="configFile" value="file:/path/to/jetbrick-template.properties" />
</bean>

感谢 @应卓([email protected]) 贡献代码

增加 #macro 宏定义

允许在模板中定义一个宏,然后多次使用

模板定义方法: 比如 header

#macro header(String name)
    Hello ${name}!
#end

然后使用: 使用宏就像使用函数一样。

${header("Sub")}
${header("Jetx")}

获取Map值有错

您好,在使用map时出现异常,代码如下:
Map<String, Object> map = Maps.newHashMap();
map.put("name", "测试");
map.put("age", 16);
JetWebContext context = new JetWebContext(request,response);
Map<String, Object> person = Maps.newHashMap();
person.put("person",map);
context.putAll(person);
//
${person["name"]}
异常信息:message: Operator [] is not applicable for the object (Object).

增加默认的 #tag cache() 实现模板局部缓存

缓存模板内容还是比较有用的,可以提供一个默认的实现

#tag cache(5 * 60)
   缓存 5 分钟
#end

#tag cache(5 * 60, true)
   缓存 5 分钟 (Session 级别)
#end

cache 的 key 可以自动生成。

是否需要在外部 clear cache?

拼写错误: #tag layout 中的实现用的是 bodyContext, 文档中描述的是 bodyContent,不一致

public final class JetTags
{
  public static void layout(JetTagContext ctx, String name)
  {
    String bodyContext = ctx.getBodyContent();
    ctx.getContext().put("bodyContext", bodyContext);

    name = ctx.getPageContext().getAbsolutionName(name);
    JetTemplate template = ctx.getEngine().getTemplate(name);
    template.render(ctx.getContext(), ctx.getWriter());
  }
}

需要修改为 bodyContent, 和文档保持一致。

增加指令注释支持,如: <!-- #if (...) --> 增强对可视化编辑器的友好度

在HTML中,由于目前的指令直接嵌入在 HTML,对于一些使用可视化编辑器的用户来说,可能会造成一些干扰。如果能用注释语句将指令包裹起来就完美了。

如:

<!-- #if (...) -->
   ...
<!-- #end -->

支持注释的自定义:

trim.directive.comments = false
trim.directive.comments.prefix = <!--
trim.directive.comments.suffix = -->

默认不启用。

JDK 6 can't load the template class compiled using JDK 7.

UnsupportedClassVersionError found.

[main] INFO jetbrick.template.JetTemplate - Loading template class file: 
C:\Windows\jetx_1_0_0\templates\jetx_html.class

Exception in thread "main" java.lang.UnsupportedClassVersionError: 
templates/jetx_html : Unsupported major.minor version 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at jetbrick.template.compiler.JetTemplateClassLoader.loadClass(JetTemplateClassLoader.java:53)
        at jetbrick.template.JetTemplate.loadClassFile(JetTemplate.java:78)
        at jetbrick.template.JetTemplate.<init>(JetTemplate.java:57)
        at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:172)
        at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:168)
        at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:45)
        at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92)
        at org.boilit.ebm.engine.JetbrickTemplate.work(JetbrickTemplate.java:35)
        at org.boilit.ebm.Executor.doByteStreamOut(Executor.java:93)
        at org.boilit.ebm.Executor.doStreamOut(Executor.java:78)
        at org.boilit.ebm.Executor.execute(Executor.java:53)
        at org.boilit.ebm.Executor.run(Executor.java:23)
        at org.boilit.ebm.Executor.main(Executor.java:142)

throw NullPointerException when method parameter is null.

模板

${@System.getProperty(null)}
${obj.equals(null)}

结果

Exception in thread "main" java.lang.NullPointerException
    at jetbrick.template.parser.VariableResolver.getPrivateCacheKeyName(VariableResolver.java:495)
    at jetbrick.template.parser.VariableResolver.resolveStaticMethod(VariableResolver.java:463)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitExpr_static_method_invocation(JetTemplateCodeVisitor.java:1057)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitExpr_static_method_invocation(JetTemplateCodeVisitor.java:1)
    at jetbrick.template.parser.grammer.JetTemplateParser$Expr_static_method_invocationContext.accept(JetTemplateParser.java:1607)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitValue(JetTemplateCodeVisitor.java:249)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitValue(JetTemplateCodeVisitor.java:1)
    at jetbrick.template.parser.grammer.JetTemplateParser$ValueContext.accept(JetTemplateParser.java:288)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:160)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:1)
    at jetbrick.template.parser.grammer.JetTemplateParser$BlockContext.accept(JetTemplateParser.java:153)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:148)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:1)
    at jetbrick.template.parser.grammer.JetTemplateParser$TemplateContext.accept(JetTemplateParser.java:103)
    at jetbrick.template.JetTemplate.generateJavaSource(JetTemplate.java:135)
    at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:101)
    at jetbrick.template.JetTemplate.<init>(JetTemplate.java:68)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:178)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:1)
    at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:45)
    at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92)

include() 函数和 #tag layout() 传的 Map 参数出现编译错误

模板-1

${include("header.jetx", {"name": "jetbrick"})}

模板-2

#tag layout("layout.jetx", {"name": "jetbrick"})
    hello from main
#end

出现的错误

Exception in thread "main" jetbrick.template.compiler.CompileErrorException: Compilation failed.
C:\Users\Sub\AppData\Local\Temp\jetx_1_0_0\template\ext_002dfunctions_002dinclude_jetx.java:18: cannot find symbol
symbol  : method include(jetbrick.template.runtime.JetPageContext,java.lang.String,java.util.Map<capture#208 of ?,capture#811 of ?>)
location: class jetbrick.template.runtime.JetFunctions
  17:     $out.print($txt_1, $txt_1_bytes);
  18:     $out.print(JetFunctions.include($ctx,"header.jetx",JetUtils.asMap("name","jetbrick"))); // line: 3
                                 ^
1 error(s)

    at jetbrick.template.compiler.jdk.JdkCompiler.generateJavaClass(JdkCompiler.java:131)
    at jetbrick.template.compiler.jdk.JdkCompiler.compile(JdkCompiler.java:102)
    at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:114)
    at jetbrick.template.JetTemplate.<init>(JetTemplate.java:68)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:179)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:1)
    at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:44)
    at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92)

增加 #tag default_block(name) 默认 layout block 的实现

在 layout.jetx 中,定义

#tag default_block("BLOCK")
    DEFAULT BLOCK
#end

然后在 main.jetx 中可以对 BLOCK 进行重载

#tag block("BLOCK")
    Override BLOCK
#end
#include("layout.jetx")

如果没有被重载,那么将默认输出 #tag default_block() 的内容。

增加自定义 Tag 功能

用法:

先用 Java 定义一个 Tag:比如 cache

public static void cache(JetTagContext ctx, String name) {
    String value = CacheManager.get(name);
    if (value == null) {
        value = ctx.getBodyContent();
        CacheManager.set(name, value);
    }
    ctx.getWriter().write(value);
}

然后在模板中使用:

#tag cache("1-1-1")
    ......
    ${header()} ${header()} ${header()}
    ... 其他内容...
#end

添加可由用户可配置的数据格式化器功能

数据格式化器[接口]

package jetbrick.template.formatter;

/**
 * 数据格式化器
 * 
 * @author 应卓([email protected])
 *
 */
public interface ObjectFormatter {

    /**
     * 格式化对象
     * 
     * @param object 输入
     * @return 输出
     */
    public String format(Object object);

    /**
     * 当返回true时表示支持这种数据类型的格式化
     * 
     * @param objectType
     * @return
     */
    public boolean supports(Class<?> objectType);

}

#set指令创建double型字面变量时,小数点后面跟0则不能通过编译

jetx-code

#set(double d = 0.1E-10D)  ##OK
#set(double d = 0.1D)         ##OK
#set(double d = 0.01D)       ##NG

栈轨迹

Exception in thread "main" jetbrick.template.parser.SyntaxErrorException: Template parse failed.
E:\worspace-eclipse-sts\samples\target\classes\samples\templates\temp.jetx:61
message: missing ')' at '1D'
  57: 8. 特殊字符转义
  58: \#if
  59: 
  60: ===============================================================================
  61: #set(double d = 0.01D)
                         ^^

    at jetbrick.template.parser.JetTemplateErrorListener.syntaxError(JetTemplateErrorListener.java:47)
    at org.antlr.v4.runtime.ProxyErrorListener.syntaxError(ProxyErrorListener.java:65)
    at org.antlr.v4.runtime.Parser.notifyErrorListeners(Parser.java:473)
    at org.antlr.v4.runtime.DefaultErrorStrategy.reportMissingToken(DefaultErrorStrategy.java:407)
    at jetbrick.template.parser.JetTemplateErrorStrategy.recoverInline(JetTemplateErrorStrategy.java:32)
    at org.antlr.v4.runtime.Parser.match(Parser.java:196)
    at jetbrick.template.parser.grammer.JetTemplateParser.set_directive(JetTemplateParser.java:650)
    at jetbrick.template.parser.grammer.JetTemplateParser.directive(JetTemplateParser.java:392)
    at jetbrick.template.parser.grammer.JetTemplateParser.block(JetTemplateParser.java:209)
    at jetbrick.template.parser.grammer.JetTemplateParser.template(JetTemplateParser.java:114)
    at jetbrick.template.JetTemplate.generateJavaSource(JetTemplate.java:134)
    at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:101)
    at jetbrick.template.JetTemplate.<init>(JetTemplate.java:68)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:178)
    at jetbrick.template.JetEngine$ConcurrentTemplateCache.doGetValue(JetEngine.java:174)
    at jetbrick.template.utils.ConcurrentCache.get(ConcurrentCache.java:45)
    at jetbrick.template.JetEngine.getTemplate(JetEngine.java:92)
    at samples.Main.main(Main.java:15)

三元表达式如果使用 Interface 或者 Primitive Class 作为选项,会出现 NullPointerException

如:

${ true ? "" : 0}

出现错误:

java.lang.NullPointerException
    at jetbrick.template.parser.support.PromotionUtils.getResultClassForConditionalOperator(PromotionUtils.java:201)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitExpr_conditional_ternary(JetTemplateCodeVisitor.java:1410)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitExpr_conditional_ternary(JetTemplateCodeVisitor.java:99)
    at jetbrick.template.parser.grammer.JetTemplateParser$Expr_conditional_ternaryContext.accept(JetTemplateParser.java:1640)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitValue(JetTemplateCodeVisitor.java:232)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitValue(JetTemplateCodeVisitor.java:99)
    at jetbrick.template.parser.grammer.JetTemplateParser$ValueContext.accept(JetTemplateParser.java:287)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:154)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitBlock(JetTemplateCodeVisitor.java:99)
    at jetbrick.template.parser.grammer.JetTemplateParser$BlockContext.accept(JetTemplateParser.java:153)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:142)
    at jetbrick.template.parser.JetTemplateCodeVisitor.visitTemplate(JetTemplateCodeVisitor.java:99)
    at jetbrick.template.parser.grammer.JetTemplateParser$TemplateContext.accept(JetTemplateParser.java:103)
    at jetbrick.template.JetTemplate.generateJavaSource(JetTemplate.java:134)
    at jetbrick.template.JetTemplate.compileAndLoadClass(JetTemplate.java:101)
    at jetbrick.template.JetTemplate.checkLastModified(JetTemplate.java:77)
    at jetbrick.template.JetEngine.getTemplate(JetEngine.java:93)

字节码生成java代码的log是否可以改成DEBUG级别

2013-12-03 14:23:26,176 [main] INFO  jetbrick.template.JetConfig[103] - Load template from "/samples/templates/" by class jetbrick.template.resource.loader.ClasspathResourceLoader.
2013-12-03 14:23:26,180 [main] INFO  jetbrick.template.JetConfig[107] - autoload off: template will NOT automatically reload.
2013-12-03 14:23:26,182 [main] INFO  j.template.parser.VariableResolver[66] - import package: java.lang.*
2013-12-03 14:23:26,182 [main] INFO  j.template.parser.VariableResolver[66] - import package: java.util.*
2013-12-03 14:23:26,185 [main] INFO  j.template.parser.VariableResolver[122] - add method class: jetbrick.template.runtime.JetMethods
2013-12-03 14:23:26,186 [main] INFO  j.template.parser.VariableResolver[156] - add function class: jetbrick.template.runtime.JetFunctions
2013-12-03 14:23:26,187 [main] INFO  j.template.parser.VariableResolver[185] - add tag class: jetbrick.template.runtime.JetTags
2013-12-03 14:23:26,188 [main] INFO  j.t.compiler.JetTemplateClassLoader[44] - Will compile template into C:\Users\yingzhuo\AppData\Local\Temp\jetx_1_1_0
2013-12-03 14:23:26,260 [main] INFO  jetbrick.template.JetTemplate[98] - Loading template source file: E:\worspace-eclipse-sts\samples\target\classes\samples\templates\email.jetx
2013-12-03 14:23:26,391 [main] INFO  jetbrick.template.JetTemplate[111] - generateJavaSource: C:\Users\yingzhuo\AppData\Local\Temp\jetx_1_1_0\email_jetx.java
===========================================================================
import java.util.*;
import jetbrick.template.JetContext;
import jetbrick.template.runtime.*;

@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public final class email_jetx extends JetPage {

  @Override
  public void render(final JetPageContext $ctx) throws Throwable {
    final JetContext context = $ctx.getContext();
    final JetWriter $out = $ctx.getWriter();
    Boolean flag = (Boolean) context.get("flag"); // line: 1
    $out.print($txt_1, $txt_1_bytes);
    $out.print((flag?"flag为真":"flag为假")); // line: 3
    $out.print($txt_2, $txt_2_bytes);
    $out.flush();
  }

  @Override
  public String getName() {
    return "/email.jetx";
  }

  public static final String $ENC = "UTF-8";
  private static final String $txt_1 = "========\nIF语句:";
  private static final byte[] $txt_1_bytes = JetUtils.asBytes($txt_1, $ENC);
  private static final String $txt_2 = "\n========\n";
  private static final byte[] $txt_2_bytes = JetUtils.asBytes($txt_2, $ENC);
}

===========================================================================

此处生成的日志有点眼花缭乱啊! 但是关闭生成java代码的日志,把JetConfig配置信息log一并关闭了。 建议jetbrick.template.JetTemplate第111行的日志输出降低到DEBUG级别。

#tag 中的 #include 输出的内容位置不正确

模板1:

#tag block("TEST")
    1234567890
    #include("test.jetx")
    AAAAAAAAAAAAA
#end
#include("layout.jetx")

嵌入的 test.jetx

aaaaaaaaaaaa

布局 layout.jetx

XXXXXXXX
${TEST}
YYYYYYYY

结果:

aaaaaaaaaaaaXXXXXXXX
    1234567890
    AAAAAAAAAAAAA
YYYYYYYY

嵌入的 test.jetx 输出的内容在最前面,不正确。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.