应用Beetl实现静态页生成

使用Beetl实现静态页生成
使用Beetl 1.1实现静态页的生成。
使用struts1.2
首先在Lisener中设置ServletGroupTemplate相关配置。
模版文件位于WEB-INF/template下
public class InitLisener implements ServletContextListener{
	static Log log = LogFactory.getLog(InitLisener.class);
	
	public void contextDestroyed(ServletContextEvent arg0) {
		ActionServletContext.destroyed();
	}

	public void contextInitialized(ServletContextEvent event) {
		log.info("加载资源文件");
		ServletContext context = event.getServletContext();
		String configPath = context.getRealPath("//");
		ServletGroupTemplate.intance().init(context);
	    ServletGroupTemplate.intance().getGroup().config("<!--:", "-->", "${", "}");
	    ServletGroupTemplate.intance().getGroup().setCharset("UTF-8");
	    ServletGroupTemplate.intance().getGroup().registerFunction("fn.substring",new SubStringFunction());
	    ServletGroupTemplate.intance().getGroup().registerFunction("fn.length",new LengthFunction());
	    
		//context.setAttribute("templatepath", context.getRealPath("WEB-INF/template"));
		System.out.println(context.getRealPath("WEB-INF/template"));
		
		ActionServletContext.setServletContext(context);
		//PropertiesUtil.loadConfig();
	}

}


Action类,其中模拟了一些数据,输出路径为跟路径,文件名为index.html
public class StaticPageAction extends Action {
	/*
	 * Generated Methods
	 */

	/**
	 * Method execute
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 */
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		PrintWriter pWriter = null;
		ActionForward forward = new ActionForward();
		response.setCharacterEncoding("UTF-8");
		
		String templatePath = (String) ActionServletContext.getServletContext()
				.getAttribute("templatepath");
		String rootpath = ActionServletContext.getServletContext().getRealPath(
				"/");
		rootpath = rootpath + "/index.html";
		
		List<Channel> channelList = getNewsData();
		try {
			pWriter = response.getWriter();
			Template template = ServletGroupTemplate.intance().getTemplate(
					"/index.html", request, response);
			template.set("channelList", channelList);
			template.set("user", "chenlei");
			template.set("Chal", new Channel(1, "栏目test", "栏目说明", 0, 10, 30));

			StringWriter writer = new StringWriter();
			template.getText(writer);
			// false为从文件开始处写入
			OutputStreamWriter outWriter = new OutputStreamWriter(
					new FileOutputStream(rootpath, false), "UTF-8");
			System.out.println(writer.toString());

			Writer out = new BufferedWriter(outWriter);
			out.write(writer.toString());
			out.flush();
			out.close();

			pWriter.print("输出首页成功!<a href='index.jsp'>返回</>");
		} catch (IOException e) {
			pWriter.print("输出首页失败!");
		} catch (BeeException e) {
			// e.printStackTrace();
		}

		return null;
	}

	private List<Channel> getNewsData() {

		List<Channel> newList = new ArrayList<Channel>(20);
		for (int i = 1; i <= 10; i++) {
			Channel chnnel = new Channel(i, "栏目" + i, "栏目说明" + i, 0, 10, 30);
			for (int j = 1; j <= 11; j++) {
				News news = new News(
						j + i,
						"新闻消息" + j + i,
						"新华社消息: 控制语句占位符号是/<!--: ,这样,尽可能然模板少破坏原有文件,你可以通过浏览器直接浏览模板文件",
						new Date(), "chnnal/news/" + j + i + "html");
				news.setChannelId(i);
				news.setChannelTitle(chnnel.getChnnelTitle());
				chnnel.addNewsList(news);
			}
			newList.add(chnnel);
		}
		return newList;
	}
}


模版文件:index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Index.html</title>
	
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

  </head>
  
  <body>
  <!--:if(user!=null){  -->
  	你好!${user}<br>
  	${Chal.chnnelTitle}
  	${channelList.~size}
  <!--:}  -->
    栏目列表
    
   <div>
   
   <!--: if(channelList.~size!=0){
      for(Channel in channelList){  -->
   <span style="color:red;">${Channel.chnnelTitle}</span>
   	<ul>
		<!--:
		 for(News in Channel.newsList){-->
   		<li>[<!--:if(fn.length(News.channelTitle)>2){ -->${fn.substring(News.channelTitle,0,2)}…<!--: }else{ -->${News.channelTitle} <!--:} -->]-${News.title}---[${News.newdate,dateFormat='yyyy-MM-dd'}]</li>
   		<!--: } -->
   	</ul>
   	<!--: }
   	}else {  -->
   	<span style="color:red;">没有数据</span>
   	<!--:}  -->
   </div>
  </body>
</html>

web.xml中的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <listener>
    <listener-class>com.otos.cl.common.listerner.InitLisener</listener-class>
  </listener>
  <context-param>
<param-name>GroupTemplate.Root</param-name>
<param-value>/WEB-INF/template</param-value>
</context-param>
<context-param>
<param-name>GroupTemplate.Optimize</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>GroupTemplate.NativeCall</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>GroupTemplate.Check</param-name>
<param-value>2</param-value>
</context-param>
  <filter>
    <filter-name>encode</filter-name>
    <filter-class>com.otos.cl.common.filter.FilterEncoding</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encode</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>act</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>3</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>3</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>act</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    
  </welcome-file-list>
</web-app>

由于要对显示的字符串进行截取,定义了两个函数:
/**
 * 用于在模版中截取字符串长度的函数
 * 
 * @author chenl
 * 
 */
public class SubStringFunction implements Function {

	public Object call(Object[] objects, Context ctx) {
		String parentStr = "";
		Integer start = 0;
		Integer end = 0;
		Object str = objects[0];
		if (str == null) {
			return "";
		} else {
			parentStr = String.valueOf(str);
		}

		Object startindex = objects[1];
		if (startindex == null) {
			return "";
		} else {
			start = Integer.valueOf(startindex.toString());
		}
		if (objects.length >= 3) {
			Object endindex = objects[2];
			if (endindex != null) {
				end = Integer.valueOf(endindex.toString());
			}
		}
		if (start < 0 || end < 0) {
			throw new IllegalStateException("SubString函数中参数startindex和endindex不能小于0");
		}

		int length = parentStr.length();

		if (length == 1) {
			return parentStr;
		} else {
			if (end == 0)
				parentStr = parentStr.substring(start);
			else
				parentStr = parentStr.substring(start, end);
		}

		return parentStr;
	}
}


/**
 * Beetl自定义函数
 * @author chenl
 *
 */
public class LengthFunction implements Function {

	public Object call(Object[] arg0, Context arg1) {
		int length = 0;
		if(arg0.length==1){
			Object obj = arg0[0];
			if(obj instanceof String) {
				length = ((String) obj).length();
			}else if(obj instanceof Integer){
				length = ((String) obj).length();
			}else if(obj instanceof Double){
				length = ((String) obj).length();
			}else if(obj instanceof Float){
				length = ((String) obj).length();
			}else{
				throw new IllegalStateException("参数不正确");
			}
		}else{
			throw new IllegalStateException("参数不正确");
		}
		return length;
	}

}


生成结果:index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Index.html</title>
	
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  
  <body>
  	你好!chenlei<br>
  	栏目test
  	10
    栏目
    
   <div>
   
   <span style="color:red;">栏目1</span>
   	<ul>
   		<li>[栏目…]-新闻消息11---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息21---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息31---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息41---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息51---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息61---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息71---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息81---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息91---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息101---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息111---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目2</span>
   	<ul>
   		<li>[栏目…]-新闻消息12---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息22---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息32---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息42---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息52---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息62---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息72---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息82---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息92---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息102---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息112---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目3</span>
   	<ul>
   		<li>[栏目…]-新闻消息13---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息23---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息33---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息43---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息53---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息63---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息73---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息83---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息93---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息103---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息113---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目4</span>
   	<ul>
   		<li>[栏目…]-新闻消息14---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息24---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息34---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息44---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息54---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息64---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息74---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息84---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息94---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息104---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息114---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目5</span>
   	<ul>
   		<li>[栏目…]-新闻消息15---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息25---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息35---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息45---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息55---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息65---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息75---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息85---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息95---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息105---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息115---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目6</span>
   	<ul>
   		<li>[栏目…]-新闻消息16---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息26---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息36---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息46---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息56---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息66---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息76---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息86---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息96---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息106---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息116---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目7</span>
   	<ul>
   		<li>[栏目…]-新闻消息17---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息27---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息37---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息47---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息57---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息67---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息77---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息87---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息97---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息107---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息117---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目8</span>
   	<ul>
   		<li>[栏目…]-新闻消息18---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息28---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息38---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息48---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息58---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息68---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息78---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息88---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息98---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息108---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息118---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目9</span>
   	<ul>
   		<li>[栏目…]-新闻消息19---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息29---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息39---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息49---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息59---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息69---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息79---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息89---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息99---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息109---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息119---[2012-05-07]</li>
   	</ul>
   <span style="color:red;">栏目10</span>
   	<ul>
   		<li>[栏目…]-新闻消息110---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息210---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息310---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息410---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息510---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息610---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息710---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息810---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息910---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息1010---[2012-05-07]</li>
   		<li>[栏目…]-新闻消息1110---[2012-05-07]</li>
   	</ul>
   </div>
  </body>
</html>


感觉自定义函数功能不错,但是也麻烦了些,两个函数就要写两个类。
如果能归类就好了,比如对字符串的操作,一个自定义函数中不同的方法就可以搞定。
1 楼 javamonkey 2012-05-18  
非常好的建议啊,可以让GroupTempl注册一个特殊的类,此类实现FunctionPackage接口

class myStringsFunction implments FunctionPackage
{

   @Override
   public String getPackageName(){
     return "mycom.string"
    }

    public string substring(String str,int,int,Context ctx){........}

    public int lenght(String str,Context ctx){...........}
}

然后,GroupTemplate.registerFunctionPackage(new myStringsFunction() )

这样,就可以在模板里使用
${mycom.string.substring("abcddd",1,4)}

你觉得怎么样?
2 楼 chenlei65368 2012-05-18  
mycom
javamonkey 写道
非常好的建议啊,可以让GroupTempl注册一个特殊的类,此类实现FunctionPackage接口

class myStringsFunction implments FunctionPackage
{

   @Override
   public String getPackageName(){
     return "mycom.string"
    }

    public string substring(String str,int,int,Context ctx){........}

    public int lenght(String str,Context ctx){...........}
}

然后,GroupTemplate.registerFunctionPackage(new myStringsFunction() )

这样,就可以在模板里使用
${mycom.string.substring("abcddd",1,4)}

你觉得怎么样?

这样不错