日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

groovy 模板引擎實現(xiàn)原理分析

 CevenCheng 2012-11-25

groovy 模板引擎實現(xiàn)原理分析








groovy的SimpleTemplateEngine實現(xiàn)了模板功能,類似于jsp。那就分析groovy是如何實現(xiàn)模板的。 

使用模板 

Java代碼
  1. 1.Template template = new SimpleTemplateEngine().createTemplate(   
  2. 2.        new StringReader("<% // This is a comment that will be filtered from output %>\n" +   
  3. 3.        "Hello <%out.println(name);%> !")   
  4. 4.    );   
  5. 5.  
  6. 6.    final StringWriter sw = new StringWriter();   
  7. 7.    template.make([name:'bloodwolf_china').writeTo(sw);   
  8. 8.    println sw.toString();  
  9. Template template = new SimpleTemplateEngine().createTemplate(
  10.         new StringReader("<% // This is a comment that will be filtered from output %>\n" +
  11.         "Hello <%out.println(name);%> !")
  12.     );

  13.     final StringWriter sw = new StringWriter();
  14.     template.make([name:'bloodwolf_china').writeTo(sw);
  15.     println sw.toString();
復制代碼
看看SimpleTemplateEngine類 

Java代碼
  1. 1.public Template createTemplate(Reader reader) throws CompilationFailedException, IOException {   
  2. 2.        SimpleTemplate template = new SimpleTemplate();   
  3. 3.        String script = template.parse(reader);   
  4. 4.                 
  5. 5.            template.script = groovyShell.parse(script, "SimpleTemplateScript" + counter++ + ".groovy");   
  6. 6.          
  7. 7.        return template;   
  8. 8.    }  
  9. public Template createTemplate(Reader reader) throws CompilationFailedException, IOException {
  10.         SimpleTemplate template = new SimpleTemplate();
  11.         String script = template.parse(reader);
  12.               
  13.             template.script = groovyShell.parse(script, "SimpleTemplateScript" + counter++ + ".groovy");
  14.        
  15.         return template;
  16.     }
復制代碼
這兒做了三件事 
1、創(chuàng)建了一個SimpleTemplate對象 
2、解析模板,主要是把<%=exp%>轉(zhuǎn)為groovy的內(nèi)置表達式${exp},把非<%code%>轉(zhuǎn)為調(diào)用out.print(內(nèi)容)函數(shù),<%code%>中的就是groovy代碼了。這樣就把整個模板解析為一段代碼。如
引用
Hello <%out.println(name);%> !
變成 

Java代碼
  1. 1.out.print("Hello ");   
  2. 2.out.println(name);   
  3. 3.out.print(" !");  
  4. out.print("Hello ");
  5. out.println(name);
  6. out.print(" !");
復制代碼
3、用groovyShell獲取一個Script對象 

Script對象只一個支持普通groovy對象,利用了Groovy的特性 
實現(xiàn) getProperty(String property)方法,從參數(shù)綁定對象中獲取屬性,這樣腳本中就能獲取綁定參數(shù)。 

Java代碼
  1. 1.public abstract class Script extends GroovyObjectSupport {   
  2. 2.    private Binding binding;   
  3. 3.    public Object getProperty(String property) {   
  4. 4.        try {   
  5. 5.            return binding.getVariable(property);   
  6. 6.        } catch (MissingPropertyException e) {   
  7. 7.            return super.getProperty(property);   
  8. 8.        }   
  9. 9.    }   
  10. 10.     public abstract Object run();   
  11. 11.}  
  12. public abstract class Script extends GroovyObjectSupport {
  13.     private Binding binding;
  14.     public Object getProperty(String property) {
  15.         try {
  16.             return binding.getVariable(property);
  17.         } catch (MissingPropertyException e) {
  18.             return super.getProperty(property);
  19.         }
  20.     }
  21.      public abstract Object run();
  22. }
復制代碼
groovyShell把一段代碼組裝成一個GroovyCodeSource對象,然后調(diào)用GroovyClassLoader,CompilationUnit把CodeSource編譯成一個Script對象,run()方法中執(zhí)行的即是out.print(模板內(nèi)容)這段代碼。 

在看看如何輸出模板內(nèi)容的 

Java代碼
  1. 1.private static class SimpleTemplate implements Template {   
  2. 2.  
  3. 3.        protected Script script;   
  4. 4.  
  5. 5.        public Writable make() {   
  6. 6.            return make(null);   
  7. 7.        }   
  8. 8.  
  9. 9.        public Writable make(final Map map) {   
  10. 10.            return new Writable() {   
  11. 11.                /**  
  12. 12.                 * Write the template document with the set binding applied to the writer.  
  13. 13.                 *  
  14. 14.                 * @see groovy.lang.Writable#writeTo(java.io.Writer)  
  15. 15.                 */  
  16. 16.                public Writer writeTo(Writer writer) {   
  17. 17.                    Binding binding;   
  18. 18.                    if (map == null)   
  19. 19.                        binding = new Binding();   
  20. 20.                    else  
  21. 21.                        binding = new Binding(map);   
  22. 22.                    Script scriptObject = InvokerHelper.createScript(script.getClass(), binding);   
  23. 23.                    PrintWriter pw = new PrintWriter(writer);   
  24. 24.                    scriptObject.setProperty("out", pw);   
  25. 25.                    scriptObject.run();   
  26. 26.                    pw.flush();   
  27. 27.                    return writer;   
  28. 28.                }   
  29. 29.  
  30. 30.                /**  
  31. 31.                 * Convert the template and binding into a result String.  
  32. 32.                 *  
  33. 33.                 * @see java.lang.Object#toString()  
  34. 34.                 */  
  35. 35.                public String toString() {   
  36. 36.                    StringWriter sw = new StringWriter();   
  37. 37.                    writeTo(sw);   
  38. 38.                    return sw.toString();   
  39. 39.                }   
  40. 40.            };   
  41. 41.        }   
  42. 42.}  
  43. private static class SimpleTemplate implements Template {

  44.         protected Script script;

  45.         public Writable make() {
  46.             return make(null);
  47.         }

  48.         public Writable make(final Map map) {
  49.             return new Writable() {
  50.                 /**
  51.                  * Write the template document with the set binding applied to the writer.
  52.                  *
  53.                  * @see groovy.lang.Writable#writeTo(java.io.Writer)
  54.                  */
  55.                 public Writer writeTo(Writer writer) {
  56.                     Binding binding;
  57.                     if (map == null)
  58.                         binding = new Binding();
  59.                     else
  60.                         binding = new Binding(map);
  61.                     Script scriptObject = InvokerHelper.createScript(script.getClass(), binding);
  62.                     PrintWriter pw = new PrintWriter(writer);
  63.                     scriptObject.setProperty("out", pw);
  64.                     scriptObject.run();
  65.                     pw.flush();
  66.                     return writer;
  67.                 }

  68.                 /**
  69.                  * Convert the template and binding into a result String.
  70.                  *
  71.                  * @see java.lang.Object#toString()
  72.                  */
  73.                 public String toString() {
  74.                     StringWriter sw = new StringWriter();
  75.                     writeTo(sw);
  76.                     return sw.toString();
  77.                 }
  78.             };
  79.         }
  80. }
復制代碼
很清楚了,調(diào)用make方法,創(chuàng)建一個Script對象,綁定參數(shù)binding = new Binding(map)。 
創(chuàng)建一個PrintWriter,綁定為out參數(shù),而模板解析的代碼中的out.print(內(nèi)容)就有著落了。 

所以: 

?Groovy的模板是通過編譯,生成Java類,然后調(diào)用方法實現(xiàn)的 
?使用模板機制注意要緩存Script對象或Template對象,否則每次調(diào)用都會編譯生成一個新的Java類,導致內(nèi)存溢出/泄露

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多