Javaã®ãã³ãã¬ãŒããšã³ãžã³ã䜿ãæã¯VelocityãFreeMarkerãéžæããããšãå€ãã®ã§ãããä»ã«ããéžæè¢ããªãã®ããªãšæã£ãŠã¡ãã£ãšèª¿ã¹ãŠã¿ãŸããã
èªåãæ±ããŠããã®ã¯HTMLã«ç¹åããŠããªããæ±çšã®ãã³ãã¬ãŒããšã³ãžã³ã§ããããªã®ã§ããã®æèã ãšThymeleafã¯å€ããããªãšæã£ãŠããŸãã
ã§ãŸãããã®ãããã®ãšã³ããªãèŠããããŠ
A Java Template Engine
http://vicox.net/2014/09/02/a-java-template-engine/
ä»åã¯ã以äžã®ãã³ãã¬ãŒããšã³ãžã³ãè©ŠããŠã¿ãŸããã
- Pebble
- Rythm
- Jtwig
- HTTL
詳ããæ¯èŒãããã¯ããŸããããŸãã¯è©ŠããŠã¿ãŠãåãããªïŒèå³ãæãŠãããªïŒãšããçšåºŠã®åæ©ã§ãã
ã§ã¯ãé ã«è©ŠããŠã¿ãŸãã
ããåãã³ãã¬ãŒããšã³ãžã³äžã§äžéšäœ¿ã£ãŠãããJavaBeansçãªãã®ã¯ä»¥äžã®å®çŸ©ãšããŠããŸããããã±ãŒãžã¯ãåMainã¯ã©ã¹ãšåãããã±ãŒãžã«å±ããŠãããã®ãšããŸãã
public class Person { private String lastName; private String firstName; public Person(String lastName, String firstName) { this.lastName = lastName; this.firstName = firstName; } public String getLastName() { return lastName; } public String getFirstName() { return firstName; } }
ãŸããåäŸã«ãããŠããã³ãã¬ãŒãã¯ã¯ã©ã¹ãã¹äžã«ãã¡ã€ã«ãšããŠçœ®ããã®ãšããŸãã
Pebble
Djangoã«ã€ã³ã¹ãã€ã¢ãããã·ã³ã¿ãã¯ã¹ãæã€ãã³ãã¬ãŒããšã³ãžã³ãããã§ããã©ãèªåã¯Djangoã䜿ã£ãããšããªãã®ã§ããããããŸãããâŠã
Pebble
http://www.mitchellbosecke.com/pebble/home
ãšã¹ã±ãŒããèªåçã«ããããããã§ãã
ã§ã¯ã以äžã®ããŒãžãèŠã€ã€è©ŠããŠã¿ãŸãã
Installation & Configuration
http://www.mitchellbosecke.com/pebble/documentation/guide/installation
Basic Usage
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
MavenäŸåé¢ä¿ã
<dependency> <groupId>com.mitchellbosecke</groupId> <artifactId>pebble</artifactId> <version>1.5.1</version> </dependency>
ãµã³ãã«ã³ãŒãã
src/main/java/org/littlewings/template/pebble/PebbleExample.java
package org.littlewings.template.pebble; import java.io.IOException; import java.io.StringWriter; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import com.mitchellbosecke.pebble.PebbleEngine; import com.mitchellbosecke.pebble.error.PebbleException; import com.mitchellbosecke.pebble.template.PebbleTemplate; public class PebbleExample { public static void main(String... args) throws PebbleException, IOException { PebbleEngine engine = new PebbleEngine(); StringWriter writer = new StringWriter(); Map<String, Object> context = new HashMap<>(); context.put("word", "äžç"); context.put("persons", Arrays.asList(new Person("磯é", "ã«ããª"), new Person("磯é", "ã¯ã«ã¡"))); context.put("containTag", "<script>Hello!!</script>"); PebbleTemplate template = engine.getTemplate("templates/sample.peb"); template.evaluate(writer, context); System.out.println(writer); } }
ãã³ãã¬ãŒãã
src/main/resources/templates/sample.peb
ããã«ã¡ã¯ã{{ word }} {% for person in persons %} å§ïŒ {{ person.lastName }} åïŒ {{ person.firstName }} {% endfor %} escape?: {{ containTag }} raw: {{ containTag | raw }}
å€æ°ã¯{{ }}ã§å²ã¿ãforãªã©ã¯{% %}ã§å²ãã¿ããã§ãã
å®è¡çµæã
ããã«ã¡ã¯ãäžç å§ïŒ 磯é åïŒ ã«ã㪠å§ïŒ 磯é åïŒ ã¯ã«ã¡ escape?: <script>Hello!!</script> raw: <script>Hello!!</script>
HTMLã¿ã°ã¯ãããã©ã«ãã§ãšã¹ã±ãŒããããŠããŸãã
䜿ã£ãŠã¡ãã£ãšéåæããã£ãã®ããæ¹è¡ã®æ±ãã§ããâŠããã³ãã¬ãŒãã«æ¹è¡ãããããå ¥ã£ãŠããå²ã«ã¯ãåºåçµæã«ã¯å«ãŸããŠããŸãããããããåããšè¡ããã£ã€ãããããŸãã
ã©ãããããšã§ãããâŠã
Rythm
ãªãã£ã·ã£ã«ãµã€ããåœéåãããŠããŸããããªããæ¥æ¬èªãæªããæãâŠã
Rythm
http://rythmengine.org/
ãŸããå¯äžæ¥æ¬èªãšã³ããªããããŸããã
Java ã® template engine ã® Rythm ãè©Šã
http://tc.hatenablog.com/entry/2015/04/07/213444
ã§ã¯ããã¥ãŒããªã¢ã«ããã³ãã¬ãŒããšã³ãžã³ã¬ã€ãã«ãã£ãŠè©ŠããŠã¿ãŸãã
Tutorial
http://rythmengine.org/doc/tutorial.md
Template Author's Guide
http://rythmengine.org/doc/template_guide.md
MavenäŸåé¢ä¿ã
<dependency> <groupId>org.rythmengine</groupId> <artifactId>rythm-engine</artifactId> <version>1.0.1</version> </dependency>
ãµã³ãã«ã³ãŒãã
src/main/java/org/littlewings/template/rythm/RythmExample.java
package org.littlewings.template.rythm; import java.io.IOException; import java.io.StringWriter; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; import org.rythmengine.RythmEngine; public class RythmExample { public static void main(String... args) throws URISyntaxException, IOException { RythmEngine rythm = new RythmEngine(); StringWriter writer = new StringWriter(); Path templatePath = Paths.get(Thread.currentThread().getContextClassLoader().getResource("templates/sample.txt").toURI()); Map<String, Object> context = new LinkedHashMap<>(); context.put("word", "äžç"); context.put("persons", Arrays.asList(new Person("磯é", "ã«ããª"), new Person("磯é", "ã¯ã«ã¡"))); context.put("containTag", "<script>Hello!!</script>"); rythm.render(writer, templatePath.toFile(), context); System.out.println(writer); } }
ãã³ãã¬ãŒãã
src/main/resources/templates/sample.txt
@args String word, List persons, String containTag @import org.littlewings.template.rythm.Person ããã«ã¡ã¯ã@word @for(Person person : persons) { å§ïŒ @person.getLastName() åïŒ @person.getFirstName() } escape?: @containTag
æåã«ã䜿ãå€æ°ãšãã®åã®å®£èšãå¿ èŠã§ãã
ãªãããã³ãã¬ãŒãã«ãã€ã³ãããå€æ°ãåäžã®MapãšããŠæž¡ããå Žåã¯ãå±éãããŠãã³ãã¬ãŒãã«æž¡ãããããã§ãã
https://github.com/greenlaw110/Rythm/blob/rythm-engine-1.0.1/src/main/java/org/rythmengine/RythmEngine.java#L872
ãããããããããã£ããããããŸããâŠã
å®è¡çµæã
ããã«ã¡ã¯ãäžç å§ïŒ 磯é åïŒ ã«ã㪠å§ïŒ 磯é åïŒ ã¯ã«ã¡ escape?: <script>Hello!!</script>
ãã¡ãã¯ããšã¹ã±ãŒããããã«åºåãããŸãã
ãªã®ã§ããããã³ãã¬ãŒããã¡ã€ã«ã®æ¡åŒµåãã.htmlãã«ãããšããªããšãšã¹ã±ãŒããããããã«ãªããŸãã
src/main/resources/templates/sample.html
@args String word, List persons, String containTag @import org.littlewings.template.rythm.Person ããã«ã¡ã¯ã@word @for(Person person : persons) { å§ïŒ @person.getLastName() åïŒ @person.getFirstName() } escape?: @containTag
ãã³ãã¬ãŒããèªããã¹ãå€æŽã
Path templatePath = Paths.get(Thread.currentThread().getContextClassLoader().getResource("templates/sample.html").toURI());
åºåçµæã
ããã«ã¡ã¯ãäžç å§ïŒ 磯é åïŒ ã«ã㪠å§ïŒ 磯é åïŒ ã¯ã«ã¡ escape?: <script>Hello!!</script>
ããšãã¡ãã£ãšå€ãã£ãæåãšããŠãã¡ãœãããªã©ããã³ãã¬ãŒãäžã§å®£èšãããåã«å¯ŸããŠèŠã€ããããšãã§ããªããšãå®è¡æã«ãšã©ãŒã«ãªããŸãã
äŸãã°ããããªæãã«getLastNameã®ã€ã¥ããééãããš
å§ïŒ @person.getLastNam() åïŒ @person.getFirstName()
ãããªæãã®ãšã©ãŒã«ãªããŸãã
Exception in thread "main" org.rythmengine.exception.CompileException: The method getLastNam() is undefined for the type Person Template: /xxxxx/rythm-example/target/classes/templates/sample.txt Relevant template source lines: ------------------------------------------------- 2: @import org.littlewings.template.rythm.Person 3: 4: ããã«ã¡ã¯ã@word 5: 6: @for(Person person : persons) { >> 7: å§ïŒ @person.getLastNam() åïŒ @person.getFirstName() 8: } 9: 10: escape?: @containTag Relevant Java source lines: ------------------------------------------------- 123: org.rythmengine.internal.LoopUtil person_utils = new org.rythmengine.internal.LoopUtil(person_isFirst, person_isLast); //line: 6 124: org.rythmengine.internal.LoopUtil person__utils = new org.rythmengine.internal.LoopUtil(person_isFirst, person_isLast, person); //line: 6 125: __pushItrVar("person", person); //line: 6 126: p(__v6361); //line: 7 127: >> 128: try{pe(person.getLastNam());} catch (RuntimeException e) {__handleTemplateExecutionException(e);} //line: 7 129: p(__v14126); //line: 7 130: 131: try{pe(person.getFirstName());} catch (RuntimeException e) {__handleTemplateExecutionException(e);} //line: 7 132: p(__v73678); //line: 7 133: 134: __popItrVar();
ããã¯ããªãã¬ã¯ã·ã§ã³ã§è§£æ±ºã§ããã°OKã¿ãããªæåã§ã¯ãªããäŸããã³ãã¬ãŒãã«ãã€ã³ãããããªããžã§ã¯ãã該åœã®ã¡ãœããããã£ãŒã«ããæã£ãŠããŠããObjectåãšããŠæ±ãããŠããããããšå¯Ÿè±¡ã®ã¡ã³ããŒã解決ã§ããã«ãšã©ãŒã«ãªããŸãã
ãžããã£ãŠæãã§ããã
Jtwig
PHPã«Twigãšãããã³ãã¬ãŒããšã³ãžã³ãããã¿ãããªã®ã§ãããããã®ç§»æ€çã ã£ãããããã§ããããâŠïŒ
Jtwig
http://jtwig.org/
ã·ã³ã¿ãã¯ã¹ã䌌ãŠããæ°ãããã®ã§ããããªæããã
ãã¥ãŒããªã¢ã«ãSpring MVCã§æžãããŠããã®ã§ããã
Integrating Jtwig
http://jtwig.org/documentation/get-started/
ãšããããæ®éã«äœ¿ããŸãã
ãµã³ãã«ãåèã«ããŸããã
https://github.com/jtwig/jtwig-examples/tree/master/simple-app
MavenäŸåé¢ä¿ã
<dependency> <groupId>com.lyncode</groupId> <artifactId>jtwig-core</artifactId> <version>3.1.1</version> </dependency>
ãµã³ãã«ã³ãŒãã
src/main/java/org/littlewings/template/jtwig/JtwigExample.java
package org.littlewings.template.jtwig; import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import com.lyncode.jtwig.JtwigModelMap; import com.lyncode.jtwig.JtwigTemplate; import com.lyncode.jtwig.configuration.JtwigConfiguration; import com.lyncode.jtwig.exception.CompileException; import com.lyncode.jtwig.exception.ParseException; import com.lyncode.jtwig.exception.RenderException; public class JtwigExample { public static void main(String... args) throws ParseException, CompileException, RenderException, URISyntaxException { Path templatePath = Paths.get(Thread.currentThread().getContextClassLoader().getResource("templates/sample.twig").toURI()); JtwigConfiguration config = new JtwigConfiguration(); JtwigTemplate template = new JtwigTemplate(templatePath.toFile(), config); JtwigModelMap context = new JtwigModelMap(); context.put("word", "äžç"); context.put("persons", Arrays.asList(new Person("磯é", "ã«ããª"), new Person("磯é", "ã¯ã«ã¡"))); context.put("containTag", "<script>Hello!!</script>"); System.out.println(template.output(context)); } }
ãã³ãã¬ãŒããã¡ã€ã«ã
src/main/resources/templates/sample.twig
ããã«ã¡ã¯ã{{ word }} {% for person in persons %} å§ïŒ {{ person.lastName }} åïŒ {{ person.firstName }} {% endfor %} escape?: {{ containTag }} escape?: {{ containTag | escape }}
Pebbleãšåããããªæ§æã«èŠããâŠã
å®è¡çµæã
ããã«ã¡ã¯ãäžç å§ïŒ 磯é åïŒ ã«ã㪠å§ïŒ 磯é åïŒ ã¯ã«ã¡ escape?: <script>Hello!!</script> escape?: <script>Hello!!</script>
ãããæ¹è¡ã®èª¿æŽãïŒïŒ
ããšãããã©ã«ãã§HTMLãšã¹ã±ãŒããããã¿ããã§ããã
HTTL
æåŸã¯ãHTTLãHyper-Text Template Languageã®ç¥ããããããã©ãŒãã³ã¹ãé«ããšè¬³ã£ãŠããŸããããšãæ§æãVelocityã«äŒŒãŠãããšã
HTTL
http://httl.github.io/en/
ãµã³ãã«ã¯ãã¡ãã
Example
http://httl.github.io/en/example.html
Syntax
http://httl.github.io/en/syntax.html
MavenäŸåé¢ä¿ã
<dependency> <groupId>com.github.httl</groupId> <artifactId>httl</artifactId> <version>1.0.11</version> </dependency>
ãµã³ãã«ã³ãŒãã
src/main/java/org/littlewings/template/httl/HttlExample.java
package org.littlewings.template.httl; import java.io.IOException; import java.io.StringWriter; import java.text.ParseException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import httl.Engine; import httl.Template; public class HttlExample { public static void main(String... args) throws IOException, ParseException { Engine engine = Engine.getEngine(); Map<String, Object> context = new HashMap<>(); context.put("word", "äžç"); context.put("persons", Arrays.asList(new Person("磯é", "ã«ããª"), new Person("磯é", "ã¯ã«ã¡"))); context.put("containTag", "<script>Hello!!</script>"); Template template = engine.getTemplate("templates/sample.httl", "UTF-8"); StringWriter writer = new StringWriter(); template.render(context, writer); System.out.println(writer); } }
ãã³ãã¬ãŒããã¡ã€ã«ã
src/main/resources/templates/sample.httl
#set(String word, List<org.littlewings.template.httl.Person> persons, String containTag) ããã«ã¡ã¯ã${word} #for(org.littlewings.template.httl.Person person : persons) å§ïŒ ${person.lastName} åïŒ ${person.firstName} #end escape?: ${containTag} raw?: $!{containTag}
確ãã«ã¡ãã£ãšVelocityã£ãœãã§ãããåã®å®£èšãå¿ èŠã§ãã
åºåçµæã
ããã«ã¡ã¯ãäžç å§ïŒ 磯é åïŒ ã«ã㪠å§ïŒ 磯é åïŒ ã¯ã«ã¡ escape?: <script>Hello!!</script> raw?: <script>Hello!!</script>
ããã©ã«ãã§HTMLãšã¹ã±ãŒãããããã$!ã§ãšã¹ã±ãŒã解é€ã§ãã
å宣èšããŠããããšãããåè¿°ã®Rythmã®æãšåãããã«ãããããã£åãªã©ééãããš
å§ïŒ ${person.lastName} åïŒ ${person.firstName}
ãšã©ãŒã«ãªã£ãŠã³ã±ãŸãã
é倧: No such property lastNam in class org.littlewings.template.httl.Person, because no such method getLastNam() or method isLastNam() or method lastNam() or filed lastNam. Occur to offset: 177, line: 5, column: 14, char: ., in: /templates/sample.httl ======================================== ... å§ïŒ ${person.lastNam} åïŒ ${person... ^-here ======================================== , stack: java.text.ParseException: No such property lastNam in class org.littlewings.template.httl.Person, because no such method getLastNam() or method isLastNam() or method lastNam() or filed lastNam.
ãŸãã以äžã®ãããªããããã£ãã¡ã€ã«ãçšæããŠ
src/main/resources/httl-html.properties
comment.left=<!-- comment.right=-->
ã³ãŒãããã®ããã«å€æŽããŠãèšå®ãã¡ã€ã«ãèªãããã«ãããš
public static void main(String... args) throws IOException, ParseException { Engine engine = Engine.getEngine("httl-html.properties"); Map<String, Object> context = new HashMap<>(); context.put("word", "äžç"); context.put("persons", Arrays.asList(new Person("磯é", "ã«ããª"), new Person("磯é", "ã¯ã«ã¡"))); context.put("containTag", "<script>Hello!!</script>"); Template template = engine.getTemplate("templates/sample-html.httl", "UTF-8"); StringWriter writer = new StringWriter(); template.render(context, writer); System.out.println(writer); }
åãã£ã¬ã¯ãã£ãããHTMLã³ã¡ã³ãã®äžã«åã蟌ãããšãã§ããããã«ãªããŸãã
<!-- #set(String word, List<org.littlewings.template.httl.Person> persons, String containTag) --> ããã«ã¡ã¯ã${word} <!-- #for(org.littlewings.template.httl.Person person : persons) --> å§ïŒ ${person.lastName} åïŒ ${person.firstName} <!-- #end --> escape?: ${containTag} raw?: $!{containTag}
ãjericho-htmlãã䜿ãããšã§ãHTMLå±æ§äžã«ãã£ã¬ã¯ãã£ããæžãããšãå¯èœã¿ããã§ãã
ã§ãã©ãã ã£ãïŒ
ãšãããããããã£ãšãHello Worldãçã«è©ŠããŠã¿ãŸããããå人çã«ã¯ãã®æ®µéã§ã¯ãããã¯ïŒãã¿ãããªå°è±¡ã¯æãŠãªãã£ãæ°ãããŸãã
ã©ãããããããçããããŸãããVelocityãšãFreeMarkerã§ãããããããªãããªããšæã£ããâŠã
â»Velocityã¯éçºãã»ãŒæ¢ãŸã£ãŠãã以å€ã«ãToolsãšãã°ãŸãããã¡ãã£ãšåŸ®åŠãªãã§ããã©
Pebbleã®æ¹è¡ã«çããªãã£ãããããã¡ãã£ãšèããããã
ãªãããããã®ãã³ãã¬ãŒããšã³ãžã³ããçŸåšã¯ãããŸã§æŽ»çºã«éçºãè¡ãããŠããããã§ã¯ãªãããã§ããPebbleã¯ãŒã¡ãŒã¡ç¶ããŠããã¿ããã§ããã
ãã®ãšã³ããªãèªãŸããæ¹ã§ãèå³ãåŒããšãããããã°ã