2016-05-29 91 views
0

我正在學習Java EE 7 Servlets,並嘗試使用嵌入式Jetty(v 9.3.7)從Java EE 7教程部署hello2example,但收效甚微。 hello2由兩個servlet和一個圖像文件組成。該配置被註釋並且該項目沒有任何web.xml。使用帶註釋的配置文件的嵌入式碼頭

WebAppContext部分從嵌入碼頭examples我創造了這個主類以啓動我的嵌入式服務器:

public class MyServer { 

public static void main(String[] args) throws Exception { 
    Server server = new Server(8080); 
    String webappPath = new File(MyServer.class.getProtectionDomain().getCodeSource().getLocation().getFile()) 
       .getParentFile().getParentFile().getAbsolutePath(); 

    WebAppContext webapp = new WebAppContext(webappPath, ""); 

    webapp.setConfigurations(new Configuration[]{ 
      new AnnotationConfiguration()}); 

    server.setHandler(webapp); 
    server.start(); 
    server.join(); 
    } 
} 

據我瞭解,由於碼頭是一個Java EE Web容器,它應該能夠服務於示例Serlvet項目是,我只需要指向戰爭文件夾結構。以下是該項目的結構:

-- hello2 
\-- src 
    \-- main 
     +-- java 
     │   +-- MyServer.java 
     │   \-- javaeetutorial 
     │    \-- hello2 
     │     +-- GreetingServlet.java 
     │     \-- ResponseServlet.java 
     \-- webapp 
      +-- WEB-INF 
      │   \-- classes 
      │    +-- MyServer.class 
      │    \-- javaeetutorial 
      │     \-- hello2 
      │      +-- GreetingServlet.class 
      │      \-- ResponseServlet.class 
      +-- index.html 
      \-- resources 
       \-- images 
        \-- duke.waving.gif 

hello2示例代碼可以發現here。以下是該文件被編譯爲hello2/webapp/classes/從而使webapp文件夾的分解WAR的GreetingServlet

@WebServlet("/greeting") 
public class GreetingServlet extends HttpServlet { 

@Override 
public void doGet(HttpServletRequest request, 
     HttpServletResponse response) 
     throws ServletException, IOException { 
.... 

ResponseServlet

@WebServlet("/response") 
public class ResponseServlet extends HttpServlet { 

@Override 
public void doGet(HttpServletRequest request, 
     HttpServletResponse response) 
     throws ServletException, IOException { 
.... 

某些部分。我添加index.html是爲了測試Jetty是否選擇它。其結果是,我得到404錯誤當我訪問本地主機:8080,本地主機:8080 /問候或本地主機:8080 /響應

如果我添加WebXmlConfigurationwebapp.setConfigurations(),然後設置類似webapp.setResourceBase(webappPath)的資源基礎,我設法進入Jetty的靜態文件服務器。這是因爲Jetty然後使用默認的web.xml,它將用於文件服務目的的servlet添加到服務器。但即使如此,我的註釋servlet沒有拿起。

我有碼頭閱讀註釋servlet配置是通過設置WEB-INF目錄的方式明確使用WebAppContext.getMetadata().setWebInfClassesDirs()

webapp.getMetaData().setWebInfClassesDirs(
    Arrays.asList(Resource.newResource(
    MyServer.class.getProtectionDomain().getCodeSource().getLocation()))); 

然後,servlet的反應不如預期,但這並不爲我的index.html或圖像文件。我也將資源庫設置爲無用。所以我想要的是Jetty無需web.xml即可爲我的Web應用程序提供服務,並且只需將它指向展開的WAR目錄即可。顯然我錯過了一些東西。

回答

0

使用...

webapp.setConfigurations(new Configuration[]{ 
     new AnnotationConfiguration()}); 

將取消所有現存的重要配置,只啓用了AnnotationConfiguration

難怪它不爲你工作,與安裝,加載WEB-INF/web.xml缺少的配置,使用WEB-INF/lib配置丟失等

你必須適當地修改現有的配置列表,並且有很多示例可以向您展示這一點。

由於您沒有指定使用JNDI的註釋,或者存在於web-fragments中,或者來自webapp上下文之外(例如容器本身),所以您需要的確切配置很難指定。

請參閱https://github.com/jetty-project/embedded-servlet-3.1項目,瞭解完成此項目的完整項目。

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

這是一個普遍的設置,這是最常見的,但可能會使您可能不希望額外的配置。

即使您不想要其他組件,您仍然需要讓它們成爲發現的Web應用程序。否則,你有一個100%的手動Web應用程序,你特別呼籲.addServlet().addFilter()等。

您應該改爲使用此語法。

private void enableAnnotationScanning(Server server) 
{ 
    Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server); 
    classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", 
      "org.eclipse.jetty.annotations.AnnotationConfiguration"); 
} 

,因爲這將修改配置的現有列表只添加AnnotationConfiguration

如果你想看到這種格式的其他例子,看看下面的示例項目:

+0

正如我在我的問題中寫的,我使用註釋來配置,而不是在Java EE 7中可選的web.xml。另外,我相信我不需要WEB-INF/lib,因爲我沒有使用它。我只使用了AnnotationConfiguration,因爲我配置了註釋中的所有內容,我想了解它爲什麼不起作用。我的理論是,這個設置應該適用於所有支持servlet容器的Java EE 7。 – qtips

+0

即使您沒有實際的文件,您仍然需要配置,因爲這是如何設置webapp元數據的。沒有配置,沒有元數據,沒有關於設置的知識,等等。元數據是構建在所有這些配置上的。只有Annotation/Plus/Env是可選的,其餘都是必需的。 –

+0

添加WebInfConfiguration時,Jetty開始閱讀我的註釋配置:)我仍然認爲我不應該需要WebXmlConfiguration,因爲我看到Jetty使用默認的web.xml來設置一些內置的servlet。但沒有它,Jetty不會服務我的index.html。爲什麼必須添加自己的web.xml以支持靜態內容?我想我被Jettys WebAppContext弄糊塗了;它用於專門爲Web應用程序提供服務(與ServletContextHandler相比),但不支持標準的Java EE配置,不使用setConfigurations。 – qtips

0

與喬金 - Erdfelt討論之後,我再看着Tomcat和我明白,碼頭可能不是測試不同種類的Java EE Web功能的最佳容器。 Jetty以其他方式實現對Java EE的支持,而不是Glasshfish和Tomcat,而這又需要不同的設置方法,這在Joakims答案下的討論中進行了詳細說明。

使用下面的代碼片斷

public class MyServer { 

public static void main(String[] args) throws Exception { 
    Tomcat tomcat = new Tomcat(); 
    tomcat.setPort(8080); 

    tomcat.addWebapp("","webapp"); 

    tomcat.start(); 
    tomcat.getServer().await(); 
    } 

} 

它首先考慮如Tomcat並不需要任何的web.xml,但經過進一步調查,Tomcat使用默認的web.xml和Tomcat測試如果不能提供一個後。這個web.xml包含一個<welcome-file>index.html</welcome-file>和一個提供靜態內容的DefaultServlet。這種方法與Jettys類似,我認爲這也是Glassfish的工作原理。所以經驗教訓是,總是有一些DefaultServlet潛伏在Java EE web服務器的後臺,這有一些神奇的功能。即使web.xml對服務器的用戶是可選的,服務器仍然在幕後提供它以使其自行工作。

+0

對我所說的有趣的解釋。 :-( –

+0

如果我誤解了你,我很抱歉:(jetty似乎非常靈活,可能也提供了更好的性能,但是這種靈活性使得安裝更加困難,你不能簡單地遵循官方的Java EE教程設置並期望它能夠工作。你必須添加碼頭特定的設置才能使其工作。當然這不是一個大問題,但是在學習Java EE和Sevlet時可能會有點混淆。 – qtips

+0

如果你專注於Java EE,我會推薦使用[TomEE](http://tomee.apache.org/),而不是普通的Tomcat(因爲它與Jetty的子集範圍相同)。但是請注意,TomEE並不擅長嵌入(主要是由於Java EE對它的限制) –