====== Freemarker ======
* http://freemarker.org/
* [[http://freemarker.sourceforge.net/docs/app_faq.html|Freemarker FAQ]]
* [[http://documentation.magnolia-cms.com/reference/templating/freemarker.html|Templating with FreeMarker - a primer]]
* [[https://github.com/kwon37xi/freemarker-template-inheritance|Freemarker Template Inheritance]]
===== Eclipse Editor 등록 =====
* ''General -> Content Types''에서 HTML에 ''*.ftl''을 등록해주면 HTML 템플릿 엔진으로 사용가능.
===== null 검사 =====
* http://www.j2eeprogrammer.com/2008/12/check-for-null-in-freemarker-24.html
* [[http://freemarker.incubator.apache.org/docs/dgui_template_exp.html|Expressions]] - Handling missing values 참조.
* ''??'' null이 아닌지 테스트
- null이 아닌가?(아니면 true)
<#if aVariable??>
- 문자열의 경우 null이거나, empty인가?
<#if aVariable?has_content>
혹은
<#if aVariable!?size > 0 or aVariable!?length > 0>
- Missing Value Operator. someValue가 존재하는가?
<#if someValue??>
...
- someValue와 someProp이 모두 존재해야 true
<#if (someValue.somePrope)??>
===== null 기본값 =====
* ''!기본값표현식''이 가능하다.
* 단, **''!기본값표현식'' 뒤에 다른 표현식이 오면 꼭 괄호로 감싸야한다.**
* null 일 경우 기본값으로 대체. 기본값표현식을 생량하고 ''!''만 쓰면 빈 문자열, 빈 시퀀스, 빈 해시를 나타내게 된다.
someValue!"기본값"
- 아래 구문은 작동하지 않는다. "'기본값' == '다른값'"을 기본값 표현식으로 간주하기 때문.
<#if someValue!'기본값' == '다른값'>
-> 다음처럼 변경할 것
<#if (someValue!'기본값') == '다른값'>
colors!['red', 'blue', 'green']
- someValue가 null이라도 자동으로 기본값으로 지정된다.
(someValue.someProp)!'기본값'
===== Macro =====
* [[http://whiteship.tistory.com/1480|Freemarker Macro]]
===== Java 코드로 만드는 지시자(Directives) =====
* [[http://freemarker.sourceforge.net/docs/pgui_datamodel_directive.html|Datamodel - Directives]]
* [[http://freemarker.sourceforge.net/docs/api/freemarker/template/TemplateDirectiveModel.html|TemplateDirectiveModel (FreeMarker 2.3.19 API)]]
===== Macro/Function 인자 null 문제 =====
* Macro와 Function의 인자에 null 값이 넘어오면 인자가 아예 없는 것으로 취급하여 오류가 발생한다.
* Macro와 Function 선언시 인자에 default 값을 지정하고 해당 default값이 올 경우 없는 값으로 간주하고 오류 처리를 하는 로직이 있어야 한다.
<#macro showDealUnitTemplate deals deal?default.. idx>...#macro>
혹은..
<#macro showDealUnitTemplate deals deal="" idx>...#macro>
===== TemplateMethodModel =====
* JSP의 Function 커스텀 태그 같이 함수 역할의 모델을 만들어 사용할 수 있다.
* [[http://freemarker.sourceforge.net/docs/pgui_datamodel_method.html|Datamodel - Method]]
* [[http://freemarker.sourceforge.net/docs/api/freemarker/template/TemplateMethodModel.html|freemarker.template.TemplateMethodModel]] : 모든 인자를 문자열로 변환하는 메소드 모델. deprecated
* [[http://freemarker.sourceforge.net/docs/api/freemarker/template/TemplateMethodModelEx.html|freemarker.template.TemplateMethodModelEx]] : 인자의 데이터 형을 그대로 유지하는 메소드 모델
===== TemplateDirectiveModel =====
* 커스텀 지시자(Directive)를 만든다.
* [[http://freemarker.incubator.apache.org/docs/api/freemarker/template/TemplateDirectiveModel.html|TemplateDirectiveModel]]
* [[http://freemarker.incubator.apache.org/docs/pgui_datamodel_directive.html|Freemarker Directives]]
===== ObjectWrapper =====
* [[http://freemarker.incubator.apache.org/docs/pgui_datamodel_objectWrapper.html|ObjectWrappers]]
* Freemarker에서 템플릿에 전달된 데이터 모델 객체를 템플릿에 적합하게 변환하는 역할.
==== ObjectWrapperAndUnwrapper ====
* [[http://freemarker.incubator.apache.org/docs/api/freemarker/template/ObjectWrapperAndUnwrapper.html|ObjectWrapperAndUnWrapper]]
* ''TemplateModel''로 변환된 모델에서 원래의 Java 객체를 빼내는 역할. 대부분의 ObjectWrapper는 이 인터페이스를 구현한다.
==== BeansWrapper ====
* [[http://freemarker.sourceforge.net/docs/pgui_misc_beanwrapper.html|BeanWrapper]]
* [[http://freemarker.sourceforge.net/docs/api/freemarker/ext/beans/BeansWrapper.html|freemarker.ext.beans.BeansWrapper]] 객체를 생성하지 않고 Reflection으로 Freemarker에서 사용하는 모델을 만들어준다.
===== 설정 =====
==== 숫자 포맷팅 ====
* 기본적으로 로케일에 따라 쉼표 혹은 마침표를 붙여주는 방식으로 숫자를 출력하므로 보통 숫자로 출력하려면 아래와 같은 설정이 필요하다.
cfg.setNumberFormat("0.######"); // now it will print 1000000
==== Template Cache ====
캐시를 지정해 속도를 높여야 한다.
[[http://freemarker.incubator.apache.org/docs/pgui_config_templateloading.html|Template loading]] 참조.
cfg.setTemplateUpdateDelayMilliseconds(3600000L); // 1hour 템플릿 파일 갱신 여부 체크 주기
cfg.setCacheStorage(new MruCacheStorage(500, 5000)); // strong 500, soft 5000
* ''MruCacheStorage'' 캐싱 전략은 ''strong''에 템플릿을 캐시하다가 꽉차면 least recently used 템플릿을 ''soft'' 영역으로 옮긴다.
* ''strong'' : JVM Full GC 시에도 GC 대상에 들어가지 않는다.
* ''soft'' : JVM Full GC 시에 GC 대상이 된다.
* 기본값은 ''strong=0'', ''soft=Integer.MAX_VALUE''
* ''strong''을 템플릿 갯수와 Heap 할당량에 따라 명시적으로 지정해주는 것이 좋다.