2009-01-31 16 views
14

Estamos utilizando Apache Tomcat 6.0 y Jetty 6 donde trabajo. Utilizamos principalmente Jetty para pruebas (es genial para ejecutar incrustado en pruebas JUnit) y Tomcat para producción.¿Cómo puedo hacer que Tomcat compile previamente las JSP en el inicio?

De forma predeterminada, Tomcat compila JSP sobre la marcha cuando los usuarios lo soliciten. Pero esto resulta en un rendimiento degradado para el primer golpe. También destaca bizarre bugs en el compilador JSP de Tomcat.

El Tomcat documentation da recomendaciones para JSP-compilación en tiempo de compilación pre utilizando Ant (y un plugin Maven también está disponible) ... pero la guerra resultante contiene material Tomcat específico, por ejemplo, PageContextImpl.proprietaryEvaluate, por lo que no podemos usarlo en Jetty.

¿Hay algún indicador o configuración que podamos usar en algún lugar para obligar a Tomcat a precompilar todos los JSP tan pronto como se inicialice WAR? Estamos preparados para esperar un poco más al inicio para esto.

De antemano: Sé que hay una forma de precompilar exactamente una JSP al identificar explícitamente una etiqueta/servlet/cargar-en-inicio en web.xml para una JSP. Pero para docenas o incluso cientos de JSPs que se vuelven inmanejables.

+0

que enlazan a bizzarre bugs es incorrecto. Supongo que el https fue ingresado sin dos puntos, confundiéndolo ... – Stephen

+0

usaría dos compilaciones o dos salidas, una para embarcadero y otra para tomcat, de esa manera no es necesario esperar a que tomcat compile todas las jsps cada vez que reinicie es – tgkprog

+1

Aquí hay un tipo que quería hacer lo mismo que usted: precompilar JSP, Tomcat o Jetty, no Ant. Tal vez [esto] (http://www.j2eegeek.com/blog/2004/05/03/a-different-twist-on-pre-compiling-jsps/) también te ayudará. No lo he probado yo mismo. – duffymo

Respuesta

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 

Este fichero de construcción encontrará todos los archivos JSP de su webapp, compilarlos en clases de servlet, y generar mapeos de servlets para esas clases de servlets JSP. Los pings de mapa de servlet que genera deben ir al archivo WEB-INF/web.xml de su webapp, pero sería difícil escribir un archivo de compilación Ant que sepa cómo insertar las asignaciones de servlets en su archivo web.xml de forma repetible cada vez que se ejecuta el archivo de compilación. En su lugar, utilizamos una entidad XML para que las asignaciones de servlets generadas vayan a un nuevo archivo cada vez que se ejecute el archivo de compilación y ese archivo de asignaciones de servlets pueda insertarse en su archivo web.xml mediante el mecanismo de inclusión de entidad XML. Para usarlo, WEB- INF/web.xml de su webapp debe tener una declaración de entidad especial en la parte superior del archivo, además de una referencia a la entidad en el contenido del archivo web.xml donde desea que el archivo de asignaciones de servlets incluido. Así es como un archivo web.xml vacío servlet 2.5 de webapp mira con estas modificaciones:

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

Asegúrese de que el archivo web.xml del módulo web tiene la línea DTD (la etiqueta DOCTYPE) todo el camino en la parte superior del archivo y la declaración del esquema de la aplicación web Servlet 2.5 debajo de eso. Luego, donde sea que quiera insertar las asignaciones de servlet generadas en su archivo web.xml, ingrese la referencia de entidad & jspc-webxml; . Recuerde, la referencia de la entidad comienza con un signo de unión (&), luego tiene el nombre de la entidad y finaliza con un punto y coma (;).

Para utilizar el archivo de creación, simplemente editarlo y establecer todas las propiedades en la parte superior de los valores que responden a su configuración, y luego ejecutarlo así:

$ ant -f pre-compilación JSP. xml

1

Si vas con la solución mencionada por duffymo apuntando al blog de Vinny Carpenter, tengo un consejo. Hubo un área que causó que mi contenedor se cuelgue indefinidamente al contactar al servidor local (específicamente en el método privado connect()). El uso de este truco fue mi solución:

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

Configuración de un tiempo de espera e ignorando el SocketTimeoutException funcionaba (aunque es cierto que no es la mejor solución).Además, el uso de este procedimiento significa que deberá especificar los JSP en web.xml. Esto fue suficiente para mis necesidades.

Cuestiones relacionadas