FreeMarker custom TemplateDirectiveModel (II)

FreeMarker is a written in the Java language template engine, which is based on a template to generate text output. FreeMarker has nothing to do with the Web container, that is in the Web, it does not know Servlet or HTTP. It not only can be used to achieve technical presentation layer, but also can be used to generate such as XML, JSP or Java. 

Abstract: freemarker is version 2.3.21 by way of BeansWrapperBuilder alternative DEFAULT_WRAPPER. 

Custom tags need to implement the interface execute method TemplateDirectiveModel this example code below 
public  class UserListDirective the implements TemplateDirectiveModel { 
    
    @Autowired 
    Private the UserDAO userDao; 
    @Override 
    public  void execute (the env Environment, the params the Map, TemplateModel [] loopVars, 
            TemplateDirectiveBody body) 
                      throws TemplateException, {IOException 
        String name= params.get("name").toString();
        List<User> userlist = userDao.findByProperty("name", name);

        env.setVariable("userList", getBeansWrapper().wrap(userlist));
        body.render(env.getOut());
    }
    
    public static BeansWrapper getBeansWrapper(){
        BeansWrapper beansWrapper = 
                         new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
        return beansWrapper;
    }
}
配置 UserListDirective 到 spring bean xml 中
<bean id="userListDirective" class="com.action.directive.UserListDirective"></bean>
将 spring bean 设置到 freemarkerConfig 全局变量中去。
<bean id="freemarkerConfig2"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/" />
        <property name="freemarkerVariables">
            <map >
                <entry key="userListDirective" value="userListTag" />
            </map>
        </property>
        <property name="freemarkerSettings">
            <props>
                <prop key="template_update_delay">0</prop>
                <prop key="defaultEncoding">UTF-8</prop>
                <prop key="url_escaping_charset">UTF-8</prop>
                <prop key="locale">zh_CN</prop>
                <prop key="boolean_format">true,false</prop>
                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                <prop key="date_format">yyyy-MM-dd</prop>
                <prop key="time_format">HH:mm:ss</prop>
                <prop key="number_format">0.######</prop>
                <prop key="whitespace_stripping">true</prop>
            </props>IF
    <#<@userListTag name = "zhangsan">
access method ftl file
    </ bean>
        </ Property>
 userList?? && userList?size gt 0>Tags and custom macros to solve a lot of repetitive work. 
FreeMarker a simple macro:

  
      
    


 <#macro the sayHello name = ""> 
    Hello $ {name}
 </ # Macro> 
then call the following form:

 <@sayHello name = "Shannon" /> 
However, in this template page limited ability to define the macro. [ 1 ] assumptions, many of us have to output a page popular ranking box, and ranking data dynamically acquired from the controller layer, we can use this macro to display complete all work, but only if the corresponding controller and interfaces need to pre-middle Top these go into the model, so this is a repetitive back-end work for it. Is there a way out of this also allows the back-end rework it? The answer is yes, which is the purpose in writing this blog. 

In a fortuitous opportunity to discover jeecms project used in this way, so learn a lot. 

FreeMarker can not only define macros in the template of the front page, you can also by extending its interface macros in the back end, what good is it? This way you like to make a page template with the back of the back-end capability from the front again. So that we can be a good solution [ 1 hypothesis at], we do not need at all interfaces in each controller deduplication add the required data to the model ranking, but instead encountered the corresponding macro when rendering FreeMarker template page it can go back to the back-end call the appropriate method to get the required data. Examples are as follows: 

Import freemarker.core.Environment;
 Import freemarker.template.
Importfreemarker.template.TemplateDirectiveModel; 

/ ** 
 * FreeMarker custom macros 
 * Get a ranked list download App 
 * parameter includes length (length of the list) mtypeCode (master type code) typeCode (small type code) rankMode (1,2,3 ranking mode) 
 * @author Shannon 
 * 
 * / 
public  class FMAppRankDirective the implements TemplateDirectiveModel { 

    @Resource (name = "appRankService" )
     Private appRankService appRankService; 
    
    
    @SuppressWarnings ( "an unchecked" ) 
    @Override 
    public  void Execute (the env Environment, the params the Map, TemplateModel [] loopVars, 
            TemplateDirectiveBody body) throws TemplateException, IOException {
         // DirectiveUtils borrowed jeecms project tools, mainly because it incorporates some unusual processing functions
         // in fact, can not it, params is a Map, the value can be themselves through key a, the null value is determined to do something 
        Integer = DirectiveUtils.getInt length ( "length" , the params); 
        Integer mtypeCode = DirectiveUtils.getInt ( "mtypeCode" , the params); 
        Integer typeCode = DirectiveUtils.getInt ( "typeCode" , the params); 
        Integer rankMode = DirectiveUtils.getInt ( "rankMode" , the params); 
        the ArrayList <the App> rankList = appRankService.getRankList (length, mtypeCode, typeCode, rankMode);
        
        env.setVariable ( "appRankList ", ObjectWrapper.DEFAULT_WRAPPER.wrap (rankList));
         IF (= body! Null ) { 
            body.render (env.getOut ()); 
        } 
    } 
} 
by implementing TemplateDirectiveModel FreeMarker in back-end implementation of a custom macro this macro function is very simple, just the Top "appRankList" go into the model based on the given parameters, then the template page you can use this variables. 

FreeMarker configuration parameters in this macro needs to join in. 

<the bean ID = "appRankDirective" class = "com.shannon.example.rank.util.FMAppRankDirective" /> 
<the bean ID = "the FreeMarkerConfigurer bean" class = "org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> 
    ... ... other configurations slightly ......
     <Property name = "freemarkerVariables"> 
        <the Map>
            ...... Other configurations slightly ......
             <entry Key = "appRankDirective" value-ref = "appRankDirective" /> 
        </ the Map> 
    </ Property> 
</ bean> 
used in the template page:

 <# - Application Top Box, title for title block, length is the length of the ranked list, mtypeCode main type code, the type code typeCode small, rankMode ranking mode is 
a total downloads, downloads 2 months, 3 growth of yesterday downloads
 -> 
<#macro appRankBox title = "" length = 10. 1 typeCode mtypeCode = = = -1. 1 rankMode> 
      <@appRankDirective length = length mtypeCode mtypeCode typeCode = = = typeCode rankMode rankMode /> 
        <H3 class = "Box-title"> $ title} {</ H3> 
    <div class = "Box"> 
      <UL class = "row-list">
        <#list appRankList as item> 
        ...... outputting content details omitted ......
         </ List #> 
        </ ul> 
    </ div> 
</ Macro #> 
Here I define a template page in a macro, it is responsible for the content and style of output, because the template page more intuitive macro, let the back-end macro is only responsible to take the data. Other pages directly using the "appRankBox" on it, and then to call it by the back-end "appRankDirective" macro come and collect data. 

In this way, controller to get away from the duplicate work.

 

Guess you like

Origin www.cnblogs.com/Jeely/p/11224376.html
ii