我正在打包Web应用程序存档(.war),以便通过在主类中使用此代码启动Jetty 9的嵌入副本,在shell中通过 java -jar webapp.war
启动它:
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-server
,jetty-webapp
和jetty-jsp
,所有版本9.0.4.v20130625
) -
在webapp的web.xml文件中指定一个直接指向JSTL的显式
<taglib>
映射(通过阅读JSP规范获得此想法) -
根据this answer修改服务器类路径
-
利用WebAppContext的方法,例如
addServerClass
和setParentLoaderPriority
根据Jetty's documentation,使用JSTL应该可行,但我认为嵌入式上下文可能正在改变JSTL加载的方式并导致它失败 .
将不胜感激任何想法或建议 . 此设置将替换在Windows上成功执行相同操作但在Linux上无法运行的旧设置,因为包含了引入this bug的旧依赖项 . 不幸的是,我还没有找到一个快速替换该依赖项(groupId org.mortbay.jetty
artifactId jsp-2.1-glassfish
version 2.1.v20100127
),它没有引入上面提到的JSTL URI堆栈跟踪 .
UPDATE: 我发现了一个次优的解决方案 . 由this thread启发的降级到Jetty 7现在已经启动并运行 . 这是个好消息,但它必须废弃这个部署基础架构 . 任何关于Jetty 9中JSTL taglib问题的见解仍然会受到赞赏 .
8 回答
所以这是另一个解决方案 . 我正在努力解决非常类似的问题只有我有一个单独的war文件和一个简单的嵌入类,它为我创建一个Jetty服务器并启动它指向可能的任何war文件 . 以下是这一切的工作原理 .
war文件在
WEB-INF/lib
中没有任何tld库,并且与加载器miniapplication完全分开 .Loader应用程序启动服务器并将其指向任何war文件的主类具有以下依赖项(maven):
lib
EmbeddedApp.jar < - 使用embedder类的JAR
com.sun.el-2.2.0.v201303151357.jar
javax.el-2.2.0.v201303151357.jar
javax.servlet-3.0.0.v201112011016.jar
javax.servlet.jsp-2.2.0.v201112011158.jar
javax.servlet.jsp.jstl-1.2.0.v201105211821.jar
jetty-http-9.0.6.v20130930.jar
jetty-io-9.0.6.v20130930.jar
jetty-jsp-9.0.6.v20130930.jar
jetty-security-9.0.6.v20130930.jar
jetty-server-9.0.6.v20130930.jar
jetty-servlet-9.0.6.v20130930.jar
jetty-util-9.0.6.v20130930.jar
jetty-webapp-9.0.6.v20130930.jar
jetty-xml-9.0.6.v20130930.jar
org.apache.jasper.glassfish-2.2.2.v201112011158.jar
org.apache.taglibs.standard.glassfish-1.2.0.v201112081803.jar
org.eclipse.jdt.core-3.8.2.v20130121.jar
我的dependecies只是通过程序集插件添加的
I used a manifest with classpath embedded within the jar and setting my CLASSPATH=<PATH_TO_APP>\lib\EmbeddedApp.jar assuming the reset of the dependencies are part of my classpath through the manifest. 我遇到了同样无法解决的URI错误 .
一旦我添加了更改我的脚本中的
CLASSPATH
变量以明确包含所有 jar 它开始工作 .希望这可以节省一些时间:-)
我从Surefire测试中启动Jetty时遇到了同样的问题;问题是Jetty 9没有查看任何jar文件的清单,除了在WEB-INF中,这与我编写测试的方式不兼容 .
为了解决这个问题,我编写了一些代码来从清单中找到jar文件,并将它们放入一个新的中间URLClassLoader中 .
这就是我的功能测试设置功能最终看起来是为了让它与Jetty 9一起工作:
我的代码示例放在公共域中 - 您可以在自己的代码中使用它(归属归属但不是必需的) .
在使用a1kmm的解决方案摆弄并最终使用NullPointers后,我注意到了我没有在WebAppContext上设置类加载器 . 使用以下行我不再需要自定义类加载/清单扫描设置 .
我遇到了这个问题 . 我以最不寻常的方式解决了这个问题 .
我使用Maven作为构建工具,但这是我如何构建自我执行WAR .
但就像你自己一样,我得到了那个错误 . 谷歌搜索了2天后的死亡,我发现了这个 - http://internna.blogspot.co.uk/2011/08/step-by-step-executable-war-files.html
通过为这一个切换jetty-jsp依赖:
这一切都开始神奇地工作!
到目前为止,我无法解释它为什么会起作用 . 但我很想知道
我刚刚使用ta taglib创建了简单的jsp . 然后创建服务器应用程序,它工作 . 所以,我认为它不是导致问题的taglib .
可悲的是,到目前为止,没有一个答案对我有用 . 但我终于找到了解决问题的方法 . 这听起来像一个黑客,它肯定感觉像一个 .
但是,如果我按照我在问题中描述的那样设置所有内容,直到JSTL无法解决,我可以采取一个步骤,使一切正常,就像魔术一样 .
引起畏缩的步骤是将
.war
文件的扩展名更改为.jar
. 一旦我这样做,JSTL解决得很好,一切正常 .所以现在我生成一个
.war
,你可以将其放入servlet容器中,或者你可以重命名为.jar
并独立运行 . 它可以在Unix和Windows上运行,而我以前这样做的方式在Unix上不起作用,因为詹姆斯库克提到的jsp-2.1-glassfish
库中存在一个错误 .来自我的pom的相关部分:
似乎嵌入式jetty 9不喜欢自动使用主可执行jar文件中的任何类路径条目 . 这包括taglib库 . 直接将类路径条目添加到webappclassloader似乎也不起作用 . 无论出于何种原因,类路径条目必须添加到webappclassloader的父级 .
简单的解决方案对我不起作用:
但手工扫描清单呢 . 我重新编写了上面的扫描示例,只是我可以看到发生了什么,并尝试不同的东西,我将在这里包括 .
这应该替换嵌入式jetty-jsp示例,该示例因任何原因无效,但应该,因为任何类路径条目都应自动包含在类路径中 . 但它确实说,JSP需要一个NON系统类加载器 . 所以我只能假设JSP一旦到达System类路径加载器就停止扫描类路径 . 这就是为什么我们有效地必须替换它 .
添加fat-jar作为WEB-INF jar,让
MetaInfConfiguration
找到* .tld文件 .参考:
https://eclipse.googlesource.com/jetty/org.eclipse.jetty.project/+/b3be24742353f7b5880fa8229a20ed0b19058cac/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java#123
https://github.com/wacai/json-template-renderer