Java 如何嵌入Tomcat 6?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/640022/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to embed Tomcat 6?
提问by otto.poellath
I'm currently running my webapps on Tomcat 6 in production, and would like to evaluate running Tomcat in embedded mode.
我目前正在生产中的 Tomcat 6 上运行我的 webapps,并想评估在嵌入式模式下运行 Tomcat。
Is there a good tutorial or other resource besides what's in the api documentation?
除了api 文档中的内容之外,还有没有好的教程或其他资源?
回答by Antonio
Code speaks for itself. See the pom.xml snippet and the class to run tomcat.
代码不言自明。查看 pom.xml 片段和运行 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;
}
}
回答by Antonio
This might help.
这可能会有所帮助。
If you download the source package for Tomcat6.x, you get this class:
如果你下载Tomcat6.x的源码包,你会得到这个类:
Which is an example of how to use the Embedd class: its a shell to stop|start a specific Tomcat installation. (I mean you can set up CATALINA_BASE
to point at an existing Tomcat installation).
这是如何使用 Embedd 类的示例:它是一个用于停止|启动特定 Tomcat 安装的 shell。(我的意思是您可以设置CATALINA_BASE
为指向现有的 Tomcat 安装)。
If you compile this you can run like this:
如果你编译它,你可以像这样运行:
java -D"catalina.base=%CATALINA_BASE%" -D"catalina.home=%CATALINA_HOME%" org.apache.catalina.startup.Catalina start
java -D"catalina.base=%CATALINA_BASE%" -D"catalina.home=%CATALINA_HOME%" org.apache.catalina.startup.Catalina start
I'm not sure how to alter this code to shutdown the server yet though!
不过,我不确定如何更改此代码以关闭服务器!
回答by Ichiro Furusato
There are a number of reasons why one might use Tomcat over Jetty:
在 Jetty 上使用 Tomcat 的原因有很多:
- One is already familiar with Tomcat
- One is developing web applications that need to be easily transported to a Tomcat installation
- The Jetty developer documentation is actually spottier than Tomcat's (amazing!)
- Getting questions answered in the Jetty community can sometimes take years, as in 2007. see Embedding Jetty
- Important:After Jetty 6.1.*, each web application opens into its own JVM, so if you're trying to gain programmatic access between your standalone access and your web app, your only hope is via a web API.
- If it's an issue for you, Tomcat is an open source project who intellectual property is owned by the Apache Foundation, Jetty is open source but owned by a small private company (Mortbay Consulting)
- 一个已经熟悉Tomcat的
- 一种是开发需要轻松传输到 Tomcat 安装的 Web 应用程序
- Jetty 开发人员文档实际上比 Tomcat 的更复杂(太棒了!)
- 在 Jetty 社区中回答问题有时可能需要数年时间,就像 2007 年一样。请参阅嵌入 Jetty
- 重要提示:在 Jetty 6.1.* 之后,每个 Web 应用程序都会打开自己的 JVM,因此如果您尝试在独立访问和 Web 应用程序之间获得编程访问,您唯一的希望是通过 Web API。
- 如果这对您来说是个问题,Tomcat 是一个开源项目,知识产权归 Apache 基金会所有,Jetty 是开源项目,但归一家小型私人公司所有(Mortbay Consulting)
Point #5 has been important in my work. For example, I can gain direct access to a JSPWiki instance via Tomcat, but it's completely inaccessible when using Jetty. I asked for a solution to that in 2007 and haven't yet heard an answer. So I finally gave up and began using Tomcat 6. I've looked into Glassfish and Grizzly, but so far Tomcat is (amazingly) the most stable and well-documented web container (which isn't saying much really).
第 5 点在我的工作中很重要。例如,我可以通过 Tomcat 直接访问 JSPWiki 实例,但是使用 Jetty 时完全无法访问。我在 2007 年要求解决这个问题,但还没有听到答案。所以我最终放弃并开始使用 Tomcat 6。我已经研究了 Glassfish 和 Grizzly,但到目前为止,Tomcat 是(令人惊讶的)最稳定且文档齐全的 Web 容器(实际上并没有说太多)。
回答by manikanta
Though this post is some what aged, I m answering my own answer as it could save some other' time
虽然这篇文章有些陈旧,但我正在回答我自己的答案,因为它可以节省其他时间
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;
}
}
I also faced the 404
error and struggled some time. By seeing the log 'INFO: No default web.xml
', I suspected it (if that is a warning, would've been easy to spot). The trick being using the web.xml
( rootContext.setDefaultWebXml("web.xml")
)supplied with Tomcat (conf/web.xml
). The reason being, it includes the DefaultServlet, which serves the static files likes HTML, JS. Either use the web.xml
or register the servlet manually in your code.
我也遇到了404
错误并挣扎了一段时间。通过查看日志“ INFO: No default web.xml
”,我怀疑它(如果这是警告,很容易被发现)。正使用招web.xml
(rootContext.setDefaultWebXml("web.xml")
)使用Tomcat提供(conf/web.xml
)。原因是,它包括 DefaultServlet,它为 HTML、JS 等静态文件提供服务。web.xml
在您的代码中手动使用或注册 servlet。
Usage:
用法:
// start the server at http://localhost:8080/myapp
TomcatServer server = new TomcatServer("myapp", 8080, "/src/main/", true);
server.start();
// .....
server.stop();
Do not forget to place the default web.xml
in the same directory of this program or point to the correct location.
不要忘记将默认值web.xml
放在此程序的同一目录中或指向正确的位置。
It should be noted that the shutdown hook is inspired from Antonio's answer.
应该注意的是,关闭钩子的灵感来自安东尼奥的回答。
回答by alexkasko
After reading this thread some months ago, I wrote this project: spring-embedded-tomcat. It can be used to embed tomcat6 into Spring-based applications.
几个月前阅读了这个帖子后,我写了这个项目:spring-embedded-tomcat。它可用于将 tomcat6 嵌入到基于 Spring 的应用程序中。
回答by LinuxLuigi
I think with Tomcat 7 or Jetty 9 embedding is easier. Here you will find a nice introduction: http://www.hascode.com/2013/07/embedding-jetty-or-tomcat-in-your-java-application/
我认为使用 Tomcat 7 或 Jetty 9 嵌入更容易。在这里你会找到一个很好的介绍:http: //www.hascode.com/2013/07/embedding-jetty-or-tomcat-in-your-java-application/