自定義類繼承FreemarkerManager類,重寫protected Configuration createConfiguration(ServletContext servletContext)throws TemplateException方法定義有哪些TemplateDirectiveModel類與它的別名[自定義標簽名稱],通過Spring來取:
import java.util.Map; import javax.servlet.ServletContext; import org.apache.struts2.views.freemarker.FreemarkerManager; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import freemarker.template.Configuration; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; /** * 從spring取得所有的TemplateDirectiveModel類的對象,全部取出來,交給struts管理 * @author Administrator * */ public class DirectiveFreemarkerManager extends FreemarkerManager{ @Override protected Configuration createConfiguration(ServletContext servletContext) throws TemplateException { //調用你父類操作 Configuration configuration=super.createConfiguration(servletContext); //設定在頁面使用的標簽的類型 (([]、<>),[]這種標記解析要快些) [] SQUARE_BRACKET_TAG_SYNTAX , <>ANGLE_BRACKET_TAG_SYNTAX configuration.setTagSyntax(Configuration.AUTO_DETECT_TAG_SYNTAX); //取得spring所管理所有的對象 ClassPathXmlApplication, WebAplicationContext ApplicationContext appContext=WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); // 獲取實現TemplateDirectiveModel的bean Map<String, TemplateDirectiveModel> beans= appContext.getBeansOfType(TemplateDirectiveModel.class); //再把這些類,全部交給struts的freemarker來管理 //Component("upper") public class UpperDirective implements TemplateDirectiveModel for(String key : beans.keySet()){ Object obj=beans.get(key); //TemplateDirectiveModel if(obj!=null && obj instanceof TemplateDirectiveModel){ configuration.setSharedVariable(key, obj); } } return configuration; } }
在struts.xml中添加:
<!-- 讓struts來管理freemarker自定義標簽類 struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager --> <constant name="struts.freemarker.manager.classname" value="com.xxxx.struts.DirectiveFreemarkerManager"></constant>
編寫TemplateDirectiveModel,並交給Spring管理:
import java.io.IOException; import java.io.Writer; import java.util.Map; import org.springframework.stereotype.Component; import freemarker.core.Environment; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; /** * 自定義指定,作用,把嵌套的內容中的小寫全部轉換為大寫字母 * * @author Administrator * */ @Component("upper") public class UpperDirective implements TemplateDirectiveModel { //evn 環境輸出 //params 參數 //loopVars 循環 //body 內容 @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { //如果有參數 應該不支持參數 if(!params.isEmpty()){ throw new TemplateModelException( "這個指令不允許使用參數."); } if(loopVars.length!=0){ throw new TemplateModelException( "這個指令不允許使用循環參數."); } // 如果嵌套內容不為空的 if(body!=null){ //如果有內容,自己去重寫輸出流 body.render( new UpperCaseFilterWriter(env.getOut())); }else{ throw new RuntimeException("無內容異常"); } } //內部類 private static class UpperCaseFilterWriter extends Writer{ private final Writer out; //接收網頁中的輸出 流對象 public UpperCaseFilterWriter(Writer out){ this.out=out; } //cbuf 文字內容, off位移,len 文字長度 @Override public void write(char[] cbuf, int off, int len) throws IOException { char[] transformedChar=new char[len]; for(int i=0;i<len;i++){ transformedChar[i]=Character.toUpperCase(cbuf[i+off]); } out.write(transformedChar); } @Override public void flush() throws IOException { out.flush(); } @Override public void close() throws IOException { out.close(); } } }
編寫action,result—>字符串,type=”freemarker”:
<!-- 約定大於配置 /admin/Flinktype_list.action --> <package name="freemarkerPackage" namespace="/admin" extends="commonPackage" > <action name="*_*" class="{1}Action" method="{2}"> <result name="{2}" type="freemarker">/admin/template/{1}/{2}.ftl</result> </action> </package>
模板/template/upper.ftl:
<!DOCTYPE html> <html lang="ch-ZN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>freemarker自定義標簽</title> </head> <body> <@upper> bar <#-- All kind of FTL is allowed here --> <#list ["red", "green", "blue"] as color> ${color} </#list> baaz </@upper> <hr/> <@cms_linktype limit="0,10" > 請選擇分類: <select> <#list arrTypes as x> <option value="${x.id}">${x.typeName}</option> </#list> </select> </@cms_linktype> </body>