freemarker substring

2008/06/12 15:15
freemarker에서 특정 문자열을 잘라서 보여주고 싶을때 사용하는 syntax!

<Example>
- ${'abc'?substring(0)}
- ${'abc'?substring(1)}
- ${'abc'?substring(2)}
- ${'abc'?substring(3)}

- ${'abc'?substring(0, 0)}
- ${'abc'?substring(0, 1)}
- ${'abc'?substring(0, 2)}
- ${'abc'?substring(0, 3)}

- ${'abc'?substring(0, 1)}
- ${'abc'?substring(1, 2)}
- ${'abc'?substring(2, 3)}

<output>
- abc
- bc
- c
-

-
- a
- ab
- abc

- a
- b
- c

http://freemarker.sourceforge.net/docs/ref_builtins_string.html#ref_builtin_substring
역시 freemarker는 나를 실망시키지 않는다.
이렇게 편하게 escape이 가능하다니, 값에 html만 붙여주면 되는구나.

부분적으로 적용 할 경우

First name: ${firstName?html}
Last name: ${lastName?html}
Maiden name: ${maidenName?html

전체에 적용할 경우

<#escape x as x?html>
  First name: ${firstName}
  Last name: ${lastName}
  Maiden name: ${maidenName}
</#escape>  


Freemarker escape처리
http://freemarker.org/docs/ref_directive_escape.html

대부분의 view페이지에서 제공하는 기능입니다.

Freemarker에서는 이렇게 사용을 합니다.
<#include "/common/copyright.ftl">

같은 경로에 파일이 존재 할때는
<#include "./common/copyright.ftl">

상위 폴더에 존재할 때는 다음과 같이,
<#include "*/common/copyright.ftl">

요렇게 사용도 가능합니다.
<#include "commons/*/footer.ftl">

spring, freemarker와 webwork를 보고 있으면 참 유연한 구조가 가능하다는 생각을 합니다.
framework를 만들 때는 삽질과 경험이 많아야 좋은 솔루션을 만들어내는 듯합니다...^^


참고
http://freemarker.sourceforge.net/docs/ref_directive_include.html

현재 개발중인 어플리케이션은 다양한 UI를 제공해야 하는 이슈가 있다. 그것을 위해 템플릿 엔진의 적용이 필요했고, freemarker의 선택은 사용할 수록 나를 기쁘게 한다.서버에서 만들어지는 html이지만, 테스트 코드를 통해서 테스트도 용이한 것은 큰 장점이다.

list에 대한 사용은 화면을 만드는데 자주 사용이 된다. 부가적인 옵션 기능을 통해서 어떤 뷰를 만들수 있는지 본다.

list된 데이터를 화면에 디스플레이를 할때, 다음과 같은 결과를 만들고 싶다.
pathList가 string타입의 collection이라면, pathList : ["서울","대구","부산"]
display:
서울 -> 대구 -> 부산

원하는 collection형태를 디스플이를 할때 구분자를 이어주고, 마지막에는 구분자가를 사용하지 않는 너무나 자주 쓰는 디스플레이 방법중의 하나이다.

freemarker로 우리는 편하게 할수 있다.
다음 코드를 보자.

<#list travel.pathList as path>
${path} <#if path_has_next> -> </#if>
</#list>

너무나 편안하고 손쉽게 사용할 수도 있을 뿐더라 이해하기도 쉽다.

freemarker list, break
http://fmpp.sourceforge.net/freemarker/ref_directive_list.html
사실 매뉴얼에 너무나 자세히 잘 나와있다..^^
Template Class API
http://freemarker.sourceforge.net/docs/api/freemarker/template/Template.html



Configuration instance를 통해서 요렇게 얻어온다.

ex1)
Configuration cfg = new Configuration();
...
Template myTemplate = cfg.getTemplate("myTemplate.html");

ex2)
Template temp = cfg.getTemplate("test.ftl");  


Merging the template with the data model

Writer out = new OutputStreamWriter(System.out);
temp.process(root, out);
out.flush();  


아주 심플하고 쉽다.

정리를 하자면, Configuration을 통해서 파일의 위치와 기타 정보를 셋팅 인스턴스를 만든 다음 템플릿 객체를 얻어와서 merging작업을 하면 끝!!


오래 기다렸다. 한방에 코드를 보자.

import freemarker.template.*;
import java.util.*;
import java.io.*;

public class Test {

    public static void main(String[] args) throws Exception {
        
        /* ------------------------------------------------------------------- */    
        /* You usually do it only once in the whole application life-cycle:    */    
    
        /* Create and adjust the configuration */
        Configuration cfg = new Configuration();
        cfg.setDirectoryForTemplateLoading(
                new File("/where/you/store/templates"));
        cfg.setObjectWrapper(new DefaultObjectWrapper());

        /* ------------------------------------------------------------------- */    
        /* You usually do these for many times in the application life-cycle:  */    
                
        /* Get or create a template */
        Template temp = cfg.getTemplate("test.ftl");

        /* Create a data model */
        Map root = new HashMap();
        root.put("user", "Big Joe");
        Map latest = new HashMap();
        root.put("latestProduct", latest);
        latest.put("url", "products/greenmouse.html");
        latest.put("name", "green mouse");

        /* Merge data model with template */
        Writer out = new OutputStreamWriter(System.out);
        temp.process(root, out);
        out.flush();
    }
}  

다음과 같은 코드면 쉽게 템플릿 엔진을 사용할 수가 있다.
좀더 드는 공수는 FTL을 학습하는 것이지만, 학습곡선이 길지가 않을 것이다.


자바 속에 들어있는 HTML관련해서 String or StringBuffer로 이어서 만드는 객체들을 하나씩
제거하는 일만 남았다.


http://freemarker.sourceforge.net/docs/pgui_quickstart_all.html








Configuration클래스

- Main entry point into the FreeMarker API
- this class encapsulates the various configuration parameters
- This object is not synchronized.

http://freemarker.sourceforge.net/docs/api/freemarker/template/Configuration.html



Configuration클래스 샘플 코드

Configuration cfg = new Configuration();
// Specify the data source where the template files come from.
// Here I set a file directory for it:
cfg.setDirectoryForTemplateLoading(
        new File("/where/you/store/templates"));
// Specify how templates will see the data model. This is an advanced topic...
// but just use this:
cfg.setObjectWrapper(new DefaultObjectWrapper());  

What is FreeMarker?

2006/11/21 09:31
과거에는 velocity가 주로 템플릿 엔진으로 사용이 됐는데, 최근에는 webwork와 함께 FreeMarker가 주목을 많이 받고 있는듯 하다.

What is FreeMarker?

FreeMarker is a "template engine"; a generic tool to generate text output (anything from HTML to autogenerated source code) based on templates. It's a Java package, a class library for Java programmers. It's not an application for end-users in itself, but something that programmers can embed into their products.


Template + data model = output

Ubiquitous Language : 용어정리를 해보자
- We say that the output is created by merging a template and a data model
- Files like this are called templates.


Templates

<html>
<head>
  <title>Welcome!</title>
</head>
<body>
  <h1>
    Welcome ${user}<#if user = "Big Joe">, our beloved leader</#if>!
  </h1>
  <p>Our latest product:
  <a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>  




Data Model :  the data model is basically a tree
User inserted image


(root)
  |
  +- user = "Big Joe"
  |
  +- latestProduct
      |
      +- url = "products/greenmouse.html"
      |
      +- name = "green mouse"  



Directive

* 조건문만 알면 어떤 랭귀지라도 대강 코딩할 수 있죠? 다음과 같은 syntax입니다.
Synopsis
<#if condition>
  ...
<#elseif condition2>
  ...
<#elseif condition3>
  ...
...
<#else>
  ...
</#if>


* 기대하고 기대하는 loop사용하는 방법
<#list SequenceVar as variable>repeatThis</#list>
<p>And BTW we have these fruits:
<ul>
<#list whatnot.fruits as fruit> <li>${fruit} </#list> <ul>


* include
<html>
<head>
  <title>Test page</title>
</head>
<body>
  <h1>Test page</h1>
  <p>Blah blah...
<#include "/copyright_footer.html">
</body>
</html>  


* Using directives together : 함께 사용할 수도 있슴

<p>We have these animals:
<table border=1>
  <tr><th>Name<th>Price
  <#list animals as being>
  <tr>
    <td>
      <#if being.size = "large"><b></#if>
      ${being.name}
      <#if being.size = "large"></b></#if>
    <td>${being.price} Euros
  </#list>
</table>  


ouput을 만들기 위한 샘플코드

public String createTemplateContents(String fileName, Object root) throws Exception {
     final Writer out = new StringWriter();
   Configuration cfg = new Configuration();
    cfg.setClassicCompatible(false);
    cfg.setClassForTemplateLoading(getClass(), THEME_TEMPLATES_CLASSPATH);
    cfg.setObjectWrapper(new DefaultObjectWrapper());
    Template temp = cfg.getTemplate(fileName);
  temp.process(root, out);
     out.flush();
     return out.toString();
}


기타

(열심히 API학습중!)

오~ freemarker쓸만한데, TemplateModel 인터페이스는 감동이었다.
이거 잘 이용하면 DTO형태의 Proxy클래스를 만들지 않아도 되겠다.

Velocity에도 이런 기능이 있었을 텐데, 그땐 웹UI로만 사용을 해서 깊이 있게 못 봤는데,  앞으로 template engine은 freemarker를 사용하면서 좀더 깊이 있게 들여다 봐야 겠군.

일단 소기의 목적을 달성을 위한 만큼의 API공부는 달성!! 

잘 만든 Domain Model클래스를 이용하여, 타입이 확실한 형태의 도메인 모델을 이용한 코드를 만들수도 있다. 그건 차후에 샘플을 올리도록 하겠다. 매번 property의 이름을 찾아서 Map에 담는 형태보다는 사전에 정의된 Bean을 이용하면 intuitable populate가 가능하다.

http://freemarker.sourceforge.net/
http://freemarker.sourceforge.net/docs/api/index.html
http://freemarker.sourceforge.net/docs/dgui_quickstart_datamodel.html


BLOG main image
OOP and Java by ologist

공지사항

카테고리

All (649)
private!! (106)
WEB & IT (140)
Developer (400)