从6.1.7到9.4.43的嵌入式码头升级问题



我在旧的jetty版本中使用了jetty.xml进行配置,它看起来像这样:

<Configure id="Server" class="org.mortbay.jetty.Server">
<Set name="ThreadPool">
<New class="org.mortbay.thread.BoundedThreadPool">
<Set name="minThreads">10</Set>
<Set name="maxThreads">250</Set>
<Set name="lowThreads">25</Set>
</New>
</Set>
<Call name="addConnector">
<Arg>
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="host">
<SystemProperty name="jetty.host"/>
</Set>
<Set name="port">
<SystemProperty name="jetty.port" default="9096"/>
</Set>
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
<Set name="handler">
<New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.mortbay.jetty.Handler">
<Item>
<New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
</Item>
<!-- Disabling this as it is a security risk (by exposing all contexts) in production-->
<!--Item>
<New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
</Item-->
<Item>
<New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.ContextDeployer">
<Set name="contexts">
<Ref id="Contexts"/>
</Set>
<Set name="configurationDir">
<SystemProperty name="jetty.home" default="."/>/contexts</Set>
<Set name="scanInterval">1</Set>
</New>
</Arg>
</Call>
<New class="org.mortbay.jetty.servlet.Context">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<Ref id="RequestLog">
<Set name="requestLog">
<New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
<Set name="filename">
<SystemProperty name="jetty.logs" default="../logs"/>/ws.request_yyyy_mm_dd.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="extended">true</Set>
<Set name="logCookies">false</Set>
<Set name="LogTimeZone">GMT</Set>
</New>
</Set>
</Ref>
<!-- =========================================================== -->
<!-- extra options                                               -->
<!-- =========================================================== -->
<Set name="stopAtShutdown">true</Set>
<Set name="sendServerVersion">true</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
</Configure>```
And to call this configuration following code has been written:
<Ref id="RequestLog">
<Set name="requestLog">
<New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
<Set name="filename">
<SystemProperty name="jetty.logs" default="../logs"/>/ws.request_yyyy_mm_dd.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="extended">true</Set>
<Set name="logCookies">false</Set>
<Set name="LogTimeZone">GMT</Set>
</New>
</Set>
</Ref>
<!-- =========================================================== -->
<!-- extra options                                               -->
<!-- =========================================================== -->
<Set name="stopAtShutdown">true</Set>
<Set name="sendServerVersion">true</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
</Configure>

已经编写了以下代码来调用此配置:

Server myServer;
File theConfigFile = new File( "C://jetty//etc//jetty.xml" );
XmlConfiguration theXmlConfiguration = new XmlConfiguration( theConfigFile.toURL() );
theXmlConfiguration.configure( myServer );
myServer.start();

我试图使用jetty 9.4.43:创建类似的配置

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">

<Configure id="jetty" class="org.eclipse.jetty.server.Server">
<New id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Set name="minThreads" type="int"><Property name="jetty.threadPool.minThreads" deprecated="threads.min" default="10"/></Set>
<Set name="maxThreads" type="int"><Property name="jetty.threadPool.maxThreads" deprecated="threads.max" default="200"/></Set>
<Set name="reservedThreads" type="int"><Property name="jetty.threadPool.reservedThreads" default="25"/></Set>
<Set name="idleTimeout" type="int"><Property name="jetty.threadPool.idleTimeout" deprecated="threads.timeout" default="60000"/></Set>
<Set name="detailedDump" type="boolean"><Property name="jetty.threadPool.detailedDump" default="false"/></Set>
</New>

<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler"/>
</Arg>
</Call>

<Set name="connectors">
<Array type="org.eclipse.jetty.server.Connector">
<Item>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg><Ref refid="jetty"/></Arg>
<Set name="port">
<Property name="jetty.http.port" default="9096" />
</Set>
</New>
</Item>
</Array>
</Set>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.HandlerList">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
<Set name="resourceBase">.</Set>
</New>
</Item>
</Array>
</Set>
</New>
</Set>

<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<Set name="stopAtShutdown"><Property name="jetty.server.stopAtShutdown" default="true"/></Set>
<Set name="stopTimeout"><Property name="jetty.server.stopTimeout" default="5000"/></Set>
<Set name="dumpAfterStart"><Property name="jetty.server.dumpAfterStart" deprecated="jetty.dump.start" default="true"/></Set>
<Set name="dumpBeforeStop"><Property name="jetty.server.dumpBeforeStop" deprecated="jetty.dump.stop" default="true"/></Set>
</Configure> 

使用新的jetty.xml,端口9096被公开,intelliJ运行所在目录下的所有可用文件都可以访问,但FileProxyServlet url(即localhost:9096/cts/output)不可访问(显示HTTP ERROR 404 not Found)。以前的情况并非如此,只是servlet运行良好。

以下是使用新码头运行的控制台日志:

系统属性[DEBUG]已被弃用!(请使用org.eclipse.jjetty.LEVEL=DEBUG)2021-10-1613:56:48.162:信息::main:日志记录在80050ms时初始化为org.eclipse.jetty.util.log.StdErrLog[ShutdownMonitor]未启用(端口<0):-1 2021-10-16 13:56:48.547:信息:oejs.服务器:Jetty Web服务器启动线程:jetty-9.4.43.v20210629;建成时间:2021-06-30T11:07:22.254Z;git:526006年6月6日生效;jvm 11.0.7+10-LTS 2021-10-1613:56:48.650:信息:oejs.AbstractConnector:Jetty Web服务器启动线程:已启动ServerConnector@70239ac0{HTTP/1.1,(http://1.1)}{0.0.0.0:9096}Server@4db85c57{启动}[9.4.43.v20210629]

  • 启动+=队列线程池[qtp1589931229]@5ec46cdd{STARTED,8<=8<=200,i=6,r=-1,q=0}[ReservedThreadExecutor@16627f86{s=0/2,p=0}]
  • 已启动|+-org.eclipse.jetty.util.thread.ThreadPoolBudget@2d7c53b6|+=ReservedThreadExecutor@16627f86{s=0/2,p=0}-已启动|+>螺纹size=8|+>qtp1589931229-31可运行tid=31 prio=5@java.base@11.0.7/java.lang.invoke.InerClassLambdaMetafactory.getParameterSize(InnerClassLambdaMetafactory.java:522)|+>qtp1589931229-34 TIMED_WAITING tid=34 prio=5 IDLE|+>qtp1589931229-29 TIMED_WAITING tid=29 prio=5 IDLE|+>qtp1589931229-27 TIMED_WAITING tid=27 prio=5 IDLE|+>qtp1589931229-32 TIMED_WAITING tid=32 prio=5 IDLE|+>qtp1589931229-33可运行tid=33 prio=5选择|+>qtp1589931229-28 TIMED_WAITING tid=28 prio=5 IDLE|+>qtp1589931229-30 TIMED_WAITING tid=30 prio=5 IDLE+=ScheduledExecutorScheduler@1e20e272{已启动}-已启动+=ServerConnector@70239ac0{HTTP/1.1,(HTTP/1.1)}{0.0.0.0:9096}-已启动|+~Server@4db85c57{启动}[9.4.43.v20210629]-启动|+~QueuedThreadPool[qtp1589931229]@5ec46cdd{STARTED,8<=8<=200,i=6,r=-1,q=0}[ReservedThreadExecutor@16627f86{s=0/2,p=0}]
  • 已启动|+~ScheduledExecutorScheduler@1e20e272{STARTED}-STARTED |+-org.eclipse.jetty.io.ArrayByteBufferPool@3a1e66f1|+=HttpConnectionFactory@dc1f9ce[HTTP://1.1]-已启动||+-HttpConfiguration@1960af83{32768/81928192/8192,https://:0,[]}|
    +>自定义程序大小=0||+>formEncodedMethods size=2|||+>POST |||+>PUT ||+>outputBufferSize=32768|+>outputAggregationSize=8192||+>requestHeaderSize=8192||+>responseHeaderSize=8192|+>headerCacheSize=1024||+>secureScheme=https||+>securePort=0||+>idleTimeout=-1||+>blockingTimeout=-1||+>sendDateHeader=true||+>sendServerVersion=true||+>sendXPoweredBy=false ||+>delayDispatchUntilContent=true||
    +>persistentConnectionsEnabled=true||+>maxErrorDispatches=10 ||+>minRequestDataRate=0||+>minResponseDataRate=0||+>cookieCompliance=RFC6265||+>setRequestCookieCompliance=RFC6265||+>notifyRemoteAsyncErrors=true||+>relativeRRedirectAllowed=false|+=SelectorManager@ServerConnector@70239ac0{HTTP/1.1,(http://1.1)}{0.0.0.0:9096}-已启动||+=ManagedSelector@6ade7db{STARTED}id=0个密钥=0个已选择=0个更新=0-已启动||+=EatWhatYouKill@6c4eab86/SelectorProducer@550ad4bd/正在生成/p=false/QueuedThreadPool[qtp1589931229]@5ec46cdd{已启动,8<=8<=200,i=6,r=-1,q=0}[ReservedThreadExecutor@16627f86{s=0/2,p=0}][pc=0,pic=0,pec=0,epc=0]@2021-10-16T13:56:48.6782121+05:30
  • 已启动||+-SelectorProducer@550ad4bd||+~QueuedThreadPool[qtp1589931229]@5ec46cdd{STARTED,8<=8<=200,i=6,r=-1,q=0}[ReservedThreadExecutor@16627f86{s=0/2,p=0}]
  • 已启动||+>更新@2021-10-16T13:56:48.6732217+05:30 size=0||+>密钥@2021-10-16T13:56:48.674221+05:30大小=0|+-sun.nio.ch.ServerSocketChannelImpl[/0:0:0:0:0:0:9096]|+-qtp1589931229-31-acceptor-0@24c38c77-ServerConnector@70239ac0{HTTP/1.1,(http://1.1)}{0.0.0.0:9096}+=HandlerList@34d20482{STARTED}-STARTED |+=ResourceHandler@28a68c0{已启动}-已启动+=ErrorHandler@61ad62a3{已启动}-已启动+>jdk.internal.loader.ClassLoaders$AppClassLoader@311d617d+>jdk.internal.loader.ClassLoaders$PlatformClassLoader@5e955596密钥:+-bean,+=托管,+~非托管,+?auto,+:可迭代,+]数组+@地图,+>未定义2021-10-16 13:56:48.679:信息:oejs.服务器:Jetty Web服务器启动线程:已启动@80567ms

过去几天我一直在为此而挣扎,有人能帮我吗?

我建议进行一些更改。

首先,ResourceHandler没有为您做任何事情。

<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
<Set name="resourceBase">.</Set>
</New>
</Item>
</Array>

充其量,它坐在那里什么也不做。(因为它没有上下文,所以没有请求可以到达它)。最坏的情况是,按照你的设置方式,你现在已经通过ResourceHandler共享了整个驱动器。

移除它。

接下来,您的ServletContext。。。

<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>

关于这份声明的事情。。。

  • 它没有以</New>结束,所以它是一个损坏的XML。
    • 修复您的XML
  • 第一个<Arg><Ref id="Contexts"/></Arg>是毫无意义的,也被破坏了。第一个参数似乎试图指向其他地方的Contexts引用,但该引用在任何地方都不存在,并且您对<Ref>元素的使用也是错误的,您已经用id="Contexts"声明了<Ref>本身,并且没有引用其他id,即<Ref refid="otherId"/>
    • 完全删除<Arg>,它没有任何用途
  • 使用<Arg>/cts/output</Arg>设置上下文路径在很多方面都是错误的。
    • 上下文路径规则是(必须以/开头,并且不能在其他任何位置包含任何其他斜杠,没有嵌套的上下文路径,这就是url模式的用途)
    • 不要试图使用构造函数来设置上下文路径,请使用setter
    • 也删除此<Arg>,声明一个有效的上下文路径,然后使用setter代替<Set name="contextPath">/foo</Set>
  • 您向/url模式添加了一个servlet,从而使resourceBase上的工作无效。
    • 修复这个url模式
  • 您的ServletContextHandler也不是服务器处理程序树的一部分。我认为您试图在第一个<Arg>中做到这一点,但这不是将其添加到处理程序树中的方式。
    • 如果直接声明它,只需将<New class="ServletContextHandler">...放入处理程序树本身即可
    • 如果稍后要加载/实例化ServletContextHandler,则必须使用DeploymentManagerWebAppProvider以及处理程序树中已存在的现有ContextHandlerCollection,以便将其添加到部署中

你有一个奇怪的、坦率地说是破碎的用法组合,即使是Jetty 6也不应该允许。

您不能在默认的url模式(即/)上有FileProxyServlet,并且同时提供静态资源。

建议,正确使用Jetty(这些建议也适用于Jetty 6和Jetty 4!)

  1. 不要混合ServletContextHandlerResourceHandler
  2. 仅使用ServletContextHandler
  3. 使ServletContextHandler上下文路径仅为/ctx
  4. 使ServletContextHandlerresourceBase指向静态文件内容所在的位置(目录或jar:file://url)
  5. 将普通的DefaultServlet添加到ServletContextHandler中(确保它被命名为"default",并且是映射到/的仅有servlet)
  6. 将您的com.myservlet.webservices.remote.FileProxyServlet添加到url模式/output
  7. 最后,将ServletContextHandler添加到服务器处理程序树中

以下是我鼓励您阅读的过去答案中的更多信息。

  • Jetty:默认servlet上下文路径
  • 在嵌入式Jetty中从备用路径提供静态文件
  • 使用Jetty嵌入式容器时,ServletContextHandler.setResourceBase和ResourceHandler.setResource Base之间有什么区别
  • 嵌入式Jetty处理url以提供内容
  • 如何配置码头装卸工
  • 在嵌入式Jetty中从备用路径提供静态文件
  • Jetty:如何嵌套HandlerWrapper、HandlerList、ContextHandlerCollection和ContextHandler

问题是,完全在一个XML文件中完成这项工作是令人困惑的(在Jetty 6.0.0首次发布时,不鼓励使用单个XML文件来配置Jetty)。您是否考虑过使用jetty-home附带的XML文件,并在自己的嵌入式jetty启动中引用它们(按正确的顺序)?

这意味着您只需要手动定义ServletContextHandler,并将其放在您希望WebAppProvider查找要部署的上下文的任何位置。

额外的好处是,您升级Jetty版本的努力变得微不足道。