2010-09-18 9 views
5

Ich habe eine Web-Anwendung mit Tomcat 6 geschrieben und ich versuche, es mit Tomcat 7 arbeiten zu lassen. Während seines Starts registriert die Anwendung unter anderem seine Web-Service-Komponente bei irgendein entferntes Verzeichnis. Dazu muss es eine eigene URL angeben. Die folgende (ein wenig naiv) Methode sollte WebService URL zurück:Erhalten volle Servlet URL während des Starts unter Tomcat 7

import org.apache.catalina.ServerFactory; 
import org.apache.catalina.connector.Connector; 
. 
. 
. 
private String getWsUrl(ServletContext context) 
      throws UnknownHostException, MalformedURLException { 
    String host = java.net.InetAddress.getLocalHost().getCanonicalHostName(); 
    int port = -1; 
    for (Connector c : ServerFactory.getServer().findServices()[0].findConnectors()) { 
     if (c.getProtocol().contains("HTTP")) { 
      port = c.getPort(); 
      break; 
     } 
    } 
    URL wsURL = new URL("http", host, port, context.getContextPath() 
       + C.WEB_SERVICE_PATH /* this is just a constant string */); 
    return wsURL.toString(); 
} 

Der ServerFactory.getServer() Teil problematisch sein wird sich herausstellte: Es gibt keine org.apache.catalina.ServerFactory Klasse in Tomcat 7. Vorschläge, wie dies zu umschreiben für Tomcat 7 ? Ich wäre auch glücklich, mehr tragbaren, nicht tomcat-spezifischen Code zu haben.

Antwort

0

Ich habe es noch nie verwendet, und es gibt wahrscheinlich keine URL mit dem Hostnamen und der Adresse, aber gibt es eine Chance ServletContext.getResource("/") wird tun, was Sie wollen? Ich weiß, dass es für den internen Zugriff auf eine Ressource durch das Servlet gedacht ist, aber Sie wissen es nie.

+0

Es gibt ein ** Plattendateisystem ** basierend 'URL' an die Wurzel des öffentlichen webcontent verweist. Also nein, das tut absolut nicht was der OP will :) – BalusC

+0

Okay. Die API-Dokumente geben nicht an, welche Art von URL zurückgegeben wird, und ich hatte keine Zeit, sie zu testen. Danke, dass du das überprüft hast. –

3

Ich hatte das gleiche Problem: Ich musste die Portnummer kennen, um eine URL für eine bestimmte Tomcat-Instanz zu erstellen, die Portnummer kann variieren (weil ich mehrere Instanzen zum Testen ausführe), und seit Tomcat 7 ist ServerFactory weg Weg.

Ich schrieb den folgenden Code zum Suchen und Parsen der Tomcat server.xml-Datei. Es analysiert nicht viel, nur die HTTP "Port" und "RedirectPort" -Werte erhalten. Dies hängt von den Systemeigenschaften "catalina.home" oder "catalina.base" ab, die in jeder laufenden Tomcat-Instanz vorhanden sein sollten. Das Schöne ist, dass es nicht von Tomcat-Klassen abhängig ist und den XML-Parser der JVM verwendet.

Ich hoffe, das hilft.

public final class TomcatConfigUtil { 

private static final String CONFIG_FILE_PATH = "conf/server.xml"; 

private static Map<String, String> properties = null; 

// No instances, please. 
private TomcatConfigUtil() { } 


/** 
* Get the configuration as a map of name/value pairs, or throw an exception if it wasn't found. 
* All values are returned as Strings. 
* <ul> 
* <li> httpPort - the HTTP port</li> 
* <li> httpRedirectPort - the HTTP redirect port (which seems to be the SSL port) </li> 
* </ul> 
* @exception FileNotFoundException if the configuration file wasn't found 
* @exception IOException if there was a problem reading the configuration file 
* @exception SAXException if there was a problem parsing the configuration file 
*/ 
public static synchronized Map<String, String> getConfig() throws FileNotFoundException, IOException, SAXException { 

    if (properties != null) { 

     return properties; 
    } 

    final File serverConfigFile = findServerConfigFile(); 
    if (serverConfigFile == null) { 

     throw new FileNotFoundException("Couldn't find the configuration file."); 
    } 

    final Map<String, String> tmpProperties = new HashMap<String, String>(); 

    // Content-handler does the actual parsing. 
    final ServerConfigContentHandler contentHandler = new ServerConfigContentHandler(tmpProperties); 
    final XMLReader xmlReader = XMLReaderFactory.createXMLReader(); 
    xmlReader.setContentHandler(contentHandler); 

    // Pass the config file as the input source for parsing. 
    final FileReader fileReader = new FileReader(serverConfigFile); 
    xmlReader.parse(new InputSource(fileReader)); 
    fileReader.close(); 

    return (properties = Collections.unmodifiableMap(tmpProperties)); 
} 


private static File findServerConfigFile() { 

    if (System.getProperty("catalina.home") != null) { 

     final File file = new File(System.getProperty("catalina.home"), CONFIG_FILE_PATH); 
     if (file.isFile()) { 

      return file; 
     } 
    } 

    if (System.getProperty("catalina.base") != null) { 

     final File file = new File(System.getProperty("catalina.base"), CONFIG_FILE_PATH); 
     if (file.isFile()) { 

      return file; 
     } 
    } 

    return null; 
} 


/** 
* ContentHandler implementation for the XML parser. 
*/ 
private static class ServerConfigContentHandler implements ContentHandler { 

    private final Map<String, String> map; 
    private boolean inServerElement; 
    private boolean inCatalinaServiceElement; 


    private ServerConfigContentHandler(final Map<String, String> map) { 

     this.map = map; 
    } 

    @Override 
    public void startDocument() throws SAXException { 

     this.inServerElement = false; 
     this.inCatalinaServiceElement = false; 
    } 

    @Override 
    public void startElement(final String uri, final String localName, final String qName, final Attributes atts) throws SAXException { 

     if (!this.inServerElement && "Server".equals(localName)) { 

      this.inServerElement = true; 
     } 
     else if (this.inServerElement && "Service".equals(localName) && "Catalina".equals(atts.getValue("name"))) { 

      this.inCatalinaServiceElement = true; 
     } 
     else if (this.inCatalinaServiceElement && "Connector".equals(localName) && "HTTP/1.1".equals(atts.getValue("protocol"))) { 

      if ((atts.getValue("SSLEnabled") == null || "false".equals(atts.getValue("SSLEnabled"))) && 
        (atts.getValue("secure") == null || "false".equals(atts.getValue("secure"))) && 
        (atts.getValue("scheme") == null || "http".equals(atts.getValue("scheme")))) { 

         final String portStr = atts.getValue("port"); 
         if (portStr != null) { 

          this.map.put("httpPort", portStr); 
         } 
         final String redirectPortStr = atts.getValue("redirectPort"); 
         if (redirectPortStr != null) { 

          this.map.put("httpRedirectPort", redirectPortStr); 
         } 
        } 
     } 
    } 

    @Override 
    public void endElement(final String uri, final String localName, final String qName) throws SAXException { 

     if (this.inCatalinaServiceElement && "Service".equals(localName)) { 

      this.inCatalinaServiceElement = false; 
     } 
     else if (this.inServerElement && "Server".equals(localName)) { 

      this.inServerElement = false; 
     } 
    } 

    @Override 
    public void endDocument() throws SAXException { 

     this.inServerElement = false; 
     this.inCatalinaServiceElement = false; 
    } 

    @Override 
    public void characters(final char[] ch, final int start, final int length) throws SAXException { } 

    @Override 
    public void endPrefixMapping(final String prefix) throws SAXException { } 

    @Override 
    public void ignorableWhitespace(final char[] ch, final int start, final int length) throws SAXException { } 

    @Override 
    public void processingInstruction(final String target, final String data) throws SAXException { } 

    @Override 
    public void setDocumentLocator(final Locator locator) { } 

    @Override 
    public void skippedEntity(final String name) throws SAXException { } 

    @Override 
    public void startPrefixMapping(final String prefix, final String uri) throws SAXException { } 
} 

}

+0

Interessanter Ansatz, obwohl für den Produktionscode zu schmutzig. +1 für Originalität. –

+0

Es funktioniert, jedoch bindet es die Verwendung mit Tomcat 7. Zusätzlich, nicht für diese Antwort aber für den ursprünglichen Beitrag, ist die .getLocalhost() Leistung in einigen System sehr schlecht, wahrscheinlich aufgrund IP6 von Java 1.4.1 zu suchen. Ich frage mich, ob wir eine Dump-Anfrage an Servlet selbst nach dem Start machen könnte, um notwendige Informationen über HttpRequest zu erhalten. – lent