2009-03-12 13 views
55

Attualmente sto eseguendo le mie webapp su Tomcat 6 in produzione e vorrei valutare l'esecuzione di Tomcat in modalità incorporata.Come incorporare Tomcat 6?

Esiste un buon tutorial o altra risorsa oltre a ciò che è nello api documentation?

+0

Inserisci invece il molo. Tuttavia, c'è [tomcat-embed] (http://code.google.com/p/tomcat-embed/). – stepancheg

+0

Grazie per il puntatore. Tuttavia, questo non sembra completo, attivamente sviluppato o mantenuto. Tutti i commit sono datati 11 maggio 2008 e uno dei messaggi di registro lo chiama "lontano dal completamento". –

+0

Vale la pena guardare in questo post del blog: [Embedding Tomcat 7] (http://www.copperykeenclaws.com/embedding-tomcat-7/) –

risposta

38

Il codice parla da solo. Vedi lo snippet pom.xml e la classe per eseguire 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; 
    } 

} 
+1

Non riesco a farlo funzionare, ricevo solo 404 .. Mi manca qualcosa? – falstro

+0

Hai modificato gli attributi catalinaHome, port, classesDir, webappDir di conseguenza? – Antonio

2

Questo potrebbe aiutare.

Se si scarica il pacchetto sorgente per Tomcat6.x, si ottiene questa classe:

http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/startup/Catalina.html#main(java.lang.String[])

che è un esempio di come utilizzare la classe embedd: la sua un guscio di fermare | avviare una specifica Installazione di Tomcat. (Voglio dire, puoi impostare CATALINA_BASE per puntare a un'installazione Tomcat esistente).

Se si compila questo è possibile eseguire in questo modo:

java -D "catalina.base =% CATALINA_BASE%" -D "catalina.home =% CATALINA_HOME%" org.apache.catalina.startup.Catalina start

Non sono sicuro di come modificare questo codice per arrestare il server, tuttavia!

10

Ci sono una serie di motivi per cui si potrebbe utilizzare Tomcat sopra Jetty:

  1. Uno è già familiarità con Tomcat
  2. Uno è lo sviluppo di applicazioni web che hanno bisogno di essere facilmente trasportato in un'installazione di Tomcat
  3. La documentazione dello sviluppatore di Jetty è in realtà più spaccio di quella di Tomcat (incredibile!)
  4. Per ottenere risposte alle domande nella comunità di Jetty, a volte possono essere necessari anni, come nel 2007. vedere Embedding Jetty
  5. Importante: Dopo Jetty 6.1. *, Ogni applicazione Web si apre nella sua JVM, quindi se stai cercando di ottenere l'accesso programmatico tra l'accesso indipendente e l'app Web, la tua unica speranza è tramite un'API web.
  6. Se è un problema per voi, Tomcat è un progetto open source che la proprietà intellettuale è di proprietà della Fondazione Apache, Gettata è open source, ma di proprietà di una piccola società privata (Mortbay Consulting)

Point # 5 è stato importante nel mio lavoro Ad esempio, posso ottenere l'accesso diretto a un'istanza di JSPWiki tramite Tomcat, ma è completamente inaccessibile quando si utilizza Jetty. Ho chiesto una soluzione a questo nel 2007 e non ho ancora sentito una risposta. Così alla fine ho rinunciato e ho iniziato a utilizzare Tomcat 6. Ho esaminato Glassfish e Grizzly, ma finora Tomcat è (incredibilmente) il contenitore web più stabile e ben documentato (che non sta dicendo molto).

+3

"ogni applicazione Web si apre nella sua JVM": dove hai ottenuto queste informazioni? Dubito che sia accurato. – Bruno

+0

Sembra più una cosa del classloader. Difficile da dire. –

+3

Sono abbastanza sicuro che le webapp non si aprano nella loro JVM. Usano classloader separati per impostazione predefinita. Per ottenere il comportamento del classloader, basta usare 'webapp.setParentLoaderPriority (true);' - Penso che questo sia nella documentazione di Jetty. –

16

Anche se questo post è un po 'quello invecchiato, io sto rispondendo mia risposta come si potrebbe risparmiare un po' altri' di tempo

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&gt 
*   <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; 
    } 

} 

Ho anche affrontato l'errore 404 e lottato un po' di tempo.Visualizzando il registro "INFO: No default web.xml", sospettavo che fosse (se si tratta di un avviso, sarebbe stato facile individuarlo). Il trucco sta usando lo web.xml(rootContext.setDefaultWebXml("web.xml")) fornito con Tomcat (conf/web.xml). Il motivo è che include il DefaultServlet, che serve i file statici come HTML, JS. Utilizzare lo web.xml o registrare manualmente il servlet nel codice.

Uso:

// start the server at http://localhost:8080/myapp 
TomcatServer server = new TomcatServer("myapp", 8080, "/src/main/", true); 
server.start(); 
// ..... 
server.stop(); 

Non dimenticare di inserire il default web.xml nella stessa directory di questo programma o un punto nella posizione corretta.

Si noti che il gancio di arresto si ispira a Antonio's answer.

+0

Ho provato il tuo esempio, la mia applicazione sale, vedo la primavera essere initalizzata ma quando provo ad accedere alla mia applicazione , Ricevo messaggi di errore di primavera che dicono che non sono stati trovati mapping per i miei jsps. – Thiago

+0

Un aggiornamento minore: "org.apache.catalina.startup.Embedded" è deprecato e si consiglia di utilizzare "org.apache.catalina.startup.Tomcat". Facendo questo cambiamento seguiranno molte modifiche a catena per rendere il codice eseguibile. – Athafoud

0

Dopo aver letto questa discussione alcuni mesi fa, ho scritto questo progetto: spring-embedded-tomcat. Può essere utilizzato per incorporare tomcat6 in applicazioni basate su Spring.