2009-01-31 8 views
14

Nous utilisons à la fois Apache Tomcat 6.0 et Jetty 6 là où je travaille. Nous utilisons principalement Jetty pour les tests (c'est génial pour l'exécution intégrée dans les tests JUnit) et Tomcat pour la production. Par défaut, Tomcat compile les JSP à la volée au fur et à mesure que les utilisateurs les demandent. Mais cela entraîne des performances dégradées pour le premier hit. Il met également en évidence bizarre bugs dans le compilateur JSP de Tomcat.Comment puis-je créer des JSP de pré-compilation Tomcat au démarrage?

Le Tomcat documentation donne des recommandations pour précompiler les JSP au moment de la construction en utilisant Ant (et un plugin Maven est également disponible) ... mais le WAR résultant contient des éléments spécifiques à Tomcat, par ex. PageContextImpl.proprietaryEvaluate, donc nous ne pouvons pas l'utiliser dans Jetty.

Existe-t-il un indicateur ou un paramètre que nous pouvons utiliser quelque part pour forcer Tomcat à précompiler toutes les pages JSP dès que le fichier WAR est initialisé? Nous sommes prêts à attendre un peu plus longtemps au démarrage pour cela.

En avance: Je sais qu'il existe un moyen de pré-compiler exactement un JSP en identifiant explicitement une balise/servlet/load-on-startup dans web.xml pour une JSP. Mais pour des dizaines ou même des centaines de JSP qui deviennent ingérables.

+0

ce lien vers bugs bizzarre est faux. Je suppose que le https a été entré sans deux-points, le confondant ... – Stephen

+0

J'utiliserais deux builds ou deux sorties - une pour jetty et une pour tomcat, de cette façon, pas besoin d'attendre que tomcat compile toutes les jsps à chaque redémarrage – tgkprog

+1

Voici un gars qui voulait faire la même chose que vous: précompiler les JSP, Tomcat ou Jetty, sans Ant. Peut-être que [this] (http://www.j2eegeek.com/blog/2004/05/03/a-different-twist-on-pre-compiling-jsps/) vous aidera aussi. Je n'ai pas essayé moi-même. – duffymo

Répondre

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 

Ce fichier de construction trouverez tous les fichiers de votre webapp JSP, les compiler dans des classes de servlet, et générer des correspondances de servlet pour les classes de servlet JSP. Les pings de carte de servlet qu'il génère doivent aller dans le fichier WEB-INF/web.xml de votre webapp, mais il serait difficile d'écrire un fichier de construction Ant qui sait comment insérer les mappages de servlet dans votre fichier web.xml de façon reproductible tous les heure à laquelle le fichier de construction est exécuté. Au lieu de cela, nous avons utilisé une entité XML incluse afin que les mappages de servlet générés soient placés dans un nouveau fichier chaque fois que le fichier de construction s'exécute et que ce fichier de mappages de servlet puisse être inséré dans votre fichier web.xml. Pour l'utiliser, WEB-INF/web.xml de votre webapp doit avoir une déclaration d'entité spéciale en haut du fichier, plus une référence à l'entité dans le contenu du fichier web.xml où vous voulez que le fichier de mappages de servlet soit inclus. Voici comment un servlet vide 2,5 fichier web.xml de webapp regarde avec ces modifications:

<!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> 

Assurez-vous que le fichier web.xml de votre webapp a la DTD en ligne (la balise DOCTYPE) tout le chemin en haut du fichier et la déclaration du schéma de l'application web de servlet 2.5 ci-dessous. Ensuite, où vous voulez insérer les mappages de servlet générés dans votre fichier web.xml, placez la référence d'entité & jspc-webxml; . Rappelez-vous que la référence d'entité commence par une perluète (&), a ensuite le nom de l'entité et se termine par un point-virgule (;).

Pour utiliser le fichier de construction, il suffit d'éditer et définir toutes les propriétés en haut des valeurs qui correspondent à votre configuration, puis l'exécuter comme ceci:

ant $ -f Précompilation-jsps. xml

1

Si vous allez avec la solution mentionnée par duffymo pointant vers le blog de Vinny Carpenter, j'ai un conseil. Une zone a provoqué le blocage indéfini de mon conteneur lors de la connexion de localhost (en particulier dans la méthode privée connect()). En utilisant le hack était ma solution de contournement:

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

Définition d'un délai d'attente et en ignorant le SocketTimeoutException travaillé (mais certes pas la meilleure solution).En outre, l'utilisation de cette procédure signifie que vous devez spécifier les pages JSP dans le fichier web.xml. C'était suffisant pour mes besoins.