You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Jetty与Jakarta包后出现UnavailableException问题求助

问题:升级Jetty和Jakarta包后抛出Servlet类型不匹配异常

将插件页面提供的示例更新到最新版Jetty容器和Jakarta包后抛出异常,程序期望旧类javax.servlet.Servlet,而非新的jakarta.servlet.Servlet。

环境信息

os: Ubuntu 22.10
java: openjdk version "11.0.11" 2021-04-20
scala: 2.13.10

build.sbt配置

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.10"

lazy val root = (project in file("."))
  .settings(
    name := "MyServlet"
  )

val jakartaServletApiVersion = "6.0.0"
val jettyVersion = "11.0.13"

libraryDependencies += "jakarta.servlet" % "jakarta.servlet-api" % jakartaServletApiVersion

Jetty / containerLibs := Seq("org.eclipse.jetty" % "jetty-runner" % jettyVersion)

enablePlugins(JettyPlugin)

plugins.sbt配置

addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.2.4")

web.xml配置

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>mypackage.MyServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

MyServlet.scala代码

package mypackage

import jakarta.servlet.annotation.WebServlet
import jakarta.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}

@WebServlet(urlPatterns = Array("/hello"))
class MyServlet extends HttpServlet {
  println("HEY")

  override def doGet(req: HttpServletRequest, res: HttpServletResponse): Unit = {
    res.setContentType("text/html")

    res.setCharacterEncoding("UTF-8")
    res.getWriter.write("""<h1>Hello, world!</h1>""")
  }
}

执行命令

jetty:start

抛出异常

UnavailableException: Servlet class mypackage.MyServlet is not a javax.servlet.Servlet

javax.servlet.UnavailableException: Servlet class mypackage.MyServlet is not a javax.servlet.Servlet
    at org.eclipse.jetty.servlet.ServletHolder.checkServletType(ServletHolder.java:514)
    at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:386)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
    at org.eclipse.jetty.servlet.ServletHandler.lambda$initialize$0(ServletHandler.java:730)
    at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
    at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
    at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:755)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:379)
    at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1449)
    at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1414)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:911)
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:288)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:524)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:117)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
    at org.eclipse.jetty.server.Server.start(Server.java:423)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:110)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
    at org.eclipse.jetty.server.Server.doStart(Server.java:387)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
    at org.eclipse.jetty.runner.Runner.run(Runner.java:519)
    at org.eclipse.jetty.runner.Runner.main(Runner.java:564)

原因分析与解决方法

原因

你使用的xsbt-web-plugin 4.2.4版本默认适配传统javax.servlet规范,未支持Jakarta EE的包名迁移(从javax改为jakarta)。尽管Jetty 11本身兼容Jakarta Servlet 5.0/6.0,但插件仍在用旧的javax.servlet.Servlet类型校验你的Servlet类,导致类型不匹配异常。

解决步骤

  1. 升级xsbt-web-plugin到支持Jakarta的版本
    修改plugins.sbt中的插件版本为5.x系列(要求sbt 1.5+,你的环境满足):

    addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "5.0.0")
    
  2. 在build.sbt中启用Jakarta模式
    添加配置告知插件使用Jakarta Servlet规范:

    webAppPackage := WebAppPackage.Jakarta
    
  3. 更新web.xml的Jakarta命名空间
    将旧的javax命名空间替换为Jakarta EE 6.0规范:

    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
             version="6.0">
    
        <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>mypackage.MyServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>MyServlet</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    </web-app>
    

完成以上修改后,重新执行jetty:start即可正常启动服务。

内容的提问来源于stack exchange,提问作者Heitor Barbieri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:45:36