20

我有一个带有嵌入式码头服务器的应用程序,我正在像这样启动它(放置在 main() 并使用 eclipse 启动):

Server server = new Server(port);

WebAppContext context = new WebAppContext();
context.setResourceBase("web/");
context.setDescriptor("web/WEB-INF/web.xml");
context.setConfigurations(new Configuration[]{
            new AnnotationConfiguration(), new WebXmlConfiguration(),
            new WebInfConfiguration(), new TagLibConfiguration(),
            new PlusConfiguration(), new MetaInfConfiguration(),
            new FragmentConfiguration(), new EnvConfiguration()});

context.setContextPath("/");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();

我的 web.xml 看起来像这样(暂时为空,我不确定是否可以完全删除它):

<web-app 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    metadata-complete="false"
    version="3.0">
</web-app>

我有一个像这样设置的简单类:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException  {
        request.getRequestDispatcher("/WEB-INF/html/index.html").forward(request,response);
    }
}

当我在 web.xml 中使用传统的 servlet 映射时,我的应用程序运行良好。但是当我删除 web.xml 映射并使用注释时,我只得到 404。它看起来根本不像在扫描注释。控制台如下所示:

2012-08-01 17:40:37.021:INFO:oejs.Server:jetty-8.1.5.v20120716
2012-08-01 17:40:37.227:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one.
2012-08-01 17:40:37.294:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.641:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080

我已经从我的研究中检查了一些事情:

  • servlet-3.0 jar 在类路径中
  • 在 web.xml 中元数据完整设置为 false
  • 我确保在 Web 应用程序上下文中包含 AnnotationConfiguration

我已经没有想法了,正要恢复到旧的 web.xml,但这让我很生气,为什么我不能让它工作。

4

7 回答 7

8

更新:2021 年 6 月

示例项目已更新为 Jetty 版本中性。

https://github.com/jetty-project/embedded-servlet-server

它现在有特定版本的 Jetty 的分支。

较旧的示例项目已存档。

更新:2015 年 6 月

示例项目已针对 Jetty 9 和 Servlet 3.1 进行了更新

见:https ://github.com/jetty-project/embedded-servlet-3.1

原答案:

根据您的描述,以及我使用您的代码创建的示例项目,您所做的一切都是正确的。

示例项目:https ://github.com/jetty-project/embedded-servlet-3.0

为了使它起作用,您需要以下内容(仅提及这一点,因为您的问题未包含此详细信息)

  • JDK 1.6+
  • 来自 Jetty 8.1.x(或更高版本)的 jetty-webapps jar(+ 依赖项)
  • 来自 Jetty 8.1.x(或更高版本)的 jetty-annotations jar(+ 依赖项)

仅从这些有限的要求中,您就会看到以下依赖项列表。

$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building sample-webapp 1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ sample-webapp ---
[INFO] com.company.sample:sample-webapp:war:1-SNAPSHOT
[INFO] +- org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016:provided
[INFO] +- org.eclipse.jetty:jetty-webapp:jar:8.1.5-SNAPSHOT:test
[INFO] |  +- org.eclipse.jetty:jetty-xml:jar:8.1.5-SNAPSHOT:test
[INFO] |  |  \- org.eclipse.jetty:jetty-util:jar:8.1.5-SNAPSHOT:test
[INFO] |  \- org.eclipse.jetty:jetty-servlet:jar:8.1.5-SNAPSHOT:test
[INFO] |     \- org.eclipse.jetty:jetty-security:jar:8.1.5-SNAPSHOT:test
[INFO] |        \- org.eclipse.jetty:jetty-server:jar:8.1.5-SNAPSHOT:test
[INFO] |           +- org.eclipse.jetty:jetty-continuation:jar:8.1.5-SNAPSHOT:test
[INFO] |           \- org.eclipse.jetty:jetty-http:jar:8.1.5-SNAPSHOT:test
[INFO] |              \- org.eclipse.jetty:jetty-io:jar:8.1.5-SNAPSHOT:test
[INFO] \- org.eclipse.jetty:jetty-annotations:jar:8.1.5-SNAPSHOT:test
[INFO]    +- org.eclipse.jetty:jetty-plus:jar:8.1.5-SNAPSHOT:test
[INFO]    |  +- org.eclipse.jetty.orbit:javax.transaction:jar:1.1.1.v201105210645:test
[INFO]    |  \- org.eclipse.jetty:jetty-jndi:jar:8.1.5-SNAPSHOT:test
[INFO]    |     \- org.eclipse.jetty.orbit:javax.mail.glassfish:jar:1.4.1.v201005082020:test
[INFO]    |        \- org.eclipse.jetty.orbit:javax.activation:jar:1.1.0.v201105071233:test
[INFO]    +- org.eclipse.jetty.orbit:javax.annotation:jar:1.1.0.v201108011116:test
[INFO]    \- org.eclipse.jetty.orbit:org.objectweb.asm:jar:3.1.0.v200803061910:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.771s
[INFO] Finished at: Fri Aug 10 18:17:46 MST 2012
[INFO] Final Memory: 6M/180M
[INFO] ------------------------------------------------------------------------

您很可能只是缺少依赖项或 JDK 要求。

于 2012-08-11T01:18:12.670 回答
7

AnntationConfigurationscanForAnnotations(WebAppContext)类通过其方法扫描注释。在方法AnnotationConfiguration类中扫描以下路径。

  • 容器罐
  • WEB-INF/类
  • WEB-INF/库

因此,如果您希望src/main/java扫描生产代码中的 servlet 类(即目录中的源代码),请将生产代码添加WebAppContextWEB-INF/classes.

试试下面的代码,将您的代码添加到WebAppContext的元数据中。

URL classes = getClass()
        .getProtectionDomain()
        .getCodeSource()
        .getLocation();

WebAppContext context = new WebAppContext();
context.getMetaData()
    .setWebInfClassesDirs(
        Arrays.asList(Resource.newResource(classes)));
于 2014-10-06T16:31:31.150 回答
5

我有同样的问题,但经过多次阅读后,我得到了解决方案!重要提示:请记住在您的构建路径中包含以下 jar:

jetty-all-9.0.6.v20130930.jar

jetty-annotations-9.0.6.v20130930.jar

org.objectweb.asm-3.1.0.v200803061910.jar

javax.servlet-api-3.0.1.jar

jetty-plus-9.0.6.v20130930.jar

public class Main {

   public static void main(String[] args) throws Exception {

       //Create the server
       Server server = new Server(8080);

       ClassList clist = ClassList.setServerDefault(server);

       //clist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration",    "org.eclipse.jetty.plus.webapp.PlusConfiguration");
       clist.addBefore(JettyWebXmlConfiguration.class.getName(), AnnotationConfiguration.class.getName());

       //Here is the trick to scan current classpath!
       webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", 
            ".*/build/classes/");

       webapp.setContextPath("/");
       webapp.setResourceBase("./WebContent");


       server.setHandler(webapp);

       server.start();
       server.join();

   }

}
于 2013-11-03T00:41:03.620 回答
1

基于之前 Joakim 提供的示例,我上传了一个修改后的版本,该版本支持嵌入式码头中的注释,而无需将项目打包到 war 文件中。该项目已准备好部署到 Heroku,正在运行:

$java -cp target/classes:"target/dependency/*" com.example.Launcher

如果您对细节感兴趣,重要的几行来自 com.example.Launcher:

context.setConfigurations(new Configuration[] {
            new AnnotationConfiguration(), new WebXmlConfiguration(),
            new WebInfConfiguration(),
            new PlusConfiguration(), new MetaInfConfiguration(),
            new FragmentConfiguration(), new EnvConfiguration() });

// Important! make sure Jetty scans all classes under ./classes looking for annotations. 
//'Classes' directory is generated running 'mvn package'
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/classes/.*");

您可以根据要扫描注释的类相应地更改 JarPattern。

在这里你有完整的例子:https ://github.com/pablormier/embedded-jetty-annotations-example

于 2014-08-03T09:41:20.147 回答
1

我提出了一种针对 Jetty & Spring 的不同方法。我没有让 Jetty 扫描类,而是在自定义 Jettyinitializer的方法中手动调用类。代码如下:startContext()ServletContextHandler

public class CustomServletContextHandler extends ServletContextHandler {

   @Override
   protected void startContext() throws Exception {

       SpringServletContainerInitializer initer = new SpringServletContainerInitializer();

        HashSet<Class<?>> classes = new HashSet<>();
        // Add annotated classes here such as
        //classes.add(SpringSecurityInitializer.class);
        //classes.add(SpringWebInitilializer.class);

        try {
            initer.onStartup(classes, this.getServletContext());
        }catch(Exception e)
        {
            e.printStackTrace();
        }

        super.startContext();
    }
}

然后在创建上下文时,使用自定义处理程序:

 ServletContextHandler ctx = new CustomServletContextHandler();
 ctx.setContextPath("/");
 ...
于 2016-03-03T12:45:58.510 回答
0

在我们的例子中,这些行有助于 Jetty 启动代码:

    ClassList cl = Configuration.ClassList.setServerDefault(server);
    cl.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration");
于 2014-10-17T09:41:54.427 回答
0

你可以

  1. EmptyResource.INSTANCE如果您不需要静态资源,请提供

  2. 添加 AnnotationConfiguration 和覆盖 scanForAnnotations方法,将类路径资源添加到WebAppContext元数据,可能带有根包的路径以进行扫描

    WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        webapp.setBaseResource(EmptyResource.INSTANCE);
        webapp.setConfigurations(new Configuration[]{
                new AnnotationConfiguration(){
                    @Override
                    protected void scanForAnnotations(WebAppContext context) throws Exception {
                        Resource classPathResource =    Resource.newResource(EmbeddedServerApp.class.getResource("/my/learn/jetty/servlet").toURI());
                        context.getMetaData().addContainerResource(classPathResource);
                        super.scanForAnnotations(context);
                    }
                },
        });
        server.setHandler(webapp);
        server.start();
    
于 2020-02-01T19:13:49.543 回答