RSS

利用Mailbox为日志型web应用服务

12 Jul

很多时候,我们都以类似日志的方式做记录,而回顾历史时,我们想看到的不只是一条条的历史记录,更多的是期望能以某种方式对记录信息做聚集,并有组织地、最好是华丽丽地展现出来。为这类需求去开发web应用,如果仍采用典型的Browser <–> Web server <–> Database 的设计(如古老的S.S.H.常做的那样)是不好的。

  • 原因一,数据库大材小用。单纯的数据内容加上更加单纯的关系,如果用一关系型数据库,那真是浪费;
  • 原因二,Web form提交记录的方式死板。日志型的信息何必要以登录后提交页面的方式记录,太过正式了吧,为什么不是发一条微博或者一封邮件就顺带着记录了呢?

如果考虑到微博的私密性不够,那么就邮件吧:让你的邮箱为你忠实记录下这些日志型的记录——用约定的字眼为邮件打上标签后发送,让设计的web应用从你指定的收件箱中抓取此类邮件,分析内容获得历史记录,适当地做信息聚集,然后将你的记录信息华丽地展现在页面上(比如这样)。

应用的设计框架画成下图。

可以看到设计中很重要的一点是周期性地将内存维护的数据与mailbox同步,这一步的工作应该是交给独立的后台线程去做的。不采用实时访问mailbox取数据的原因是显而易见的——慢,并发就更难了;同时,考虑到记录本身的数据量不大,实时性也无苛求,所以维护内存数据库在这里十分划得来。

这种设计的好处还有:

  • 多个用户的记录都通过邮件发送到同一个邮箱,邮件本身除了标题内容之外还记录了发件人、时间等,我们的web应用可以直接利用它们;
  • 通常web应用都不免被基于数据库的CRUD困住脱不开身,而上图的设计却没有为我们这个需求简单的应用添麻烦,开发人员可把精力更多地放在提取信息和创建丰富的页面展现上。

最后回归到代码。使用“mail.jar”访问邮件的代码可以参考下面的demo. 不要错引或多引关于mail的jar包哦,因为疏忽曾引入了两个不同的但都关于mail的jar包,以致跑起的程序取不到邮件却又不报错误,本人吃过这个亏了,所以希望读者小心。

import com.sun.security.sasl.Provider
import java.security.Security
import java.util.Properties
import javax.mail._

class MailFetcher {

  def connect(username: String, password: String) : Store = {
    Security.addProvider(new Provider)

    val SSL_FACTORY: String = "javax.net.ssl.SSLSocketFactory"
    val pop3Props: Properties = new Properties

    pop3Props.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY)
    pop3Props.setProperty("mail.pop3.socketFactory.fallback", "false")
    pop3Props.setProperty("mail.pop3.port", "995")
    pop3Props.setProperty("mail.pop3.socketFactory.port", "995")

    val session = Session.getInstance(pop3Props, null)
    val store = session.getStore("pop3")
    store.connect("pop.gmail.com", 995, username, password)

    store
  }

  def fetchMailsFromFolder(folderName: String, store: Store) : Array[Message] = {
    val folder = store.getFolder(folderName)
    folder.open(Folder.READ_ONLY)
    folder.getMessages();
  }

  def printMessagesInfo(messages: Array[Message]) {
    printTotalCount(messages.length)
    printSubjects(messages)
  }

  private def printTotalCount(count: Int) {
    println("Total count of emails: " + count)
  }
  private def printSubjects(messages: Array[Message]): Unit = {
    messages.foreach(msg => println(msg.getSubject))
  }

}

object MailFetcher {
  def main(args: Array[String]) {

    val mailFetcher = new MailFetcher

    val store = mailFetcher.connect("your.account@gmail.com", "your.password")

    val messages = mailFetcher.fetchMailsFromFolder("INBOX", store)

    mailFetcher.printMessagesInfo(messages)
  }
}
 

About Wu Shaobo

@ThoughtWorks
Comments Off on 利用Mailbox为日志型web应用服务

Posted by in Uncategorized

 

Comments are closed.