静态网站/博客生成器(static site/blog generator)的产品已有不少,各种语言各种框架的都有,其中不乏优秀的产品,为什么还要开发一个自己的生成器呢?
简单说来,主要是基于笔者个人对开发语言的选择和生成速度的考虑。
之前在使用 Octopress 的过程中,需要定制化界面时,就不得不去熟悉 Ruby 和 Liquid,虽然语法并不难,但进行大的改动时总觉得不是那么得心应手,于是产生了写一个 Java 版的静态网站/博客生成器的想法。
这不是说 Ruby 不好,事实上,Ruby 绝对是一个优秀的编程语言。事实上,同样的业务逻辑,用 Java 实现比 Ruby 要多写不少代码。
之所以选用 Java,完全是因为笔者对 Java 更为熟悉。
个人觉得,安装 Java 运行环境相对 在 Windows 下安装配置 Octopress,还是会简单很多。
还有许多其它语言版本的生成器,笔者没有一一试用,不好妄自评论,可参考这里。
OpooPress 生成的速度很快——这绝对是其亮点之一。
以下是包含有 1000 篇文章的博客的生成过程截图:
也就是说生成 1000 篇文章大约在 5 秒多时间内就完成了。复制这 1000 篇文章到 Octopress,生成时间则要一分钟左右。这个差距还是比较明显的。
运行环境大致情况:ThinkPad T400, 2G RAM, Sun JDK 1.6, Ruby 1.9.2.
用于测试的 1000 篇文章是机器随机生成的,生成规则:每文 5 至 70 个段落,每段落 3 至 15 个句子,每个句子 10 到 30 个汉字。
详见以下 Java 代码:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.security.SecureRandom; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.apache.commons.io.IOUtils; public class GeneratePosts { private static SecureRandom random = new SecureRandom(); private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); private static final String EXCERPT_SEPARATOR = "<!--more--" + ">"; //每句最少字数,最大字数 private int sentenceMinWords = 10; private int sentenceMaxWords = 30; //每段最少,最大句子数 private int paragraphMinSentences = 3; private int paragraphMaxSentences = 15; //内容最少,最大段落数 private int contentMinParagraphs = 5; private int contentMaxParagraphs = 70; private int categoryNum = 10; public static void main(String[] args) throws IOException { File dir = new File("."); GeneratePosts generatePosts = new GeneratePosts(); //generatePosts.generatePost(new File(dir, new Date(), 100); Calendar cal = Calendar.getInstance(); for(int i = 0; i < 1000 ; i++){ Date date = cal.getTime(); cal.add(Calendar.DAY_OF_MONTH, -1); //System.out.println(date); generatePosts.generatePost(dir, date, 1001 + i); } } public String generateWord() { try { int hightPos = (176 + Math.abs(random.nextInt(39)));// 获取高位值 int lowPos = (161 + Math.abs(random.nextInt(93)));// 获取低位值 byte[] b = new byte[2]; b[0] = (new Integer(hightPos).byteValue()); b[1] = (new Integer(lowPos).byteValue()); return new String(b, "GBK");// 转成中文 } catch (UnsupportedEncodingException e) { System.err.println(e); return ""; } } public String generateSentence(int sentenceMinWords, int sentenceMaxWords){ StringBuffer sb = new StringBuffer(); int len = sentenceMinWords + random.nextInt(sentenceMaxWords - sentenceMinWords); for(int i = 0 ; i < len ; i++){ sb.append(generateWord()); } return sb.toString(); } public String generateParagraph(){ StringBuffer sb = new StringBuffer(); int len = paragraphMinSentences + random.nextInt(paragraphMaxSentences - paragraphMinSentences); for(int i = 0 ; i < len ; i++){ sb.append(generateSentence(sentenceMinWords, sentenceMaxWords)); sb.append("。"); } return sb.toString(); } public void generateContent(PrintWriter w){ int len = contentMinParagraphs + random.nextInt(contentMaxParagraphs - contentMinParagraphs); for(int i = 0 ; i < len ; i++){ w.println(generateParagraph()); if( i == 0 ){ w.println(EXCERPT_SEPARATOR); } w.println(); } } public void generatePost(File dir, Date date, int index) throws IOException{ String title = generateSentence(5, 12); String category = "Category" + random.nextInt(categoryNum); String filename = format.format(date) + "-the-" + index + ".markdown"; File file = new File(dir, filename); FileOutputStream stream = null; OutputStreamWriter writer = null; PrintWriter pw = null; try { stream = new FileOutputStream(file); writer = new OutputStreamWriter(stream, "UTF-8"); pw = new PrintWriter(writer); pw.println("---"); pw.println("layout: post"); pw.println("title: \"" + title + "\""); pw.println("date: " + dateFormat.format(date)); pw.println("comments: true"); pw.println("categories: [" + category + "]"); pw.println("---"); generateContent(pw); System.out.println("File generated: " + file); } catch (IOException e) { throw e; }finally{ IOUtils.closeQuietly(pw); IOUtils.closeQuietly(writer); IOUtils.closeQuietly(stream); } } }
PS: 文中揭示了 OpooPress 的另外一个特性,那就是 OpooPress 文章的格式和 Octopress 是一致的,如果需要迁移,直接复制过来即可。
Source |
|