技术,互联网,eLearning …
« »
2009年10月26日eLearning

Sakai的组件模型

从知名度和用户量来看,Sakai不算是一个成功的学习管理系统(LMS),从这里的比较就可以看出来。但Sakai有大量资金支持,是集众多专业开发者的力量打造而成的,其软件设计方面还是颇值得研究的。

Sakai有一个内核,负责提供公用的服务并且管理不同的组件。此外,还有一些独立的web应用来实现多种不同的功能,这些web彼此之间相互隔离,但是可以调用Sakai的公用服务。这一功能是通过Sakai自有的Component Manager机制实现的。

Component Manager

Component Manager负责将Sakai的各部分组装起来,它使得service之间能够通讯,并且各个web app能够使用这些service。在通常情况下,servlet 容器里的web应用是独立运行的,它们之间不能通讯,并且不能输出可共享的服务。Component Manager通过自定义ClassLoader的方式,提供了一些可共享的服务,以供各个web应用使用,同时,Sakai也提供了不用关闭整个服务而重启插件应用的方法。Sakai通过Component Manager来避开servlet容器的限制。Sakai里共享的服务API运行于servlet容器的特定位置,这个位置对所有的web应用可见。

与Component Manager功能相似的工业标准

Sakai的Component Manager是一个非标准实现,有两个实现类似功能的标准:

  • EJB容器,有JBoss, Weblogic, Websphere等相关实现
  • OSGI,有Apache felix, Eclipse Equinox等实现。Spring提供对于OSGI的支持,新版本3.0的组件都做成了OSGI bundle的形式。还有Sping DM项目对OSGI提供支持。

Component Manager的工作原理

Sakai的结构如下图所示:

Sakai结构图

在第一个web app启动时,Component Manager会随之启动。Component Manager为每一个component创建一个用来加载它的ClassLoader:

/**
 * Create the class loader for this component package
 *
 * @param dir
 *        The package's root directory.
 * @return A class loader, whose parent is this class's loader,
           which has the classes/ and jars for this component.
 */
protected ClassLoader newPackageClassLoader(File dir)
{
    // collect as a List, turn into an array after
    List urls = new Vector();

    File webinf = new File(dir, "WEB-INF");

    // put classes/ on the classpath
    File classes = new File(webinf, "classes");
    if ((classes != null) && (classes.isDirectory()))
    {
        try
        {
            URL url = new URL("file:" + classes.getCanonicalPath() + "/");
            urls.add(url);
        }
        catch (Throwable t)
        {
        }
    }

    // put each .jar file onto the classpath
    File lib = new File(webinf, "lib");
    if ((lib != null) && (lib.isDirectory()))
    {
        File[] jars = lib.listFiles(new FileFilter()
        {
            public boolean accept(File file)
            {
                return (file.isFile() && file.getName().endsWith(".jar"));
            }
        });

        if (jars != null)
        {
            for (int j = 0; j < jars.length; j++)
            {
                try
                {
                    URL url = new URL("file:" + jars[j].getCanonicalPath());
                    urls.add(url);
                }
                catch (Throwable t)
                {
                }
            }
        }
    }

    // make the array from the list
    URL[] urlArray = (URL[]) urls.toArray(new URL[urls.size()]);

    // make the classloader - my loader is parent
    URLClassLoader loader = new URLClassLoader(urlArray, getClass().getClassLoader());

    return loader;
}

Component的ClassLoader和每一个web应用有共同的父ClassLoader,这个父ClassLoader可以看见/WEB-INF/classes下的类,和所有/WEB-INF/lib/下的jar包。Component的ClassLoader和web应用的ClassLoader的行为很像,只是有一点不同,这个ClassLoader是标准的URLClassloader,它会首先委托自己的父ClassLoader来加载类,只有当父ClassLoader无法找到类时,才会自己的类路径下去寻找。而web应用的ClassLoader的行为和标准的ClassLoader的行为是不一样的,因为根据Servlet规范,web应用的ClassLoader需要首先寻找自己的类路径下的类和jar包,然后才会去寻找父ClassLoader的类路径。

日志信息 »

该日志于2009-10-26 22:51由 rockmaple 发表在eLearning分类下, 你可以发表评论。除了可以将这个日志以保留源地址及作者的情况下引用到你的网站或博客,还可以通过RSS 2.0订阅这个日志的所有评论。

没有评论

发表评论 »

返回顶部