一尘不染

如何获得嵌入式Jetty 9以成功解析JSTL URI?

jsp

我正在打包一个Web应用程序存档(.war),以便可以通过java -jar webapp.war在主类中使用以下代码启动Jetty
9的嵌入式副本来在外壳中启动它:

int port = Integer.parseInt(System.getProperty("port", "80")); // I know this has implications :)
String contextPath = System.getProperty("contextPath", "");
Server server = new Server(port);
ProtectionDomain domain = Deployer.class.getProtectionDomain();
URL location = domain.getCodeSource().getLocation();
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/" + contextPath);
webapp.setWar(location.toExternalForm());
server.setHandler(webapp);
server.start();
server.join();

但是,当第一个包含JSTL taglib声明的JSP被编译时,我遇到了这个错误:

org.apache.jasper.JasperException: /WEB-INF/html/user/login.jsp(2,62) PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:92)
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:378)
at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:172)
at org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:431)
at org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:240)
at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:502)
at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:582)
at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1652)
at org.apache.jasper.compiler.Parser.parse(Parser.java:185)
at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:244)
at org.apache.jasper.compiler.ParserController.parse(ParserController.java:145)
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:212)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:451)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:698)
etc...

该JSP的前几行如下:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" isELIgnored="false" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

我已经看了很多遍(这似乎不是一个新问题),并尝试了以下解决方案:

  • 瘦身我的依赖关系,并寻找冲突(我目前只取决于jetty-serverjetty-webappjetty-jsp所有版本9.0.4.v20130625
  • <taglib>在webapp的web.xml文件中指定一个直接指向JSTL 的显式映射(通过阅读JSP规范就可以了)
  • 根据此答案修改服务器类路径
  • 利用WebAppContext的方法,例如addServerClasssetParentLoaderPriority

根据Jetty的文档,使用JSTL应该可以,但是我认为嵌入式上下文可能会改变JSTL的加载方式并导致失败。

将不胜感激任何想法或建议。此安装程序将替换一个较旧的安装程序,该安装程序在Windows上成功执行了相同的操作,但由于包含了导致此错误的旧依赖性而无法在Linux上运行。不幸的是,我无法找到没有引入上述JSTL
URI堆栈跟踪信息的依赖项(groupId org.mortbay.jettyartifactId
jsp-2.1-glassfish版本2.1.v20100127)的快速替代品。

更新:
我找到了次优的解决方案。现在受此线程启发而降级到Jetty 7
可以正常运行了。这是个好消息,但是令人沮丧的是,如果以后我需要Jetty 8或Jetty 9专有的任何功能,则必须取消此部署基础结构。在Jetty
9中对JSTL taglib问题的任何见解仍将不胜感激。


阅读 248

收藏
2020-06-08

共1个答案

一尘不染

可悲的是,到目前为止,没有答案对我有用。但是我终于找到了解决我问题的方法。这听起来像是一种破解,而且绝对感觉像是一种破解。

但是,如果我按照问题中的描述进行了所有设置,直到JSTL无法解决,我就可以采取使一切正常运行的步骤,几乎就像魔术一样。

造成这种情况的步骤是将.war文件扩展名更改为.jar。一旦这样做,JSTL就可以很好地解析,并且一切正常。

因此,现在我生成一个.war,您可以将其放入servlet容器中,也可以重命名.jar并独立运行。它可以在Unix和Windows上运行,但是由于jsp-2.1-glassfishJames
Cook提到的库中存在一个错误,因此我之前的操作方式在Unix上不起作用。

我pom的相关内容:

<properties>
    <jetty.version>9.0.5.v20130815</jetty.version>
    <war.class>com.domain.package.DeployWebapp</war.class>
    <war.class.path>com/domain/package</war.class.path>
</properties>

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>${jetty.version}</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-webapp</artifactId>
    <version>${jetty.version}</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-jsp</artifactId>
    <version>${jetty.version}</version>
    <scope>provided</scope>
</dependency>

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.7</version>
    <executions>
        <execution>
            <id>main-class-placement</id>
            <phase>prepare-package</phase>
            <configuration>
                <tasks>
                    <move todir="${project.build.directory}/${project.artifactId}-${project.version}/${war.class.path}">
                    <fileset dir="${project.build.directory}/classes/${war.class.path}">
                        <include name="DeployWebapp.class" />
                    </fileset>
                </move>
                        </tasks>
                </configuration>
                <goals>
                    <goal>run</goal>
                </goals>
            </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <id>jetty-classpath</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
                <includeGroupIds>org.eclipse.jetty,javax.servlet,javax.el,org.glassfish.web,org.eclipse.jetty.orbit,org.ow2.asm,javax.annotation</includeGroupIds>
                <outputDirectory>
                    ${project.build.directory}/${project.artifactId}-${project.version}
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <attachClasses>true</attachClasses>
        <archiveClasses>true</archiveClasses>
        <archive>
            <manifest>
                <mainClass>${war.class}</mainClass>
            </manifest>
        </archive>
        <packagingExcludes>META-INF/*.SF</packagingExcludes>
        <packagingExcludes>META-INF/*.DSA</packagingExcludes>
        <packagingExcludes>META-INF/*.RSA</packagingExcludes>
    </configuration>
</plugin>
2020-06-08