2009-01-31 10 views
14

Utilizziamo sia Apache Tomcat 6.0 che Jetty 6 dove lavoro. Utilizziamo principalmente Jetty per i test (è fantastico per l'esecuzione integrata nei test JUnit) e Tomcat per la produzione.Come posso rendere Tomcat precompilato JSP all'avvio?

Per impostazione predefinita, Tomcat compila JSP al volo mentre gli utenti li richiedono. Ma questo si traduce in prestazioni degradate per il primo colpo. Evidenzia anche bizarre bugs nel compilatore JSP di Tomcat.

Tomcat documentation fornisce suggerimenti per la precompilazione di JSP in fase di compilazione utilizzando Ant (e un plug-in Maven è anche disponibile) ... ma la WAR risultante contiene roba specifica per Tomcat, ad es. PageContextImpl.proprietaryEvaluate, quindi non possiamo usarlo in Jetty.

C'è qualche flag o impostazione che possiamo usare da qualche parte per forzare Tomcat a precompilare tutti i JSP non appena inizializzato il WAR? Siamo pronti ad aspettare un po 'di più all'avvio per questo.

In anticipo: so che c'è un modo per pre-compilare esattamente uno JSP identificando in modo esplicito un tag/servlet/load-on-startup in web.xml per un JSP. Ma per dozzine o anche centinaia di JSP diventa ingestibile.

+0

che il collegamento a bug bizzarre è sbagliato. Presumo che l'https sia stato inserito senza due punti, confondendolo ... – Stephen

+0

userei due build o due output, uno per il molo e uno per il tomcat, in questo modo non è necessario attendere che tomcat compili tutti i jsp ogni volta che si riavvia it – tgkprog

+1

Ecco un ragazzo che voleva fare la stessa cosa di te: precompilare JSP, Tomcat o Jetty, senza Ant. Forse [questo] (http://www.j2eegeek.com/blog/2004/05/03/a-different-twist-on-pre-compiling-jsps/) ti aiuterà anche tu. Non l'ho provato da solo. – duffymo

risposta

4

http://www.devshed.com/c/a/BrainDump/Tomcat-Capacity-Planning/


project name="pre-compile-jsps" default="compile-jsp-servlets"> 

    <!-- Private properties. -- > 
    <property name="webapp.dir" value="${basedir}/webapp-dir"/> 
    <property name="tomcat.home" value="/opt/tomcat"/> 
    <property name="jspc.pkg.prefix" value="com.mycompany"/> 
    <property name="jspc.dir.prefix" value="com/mycompany"/> 

    <!-- Compilation properties. --> 
    <property name="debug" value="on"/> 
    <property name="debuglevel" value="lines,vars,source"/> 
    <property name="deprecation" value="on"/> 
    <property name="encoding" value="ISO-8859-1"/> 
    <property name="optimize" value="off"/> 
    <property name="build.compiler" value="modern"/> 
    <property name="source.version" value="1.5"/> 

    <!-- Initialize Paths. --> 
    <path id="jspc.classpath"> 
    <fileset dir="${tomcat.home}/bin"> 
     <include name="*.jar"/> 
    </fileset> 
    <fileset dir="${tomcat.home}/server/lib"> 
     <include name="*.jar"/> 
    </fileset> 
    <fileset dir="${tomcat.home}/common/i18n"> 
     <include name="*.jar"/> 
    </fileset> 
    <fileset dir="${tomcat.home}/common/lib"> 
     <include name="*.jar"/> 
    </fileset> 
    <fileset dir="${webapp.dir}/WEB-INF"> 
     <include name="lib/*.jar"/> 
    </fileset> 
    <pathelement location="${webapp.dir}/WEB-INF/classes"/> 
    <pathelement location="${ant.home}/lib/ant.jar"/> 
    <pathelement location="${java.home}/../lib/tools.jar"/> 
    </path> 
    <property name="jspc.classpath" refid="jspc.classpath"/> 

    <!--========================================================== --> 
    <!-- Generates Java source and a web.xml file from JSP files.      --> 
    <!-- ========================================================== 
--> 
    <target name="generate-jsp-java-src"> 
    <mkdir dir="${webapp.dir}/WEB-INF/jspc-src/${jspc.dir.prefix}"/> 
    <taskdef classname="org.apache.jasper.JspC" name="jasper2"> 
     <classpath> 
     <path refid="jspc.classpath"/> 
     </classpath> 
    </taskdef> 
    <touch file="${webapp.dir}/WEB-INF/jspc-web.xml"/> 
    <jasper2 uriroot="${webapp.dir}" 
      package="${jspc.pkg.prefix}" 
      webXmlFragment="${webapp.dir}/WEB-INF/jspc-web.xml" 
      outputDir="${webapp.dir}/WEB-INF/jspc-src/${jspc.dir.prefix}" 
      verbose="1"/> 
    </target> 

    <!-- ========================================================== --> 
    <!-- Compiles (generates Java class files from) the JSP servlet --> 
    <!-- source code that was generated by the JspC task.   --> 
    <!-- ========================================================== --> 
    <target name="compile-jsp-servlets" depends="generate-jsp-java-src"> 
    <mkdir dir="${webapp.dir}/WEB-INF/classes"/> 
    <javac srcdir="${webapp.dir}/WEB-INF/jspc-src" 
      destdir="${webapp.dir}/WEB-INF/classes" 
      includes="**/*.java" 
      debug="${debug}" 
      debuglevel="${debuglevel}" 
      deprecation="${deprecation}" 
      encoding="${encoding}" 
      optimize="${optimize}" 
      source="${source.version}"> 
     <classpath> 
     <path refid="jspc.classpath"/> 
     </classpath> 
    </javac> 
    </target> 

    <!-- ========================================================= --> 
    <!-- Cleans any pre-compiled JSP source, classes, jspc-web.xml --> 
    <!-- ========================================================= --> 
    <target name="clean"> 
    <delete dir="${webapp.dir}/WEB-INF/jspc-src"/> 
    <delete dir="${webapp.dir}/WEB-INF/classes/${jspc.dir.prefix}"/> 
    <delete file="${webapp.dir}/WEB-INF/jspc-web.xml"/> 
    </target> 

</project 

Questa build file, troverete tutti i file JSP del vostro webapp, compilarli in classi delle servlet, e generare mappature servlet per quelle classi servlet JSP. I ping di servlet map che genera devono andare nel file WEB-INF/web.xml del tuo webapp, ma sarebbe difficile scrivere un file di build Ant che sappia come inserire i mapping dei servlet nel tuo file web.xml in modo ripetibile ogni tempo di esecuzione del file di build. Invece, abbiamo utilizzato un'entità XML in modo che i mapping dei servlet generati entrino in un nuovo file ogni volta che viene eseguito il file di build e che il file di mappatura servlet possa essere inserito nel file web.xml tramite il meccanismo di inclusione dell'entità XML. Per utilizzarlo, WEB-INF/web.xml del tuo webapp deve avere una dichiarazione di entità speciale nella parte superiore del file, oltre a un riferimento all'entità nel contenuto del file web.xml in cui desideri che il file di mappatura servlet sia incluso. Ecco come file web.xml un vuoto servlet 2.5 di webapp guarda con queste modifiche:

<!DOCTYPE jspc-webxml [ 
    <!ENTITY jspc-webxml SYSTEM "jspc-web.xml"> 
    ]> 

    <web-app xmlns=http://java.sun.com/xml/ns/javaee 
     xmlns:xsi=http://www.w3.org/2001/ XMLSchema-instance 
     xsi:schemaLocation="http:// java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/ 
    javaee/web-app_2_5.xsd" 
     version="2.5"> 

    <!-- We include the JspC-generated mappings here. --> 
    &jspc-webxml; 

    <!-- Non-generated web.xml content goes here. --> 

    </web-app> 

Assicurarsi file web.xml del vostro webapp ha la linea DTD (il tag DOCTYPE) fino alla parte superiore del file e la dichiarazione dello schema web-app di servlet 2.5 di seguito. Quindi, ovunque si desideri inserire i mapping servlet generati nel file web.xml, inserire il riferimento entità & jspc-webxml; . Ricorda che il riferimento all'entità inizia con una e commerciale (&), quindi ha il nome dell'entità e termina con un punto e virgola (;).

Per utilizzare il file di configurazione, solo modificarlo e impostare tutte le proprietà in cima ai valori che corrispondono alla vostra configurazione, e quindi eseguirlo in questo modo:

$ ant -f pre-compilazione JSP. xml

1

Se si va con la soluzione menzionata da duffymo che indica il blog di Vinny Carpenter, ho un consiglio. C'è stata un'area che ha causato il blocco del mio contenitore per un tempo indefinito mentre contattavo localhost (in particolare nel metodo private connect()). Utilizzando il seguente trucco è stata la mia soluzione:

private void connect(final String urlString) { 

     HttpURLConnection conn; 
     try { 
      final URL url = new URL(urlString); 
      conn = (HttpURLConnection)url.openConnection(); 
      conn.setConnectTimeout(5000); 
      //time it out quickly - otherwise hangs forever 
      //seems to be an issue hitting localhost 
      //will still precompile the page 
      conn.setReadTimeout(100); 
      conn.setAllowUserInteraction(true); 
      conn.getInputStream(); 
      conn.disconnect(); 
     } 
     catch (SocketTimeoutException e) { 
      log.debug(e); 
     } 
     catch (IOException ioe) { 
      log.error(ioe); 
     } 
    } 

L'impostazione di un timeout e ignorando il SocketTimeoutException lavorato (anche se certamente non è la soluzione migliore).Inoltre, l'utilizzo di questa procedura significa che è necessario specificare i JSP in web.xml. Questo era sufficiente per i miei bisogni.

Problemi correlati