嵌入式Tomcat:提示、技巧和秘籍

嵌入式Tomcat的API非常方便,只需要几行代码就可以在应用程序中启动Tomcat实例。用户很容易地从Apache Tomcat中得到有用的特性,并应用到自己的应用程序中。

在大多数情况下,用户期望嵌入式Tomcat以与独立Tomcat的运行方式相同。例如,如果他们想要改变全局服务器配置,希望可以使用同样的sever.xml应用到嵌入式Tomcat。

但是当使用嵌入式Tomcat时,会发现他们是不支持即插即用。你必须对使用一些秘籍(Hack)进行改善将其集成到应用程序中,使它得到更充分的利用。

嵌入式Tomcat中一些实用的特性并不支持即插即用:

  1. 支持服务器描述符(server . xml)。
  2. 支持全局部署描述符(web . xml)。
  3. 支持Webapp特定上下文描述符(context.xml)。

在这篇文章里,我将解释在使用嵌入式Tomcat时克服上述局限的一些技巧和窍门。

Tomcat类用来在应用程序中嵌入Tomcat。但最好用我们自己的方式扩展这个类,这将使得我们可以自由重写一些需要自定义的重要方法。下面是克服上述局限的一些技巧:

1、支持服务器描述(server.xml)

在一个标准的服务器实例中,可以通过Catalina类读取、解析和初始化sever.xml。它创建了一个Digester类的实例,把sever.xml文件转化成文件流。在继承的Tomcat类中,我们可以创建一个继承Catalina的内部类,然后重载创建Digester实例的方法就可以了。

private static class MyExtendedCatalina extends Catalina {
    @Override
    public Digester createStartDigester() {
        return super.createStartDigester();
    }
}

可以使用这个方法读取sever.xml作为输入流:

Digester digester = extendedCatalina.createStartDigester();
digester.push(extendedTomcat);
try {
    digester.parse(inputStreamOfServerXml);
} catch (IOException e) {
    log.error("Error while parsing server.xml", e);
}

可以看出,在初始阶段Digester 实例和Tomcat 实例共同作用,按照一定顺序自动运行。上述代码片应当在扩展后的Tomcat实例初始化阶段执行。

2、支持全局部署描述符(web.xml)

全局部署描述也就是所谓的root(默认的Webapps部署描述符)。Webapps从web.xml中继承了默认值,并使用应用特定部署描述符的值进行覆盖。这个文件提供了一些便利,比如可以为Webapps定义一些全局属性(默认会话超时等)。

为了把web.xml添加到所有Webapp中,必须覆盖Tomcat类的“addWebapp”方法,然后添加以下代码到重写(Overridden)后的方法。

Context context = null;
try {
    context = new StandardContext();
    context.setName(contextPath);
    context.setPath(contextPath);
    context.setDocBase(webappFilePath);
    context.setRealm(this.getHost().getRealm());
    ContextConfig contextConfig = new ContextConfig();
    context.addLifecycleListener(contextConfig);
    if (new File(pathToGlobalWebXml).exists()) {
        contextConfig.setDefaultWebXml(pathToGlobalWebXml);
    } else {
        // 1
        contextConfig.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
    }
    host.addChild(context);
} catch (Exception e) {
    log.error("Error while deploying webapp", e);
}

上面的代码在服务器主机上添加并部署了一个子应用Webapp,Tomcat类的“addWebapp”方法也具有同样的功能。但是需要注意的是(代码1),在上述代码中我们使用setDefaultWebXml方法将web.xml设置到当前webapp的上下文中。在通常Tomcat类的addWebapp方法中,总是将其设置成NO_DEFAULT_XML。

3 、支持Webapp特定上下文描述符 (context.xml)

使用全局web.xml时,还有一个非常实用的特性:用户可以在文件中为自己的Webapp添加一些元数据。这些信息同样会添加到Webapp的META-INF目录中。通常会用来添加环境资源信息,例如数据源、JNDI资源、阀门(Valve)、类加载器等Webapp特定信息。为了使用此特性,应该在主机对象(host object)调用“addChild”方法前,添加下面代码段到Tomcat类中重写的“addWebapp”方法。

JarFile webappWarFile = new JarFile(webappFilePath);
JarEntry contextXmlFileEntry = webappWarFile.getJarEntry("META-INF/context.xml");
if (contextXmlFileEntry != null) {
    // 2
    context.setConfigFile(new URL("jar:file:" + webappFilePath + "!/" + "META-INF/context.xml"));
}

应该注意的是(代码2),它调用了Webapp中context对象的setConfigFile方法,反过来将context.xml描述符添加到Webapps的上下文中。

总结

上述三种特性是通常的Tomcat环境中最常用的。通过学习上述技巧,可以克服在使用嵌入式Tomcat时所遇到的问题。可以进一步拓展这些技巧以获取更多的特性,例如支持全局context.xml等。

原文链接: kishanthan 翻译: ImportNew.com - 李阳
译文链接: http://www.importnew.com/8388.html
[ 转载请保留原文出处、译者和译文链接。]

关于作者: 李阳

(新浪微博:@蠡暘

查看李阳的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

1 条评论

  1. yubinlai 说道:

    怎么没看到在哪里启动,看不明白啊

    Thumb up 0 Thumb down 0

跳到底部
返回顶部