如何嵌入Tomcat 6?
Posted
技术标签:
【中文标题】如何嵌入Tomcat 6?【英文标题】:How to embed Tomcat 6? 【发布时间】:2010-10-13 00:08:40 【问题描述】:我目前正在生产环境中的 Tomcat 6 上运行我的 web 应用程序,并且想评估在嵌入式模式下运行 Tomcat。
除了api documentation 中的内容之外,还有什么好的教程或其他资源吗?
【问题讨论】:
有什么理由使用 Tomcat 而不是 Jetty,Jetty 对此用例有很好的记录并且常用的嵌入式?如果您只是在寻找可以嵌入的 Servlet 容器,Jetty 很容易做到这一点。 嵌入 Jetty。但是,有tomcat-embed。 感谢您的指点。但是,这看起来并不完整、未积极开发或维护。所有提交的日期为 2008 年 5 月 11 日,其中一条日志消息称其“远未完成”。 这篇博文值得一看:Embedding Tomcat 7 【参考方案1】:代码不言自明。查看 pom.xml sn -p 和运行 tomcat 的类。
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>6.0.18</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>coyote</artifactId>
<version>6.0.18</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper</artifactId>
<version>6.0.18</version>
<scope>test</scope>
</dependency>
public class RunWebApplicationTomcat
private String path = null;
private Embedded container = null;
private Log logger = LogFactory.getLog(getClass());
/**
* The directory to create the Tomcat server configuration under.
*/
private String catalinaHome = "tomcat";
/**
* The port to run the Tomcat server on.
*/
private int port = 8089;
/**
* The classes directory for the web application being run.
*/
private String classesDir = "target/classes";
/**
* The web resources directory for the web application being run.
*/
private String webappDir = "mywebapp";
/**
* Creates a single-webapp configuration to be run in Tomcat on port 8089. If module name does
* not conform to the 'contextname-webapp' convention, use the two-args constructor.
*
* @param contextName without leading slash, for example, "mywebapp"
* @throws IOException
*/
public RunWebApplicationTomcat(String contextName)
Assert.isTrue(!contextName.startsWith("/"));
path = "/" + contextName;
/**
* Starts the embedded Tomcat server.
*
* @throws LifecycleException
* @throws MalformedURLException if the server could not be configured
* @throws LifecycleException if the server could not be started
* @throws MalformedURLException
*/
public void run(int port) throws LifecycleException, MalformedURLException
this.port = port;
// create server
container = new Embedded();
container.setCatalinaHome(catalinaHome);
container.setRealm(new MemoryRealm());
// create webapp loader
WebappLoader loader = new WebappLoader(this.getClass().getClassLoader());
if (classesDir != null)
loader.addRepository(new File(classesDir).toURI().toURL().toString());
// create context
// TODO: Context rootContext = container.createContext(path, webappDir);
Context rootContext = container.createContext(path, webappDir);
rootContext.setLoader(loader);
rootContext.setReloadable(true);
// create host
// String appBase = new File(catalinaHome, "webapps").getAbsolutePath();
Host localHost = container.createHost("localHost", new File("target").getAbsolutePath());
localHost.addChild(rootContext);
// create engine
Engine engine = container.createEngine();
engine.setName("localEngine");
engine.addChild(localHost);
engine.setDefaultHost(localHost.getName());
container.addEngine(engine);
// create http connector
Connector httpConnector = container.createConnector((InetAddress) null, port, false);
container.addConnector(httpConnector);
container.setAwait(true);
// start server
container.start();
// add shutdown hook to stop server
Runtime.getRuntime().addShutdownHook(new Thread()
public void run()
stopContainer();
);
/**
* Stops the embedded Tomcat server.
*/
public void stopContainer()
try
if (container != null)
container.stop();
catch (LifecycleException exception)
logger.warn("Cannot Stop Tomcat" + exception.getMessage());
public String getPath()
return path;
public void setPath(String path)
this.path = path;
public static void main(String[] args) throws Exception
RunWebApplicationTomcat inst = new RunWebApplicationTomcat("mywebapp");
inst.run(8089);
public int getPort()
return port;
【讨论】:
我无法让这个运行,只能得到 404s.. 我错过了什么吗? 你是否相应地更改了 catalinaHome、port、classesDir、webappDir 的属性?【参考方案2】:虽然这篇文章有些陈旧,但我正在回答我自己的答案,因为它可以节省一些其他时间
package com.creativefella;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Embedded;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TomcatServer
private Embedded server;
private int port;
private boolean isRunning;
private static final Logger LOG = LoggerFactory.getLogger(TomcatServer.class);
private static final boolean isInfo = LOG.isInfoEnabled();
/**
* Create a new Tomcat embedded server instance. Setup looks like:
* <pre><Server>
* <Service>
* <Connector />
* <Engine>
* <Host>
* <Context />
* </Host>
* </Engine>
* </Service>
*</Server></pre>
* <Server> & <Service> will be created automcatically. We need to hook the remaining to an @link Embedded instnace
* @param contextPath Context path for the application
* @param port Port number to be used for the embedded Tomcat server
* @param appBase Path to the Application files (for Maven based web apps, in general: <code>/src/main/</code>)
* @param shutdownHook If true, registers a server' shutdown hook with JVM. This is useful to shutdown the server
* in erroneous cases.
* @throws Exception
*/
public TomcatServer(String contextPath, int port, String appBase, boolean shutdownHook)
if(contextPath == null || appBase == null || appBase.length() == 0)
throw new IllegalArgumentException("Context path or appbase should not be null");
if(!contextPath.startsWith("/"))
contextPath = "/" + contextPath;
this.port = port;
server = new Embedded();
server.setName("TomcatEmbeddedServer");
Host localHost = server.createHost("localhost", appBase);
localHost.setAutoDeploy(false);
StandardContext rootContext = (StandardContext) server.createContext(contextPath, "webapp");
rootContext.setDefaultWebXml("web.xml");
localHost.addChild(rootContext);
Engine engine = server.createEngine();
engine.setDefaultHost(localHost.getName());
engine.setName("TomcatEngine");
engine.addChild(localHost);
server.addEngine(engine);
Connector connector = server.createConnector(localHost.getName(), port, false);
server.addConnector(connector);
// register shutdown hook
if(shutdownHook)
Runtime.getRuntime().addShutdownHook(new Thread()
public void run()
if(isRunning)
if(isInfo) LOG.info("Stopping the Tomcat server, through shutdown hook");
try
if (server != null)
server.stop();
catch (LifecycleException e)
LOG.error("Error while stopping the Tomcat server, through shutdown hook", e);
);
/**
* Start the tomcat embedded server
*/
public void start() throws LifecycleException
if(isRunning)
LOG.warn("Tomcat server is already running @ port=; ignoring the start", port);
return;
if(isInfo) LOG.info("Starting the Tomcat server @ port=", port);
server.setAwait(true);
server.start();
isRunning = true;
/**
* Stop the tomcat embedded server
*/
public void stop() throws LifecycleException
if(!isRunning)
LOG.warn("Tomcat server is not running @ port=", port);
return;
if(isInfo) LOG.info("Stopping the Tomcat server");
server.stop();
isRunning = false;
public boolean isRunning()
return isRunning;
我也遇到了 404
错误并挣扎了一段时间。通过查看日志“INFO: No default web.xml
”,我怀疑它(如果这是一个警告,那么很容易发现)。诀窍是使用 Tomcat 提供的web.xml
( rootContext.setDefaultWebXml("web.xml")
) (conf/web.xml
)。原因是,它包括 DefaultServlet,它为 html、JS 等静态文件提供服务。使用 web.xml
或在您的代码中手动注册 servlet。
用法:
// start the server at http://localhost:8080/myapp
TomcatServer server = new TomcatServer("myapp", 8080, "/src/main/", true);
server.start();
// .....
server.stop();
不要忘记将默认的web.xml
放在该程序的同一目录中或指向正确的位置。
需要注意的是,shutdown hook的灵感来自Antonio's answer。
【讨论】:
我尝试了您的示例,我的应用程序启动了,我看到 spring 正在初始化,但是当我尝试访问我的应用程序时,我收到 spring 错误消息,提示找不到我的 jsps 的映射。 小更新:org.apache.catalina.startup.Embedded
已弃用,建议改用org.apache.catalina.startup.Tomcat
。进行此更改后,将进行许多链更改以使代码可运行。【参考方案3】:
使用 Tomcat 而非 Jetty 的原因有很多:
-
已经熟悉 Tomcat
其中一个正在开发需要轻松传输到 Tomcat 安装的 Web 应用程序
Jetty 开发人员文档实际上比 Tomcat 的文档更精彩(太棒了!)
在 Jetty 社区中获得答案有时可能需要数年时间,例如 2007 年。请参阅 Embedding Jetty
重要提示:在 Jetty 6.1.* 之后,每个 Web 应用程序都会打开到自己的 JVM,因此如果您尝试在独立访问和 Web 应用程序之间获得编程访问,您唯一的希望是通过 Web API。
如果您有问题,Tomcat 是一个开源项目,其知识产权归 Apache 基金会所有,Jetty 是开源项目,但归一家小型私营公司(Mortbay Consulting)所有
第 5 点对我的工作很重要。例如,我可以通过 Tomcat 直接访问 JSPWiki 实例,但使用 Jetty 时完全无法访问。我在 2007 年要求解决这个问题,但还没有听到答案。所以我最终放弃并开始使用 Tomcat 6。我研究过 Glassfish 和 Grizzly,但到目前为止,Tomcat 是(令人惊讶的)最稳定和有据可查的 Web 容器(实际上并没有说太多)。
【讨论】:
"每个 Web 应用程序都打开到它自己的 JVM":您从哪里得到这些信息?我怀疑这是否准确。 听起来更像是一个类加载器。很难说。 我很确定 webapps 不在它们自己的 JVM 中打开。他们默认使用单独的类加载器。要获得您想要的类加载器行为,只需使用webapp.setParentLoaderPriority(true);
- 我认为这是在 Jetty 文档中。
我在生产中使用过 Tomcat、Jetty 和 Grizzly,并且非常同意这个答案中所说的一切【参考方案4】:
这可能会有所帮助。
如果你下载Tomcat6.x的源码包,你会得到这个类:
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/startup/Catalina.html#main(java.lang.String[])
这是一个如何使用 Embedd 类的示例:它是一个用于停止|启动特定 Tomcat 安装的 shell。 (我的意思是你可以设置 CATALINA_BASE
指向现有的 Tomcat 安装)。
如果你编译这个,你可以这样运行:
java -D"catalina.base=%CATALINA_BASE%" -D"catalina.home=%CATALINA_HOME%" org.apache.catalina.startup.Catalina start
我不确定如何更改此代码以关闭服务器!
【讨论】:
【参考方案5】:几个月前读完这个帖子后,我写了这个项目:spring-embedded-tomcat。 它可以用来将tomcat6嵌入到基于Spring的应用程序中。
【讨论】:
【参考方案6】:我认为使用 Tomcat 7 或 Jetty 9 嵌入更容易。在这里你会发现一个很好的介绍:http://www.hascode.com/2013/07/embedding-jetty-or-tomcat-in-your-java-application/
【讨论】:
以上是关于如何嵌入Tomcat 6?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用嵌入式 tomcat 会话集群设置 Spring Boot 应用程序?