64 votes

Puis-je servir des JSP depuis un JAR dans lib, ou existe-t-il une solution de contournement?

J'ai une application web déployée comme un fichier WAR dans Tomcat 7. L'application est construite comme un multi-projet de module:

  • core - emballés que le POT, contient la plupart du backend code
  • core-api - emballés que le POT, contient des interfaces vers la base
  • webapp - emballés que la GUERRE, contient frontend code et dépend de base
  • client-extensions - module optionnel, emballé comme JAR

Normalement, nous pouvons mettre nos fichiers JSP dans la webapp projet et de référence par rapport au contexte:

/WEB-INF/jsp/someMagicalPage.jsp

La question est de savoir ce que nous faisons à propos des fichiers JSP qui sont spécifiques au client,-les extensions de projet, qui ne doit pas toujours être inclus dans la GUERRE. Malheureusement, je ne peut pas se référer aux pages Jsp à l'intérieur des fichiers JAR, il semble. Tentant classpath:jsp/customerMagicalPage.jsp les résultats dans un fichier n'est pas trouvé dans le JspServlet, car il utilise ServletContext.getResource().

Traditionnellement, nous avons un problème "résolu" ce avoir maven décompresser le client de l'extension JAR, recherchez les Jsp, et les mettre dans la GUERRE lors de sa construction. Mais la situation idéale est celle où vous déposez simplement un POT dans le explosé WAR dans Tomcat et l'extension est découvert - qui fonctionne pour tout, mais les pages Jsp.

Est-il de toute façon à résoudre ce problème? Une façon standard, un Tomcat de manière spécifique, un hack, ou une solution de contournement? Par exemple, j'ai eu la pensée de le déballage de la JSPs de démarrage de l'application...

72voto

scarba05 Points 1624

Servlet 3.0, ce qui Tomcat 7 prend en charge inclut la possibilité de regrouper les jsp dans un bocal.

Vous avez besoin de:

  • placez votre jsp en META-INF/resources répertoire de votre pot
  • éventuellement inclure un web-fragment.xml dans la META-INF répertoire de votre pot
  • placez le pot dans WEB-INF/lib répertoire de votre guerre

Vous devriez alors être en mesure de référencer vos pages jsp dans votre contexte. Par exemple, si vous avez une jsp META-INF/resources/test.jsp vous devriez être en mesure de faire référence à ce qui est à la racine de votre contexte en tant que test.jsp

6voto

waxwing Points 10190

Comme solution, j'ai créé une classe qui ouvre un fichier jar, trouve des fichiers correspondant à un certain modèle, et des extraits de ces fichiers en un lieu donné par rapport au chemin de contexte.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;

import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.ServletContextAware;

/**
 * Allows extraction of contents of a JAR file. All files matching a given Ant path pattern will be extracted into a
 * specified path.
 */
public class JarFileResourcesExtractor implements ServletContextAware {

    private String resourcePathPattern;
    private String jarFile;
    private String destination;
    private ServletContext servletContext;
    private AntPathMatcher pathMatcher = new AntPathMatcher();

    /**
     * Creates a new instance of the JarFileResourcesExtractor
     * 
     * @param resourcePathPattern
     *            The Ant style path pattern (supports wildcards) of the resources files to extract
     * @param jarFile
     *            The jar file (located inside WEB-INF/lib) to search for resources
     * @param destination
     *            Target folder of the extracted resources. Relative to the context.
     */
    private JarFileResourcesExtractor(String resourcePathPattern, String jarFile, String destination) {
        this.resourcePathPattern = resourcePathPattern;
        this.jarFile = jarFile;
        this.destination = destination;
    }

    /** 
     * Extracts the resource files found in the specified jar file into the destination path
     * 
     * @throws IOException
     *             If an IO error occurs when reading the jar file
     * @throws FileNotFoundException
     *             If the jar file cannot be found
     */
    @PostConstruct
    public void extractFiles() throws IOException {
        try {
            String path = servletContext.getRealPath("/WEB-INF/lib/" + jarFile);
            JarFile jarFile = new JarFile(path);

            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (pathMatcher.match(resourcePathPattern, entry.getName())) {
                    String fileName = entry.getName().replaceFirst(".*\\/", "");
                    File destinationFolder = new File(servletContext.getRealPath(destination));
                    InputStream inputStream = jarFile.getInputStream(entry);
                    File materializedJsp = new File(destinationFolder, fileName);
                    FileOutputStream outputStream = new FileOutputStream(materializedJsp);
                    copyAndClose(inputStream, outputStream);
                }
            }

        }
        catch (MalformedURLException e) {
            throw new FileNotFoundException("Cannot find jar file in libs: " + jarFile);
        }
        catch (IOException e) {
            throw new IOException("IOException while moving resources.", e);
        }
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    public static int IO_BUFFER_SIZE = 8192;

    private static void copyAndClose(InputStream in, OutputStream out) throws IOException {
        try {
            byte[] b = new byte[IO_BUFFER_SIZE];
            int read;
            while ((read = in.read(b)) != -1) {
                out.write(b, 0, read);
            }
        } finally {
            in.close();
            out.close();
        }
    }
}

Puis-je le configurer comme un haricot dans mon Printemps XML:

<bean id="jspSupport" class="se.waxwing.util.JarFileResourcesExtractor">
   <constructor-arg index="0" value="jsp/*.jsp"/>
   <constructor-arg index="1" value="myJarFile-1.1.0.jar"/>
   <constructor-arg index="2" value="WEB-INF/classes/jsp"/>
</bean>

Ce n'est pas une solution optimale à un problème gênant. La question devient maintenant, le gars qui tient ce code et le meurtre de moi pendant que je dors pour ce faire?

4voto

Paul Lysak Points 336

Il existe une telle solution de contournement: vous pouvez précompiler vos fichiers JSP en servlets. Vous obtiendrez ainsi des fichiers .class que vous pourrez mettre dans le fichier JAR et mapper le fichier web.xml vers certaines URL.

4voto

apetrelli Points 348

L'équipe Struts 2 a ajouté un plugin pour JSP intégré. Peut-être qu'il peut être utilisé comme base.

http://struts.apache.org/2.x/docs/embedded-jsp-plugin.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X