2009-03-12 10 views
55

Je suis en train d'exécuter mes webapps sur Tomcat 6 en production, et j'aimerais évaluer Tomcat en mode embarqué.Comment intégrer Tomcat 6?

Existe-t-il un bon didacticiel ou une autre ressource en plus de ce qui se trouve dans le api documentation?

+0

Intégrer la jetée à la place. Cependant, il existe [tomcat-embed] (http://code.google.com/p/tomcat-embed/). – stepancheg

+0

Merci pour le pointeur. Cependant, cela ne semble pas complet, activement développé ou maintenu. Tous les validations sont datées du 11 mai 2008 et l'un des messages du journal l'appelle "loin d'être terminé". –

+0

Worth à regarder dans ce billet de blog: [Embedding Tomcat 7] (http://www.copperykeenclaws.com/embedding-tomcat-7/) –

Répondre

38

Le code parle de lui-même. Voir l'extrait pom.xml et la classe pour exécuter 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

Je ne suis pas capable de faire fonctionner ça, je n'ai que 404s .. Est-ce que je manque quelque chose? – falstro

+0

Avez-vous modifié les attributs catalinaHome, port, classesDir, webappDir en conséquence? – Antonio

2

Cela pourrait aider.

Si vous téléchargez le paquet source pour Tomcat6.x, vous obtenez cette classe:

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

Ce qui est un exemple de la façon d'utiliser la classe embedd: une coquille pour arrêter | démarrer une spécifique Installation de Tomcat. (Je veux dire que vous pouvez configurer CATALINA_BASE pour pointer vers une installation Tomcat existante).

Si vous compilez cela, vous pouvez exécuter comme ceci:

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

Je ne sais pas trop comment modifier ce code pour arrêter le serveur!

10

Il y a un certain nombre de raisons pour lesquelles on peut utiliser Tomcat sur la jetée:

  1. L'un est déjà familier avec Tomcat
  2. One développe des applications web qui doivent être facilement transportés vers une installation Tomcat
  3. La documentation du développeur Jetty est en réalité plus pointue que celle de Tomcat (incroyable!)
  4. Obtenir des réponses aux questions dans la communauté Jetty peut parfois prendre des années, comme en 2007. voir Embedding Jetty
  5. Important: Après Jetty 6.1. *, Chaque application Web s'ouvre sur sa propre machine virtuelle Java. Par conséquent, si vous tentez d'obtenir un accès par programmation entre votre accès autonome et votre application Web, votre seul espoir est via une API Web.
  6. Si c'est un problème pour vous, Tomcat est un projet open source qui propriété intellectuelle appartient à la Fondation Apache, la jetée est open source, mais appartenant à une petite entreprise privée (Mortbay conseil)

point # 5 a été important dans mon travail. Par exemple, je peux obtenir un accès direct à une instance de JSPWiki via Tomcat, mais il est complètement inaccessible lorsque j'utilise Jetty. J'ai demandé une solution à cela en 2007 et je n'ai pas encore entendu de réponse. J'ai donc abandonné et commencé à utiliser Tomcat 6. J'ai regardé Glassfish et Grizzly, mais jusqu'à présent, Tomcat est (étonnamment) le conteneur web le plus stable et le mieux documenté (ce qui ne dit pas grand chose).

+3

"chaque application web s'ouvre dans sa propre machine virtuelle": où avez-vous trouvé cette information? Je doute que ce soit exact. – Bruno

+0

Semble plus comme une chose classloader. Dur à dire. –

+3

Je suis certain que les webapps ne s'ouvrent pas dans leur propre JVM. Ils utilisent des chargeurs de classe séparés par défaut. Pour obtenir le comportement du classloader, utilisez simplement 'webapp.setParentLoaderPriority (true);' - Je pense que cela se trouve dans la documentation de Jetty. –

16

Bien que ce poste est en quelque âge, je suis répondu à ma propre réponse car il pourrait sauver une autre » temps

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; 
    } 

} 

J'ai aussi fait face à l'erreur 404 et eu du mal un certain temps.En voyant le journal 'INFO: No default web.xml', je l'ai suspecté (si c'est un avertissement, aurait été facile à repérer). L'astuce étant l'web.xml(rootContext.setDefaultWebXml("web.xml")) fourni avec Tomcat (conf/web.xml). La raison en est, il comprend le DefaultServlet, qui sert les fichiers statiques aime HTML, JS. Utilisez le web.xml ou enregistrez le servlet manuellement dans votre code.

Utilisation:

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

Ne pas oublier de placer la valeur par défaut web.xml dans le même répertoire de ce programme ou d'un point à l'emplacement correct.

Il convient de noter que le crochet d'arrêt est inspiré de Antonio's answer.

+0

j'ai essayé votre exemple, mon application va, je vois le printemps étant initalized mais quand je tente d'accéder à ma demande , Je reçois des messages d'erreur indiquant qu'aucun mappage n'a été trouvé pour mes jsps. – Thiago

+0

Une mise à jour mineure: Le 'org.apache.catalina.startup.Embedded' est obsolète et il est conseillé d'utiliser' org.apache.catalina.startup.Tomcat' à la place. En effectuant ce changement de nombreuses modifications de chaîne suivront pour rendre le code exécutable. – Athafoud

0

Après avoir lu ce fil il y a, je l'ai écrit quelques mois ce projet: spring-embedded-tomcat. Il peut être utilisé pour intégrer Tomcat6 dans des applications Spring.