• JFinal自定义FreeMarker标签


    为什么采用freemarker?

    1、模板技术,不依附于语言和框架,前端和后端解耦,便于分工协作,更好的协同。

    2、页面相应速度快

    3、前端非常的灵活,采用自定义标签可以在不更改后端的基础上很容易的构造前端逻辑,可适应多变的网站。

    为什么要自定义标签?

    答案在第一个问题的第三点,我们需要一个前端灵活的架构,在不更改后端逻辑的基础上,很容易的改造前端逻辑。

    在SSH的架构中,自定义标签已经可以方便的实现(struts2的标签也是基于freemarker的自定义标签),但是用起来还是不够爽,需要大量的配置,繁琐的依赖注入等。用了jfinal以后,发现自定义freemarker标签在该框架中用起来极爽,寥寥几个类,几行代码就能将自定义标签应用起来。废话不多说了,上代码吧。

    第一步:实现标签类

     1 /**
     2  * 分类标签<br>
     3  * 参数:{parent_id:上级主键}
     4  * 返回值:{list:分类列表}
     5  * 
     6  * @author yongtree
     7  */
     8 public class CategoryListDirective implements TemplateDirectiveModel {
     9 
    10     
    11     public void execute(Environment env, Map params, TemplateModel[] loopVars,
    12             TemplateDirectiveBody body) throws TemplateException, IOException {
    13 
    14         List<Category> list = new ArrayList<Category>();
    15         if (params.containsKey("parent_id") && params.get("parent_id") != null) {
    16             list = Category.getCategoryList(params.get("parent_id").toString(),
    17                     Category.STATUS_ENABLED);
    18         } else {
    19             list = Category.getFirstCategoryList(Category.STATUS_ENABLED);
    20         }
    21 
    22         env.setVariable("list", DEFAULT_WRAPPER.wrap(list));
    23         body.render(env.getOut());
    24     }
    25 
    26 }

    第二步:action中引入

    1 setAttr("_category_list", new CategoryListDirective());

    第三步:页面是使用

    1 <@_category_list parent_id="2">
    2     <#list list as c>
    3         <a href="/category/${c.id}">${c.name}</a>
    4     </#list>
    5 </@_category_list>

    我们使用自定义标签的目的是灵活,就是要将action中要做到事情,能直接通过标签在页面上使用。而上面的第二步,需要在action中set,使其action的逻辑不灵活。自定义标签应该能脱离开具体的action,能在更多的模块中用到,不受action的限制。所以第二步需要稍加改造,这是我们可以采用jfinal的全局拦截器,将这些标签初始化内存中,在所有的action中都很容易的注入,当然你可以根据拦截器的相关配置和逻辑,将自定义标签指定到相应的action中。上代码吧

     1 /**
     2  * 自定义标签拦截器
     3  * @author yongtree
     4  */
     5 public class DirectiveInterceptor implements Interceptor {
     6 
     7     public static CategoryListDirective cld = new CategoryListDirective();
     8 
     9     public void intercept(ActionInvocation ai) {
    10         Controller c = ai.getController();
    11         c.setAttr(LABEL_CATEGORY_LIST, cld); 
    12                 ai.invoke();
    13 }
    14 
    15     public static final String LABEL_CATEGORY_LIST = "_category_list";
    16 
    17 }

    配置到Config中

    1 /**
    2      * 配置全局拦截器
    3      */
    4     public void configInterceptor(Interceptors me) {
    5         me.add(new AuthInterceptor());
    6         me.add(new DirectiveInterceptor());
    7     }
    超爽吧,简单几步,就搞定了自定义标签,这样你就可以把主要的查询和业务封装到标签里。在不改变业务逻辑和结构的基础上,前端逻辑和展示需要调整,以后就只是前端开发人员或者网站美工的工作了,再辅以freemarker的macro宏定义,再前段封装出更加方便使用的界面,那就更加的灵活和高校。所以在以内容为主的网站上,极力推荐采用这种方式来设计你的前端。
  • 相关阅读:
    页面适应UIWebView大小,不出现横向滚动条[转]
    switch case 遍历 table表头的时候使用枚举来便利 (switch 不支持字符串类型,用这种方式来达到使用目的)
    Builder 解析 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
    用2个层来显示 table 第一行 定位 效果。 支持ie6/ie7/ff/chrome,两个方向滚动条 ,保证最后一列也能对齐
    FORM 不换行的方法
    table 固定显示第一行 & 动态改变table高度
    select options 排序(保持option 对象完整性)
    JQuery ajax 如何设置同步调用(同时只能触发一个函数) 解决与层显示信息时候的冲突问题
    针对ie6 用层来实现select的title 提示属性 (增加含有滚动条情况的支持)
    定义新对象方法
  • 原文地址:https://www.cnblogs.com/gy19920604/p/5648991.html
Copyright © 2020-2023  润新知