--- layout: post title: "为什么开发 OpooPress" date: '2013-07-02 17:23' comments: true published: false keywords: "OpooPress, OpooPress vs Octopress" description: "关于 OpooPress 的一些比较好的特性简单介绍。并与 Octopress 的生成速度进行简单对比。" url: /why-i-develop-opoopress/ categories: ['website'] tags: ['opoopress'] --- 静态网站/博客生成器(static site/blog generator)的产品已有不少,各种语言各种框架的都有,其中不乏优秀的产品,为什么还要开发一个自己的生成器呢? 简单说来,主要是基于笔者个人对**开发语言**的选择和**生成速度**的考虑。 <!--more--> ## 一、Java 还是其它 之前在使用 Octopress 的过程中,需要定制化界面时,就不得不去熟悉 Ruby 和 Liquid,虽然语法并不难,但进行大的改动时总觉得不是那么得心应手,于是产生了写一个 Java 版的静态网站/博客生成器的想法。 这不是说 Ruby 不好,事实上,Ruby 绝对是一个优秀的编程语言。事实上,同样的业务逻辑,用 Java 实现比 Ruby 要多写不少代码。 之所以选用 Java,完全是因为笔者对 Java 更为熟悉。 个人觉得,安装 Java 运行环境相对 [在 Windows 下安装配置 Octopress](/octopress/),还是会简单很多。 还有许多其它语言版本的生成器,笔者没有一一试用,不好妄自评论,可[参考这里](https://iwantmyname.com/blog/2011/02/list-static-website-generators.html)。 ## 二、生成速度(Generate Speed) 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 代码: ```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 是一致的,如果需要迁移,直接复制过来即可。