为什么采用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 }