Як налаштувати додаток JAX-RS, використовуючи лише анотації (без web.xml)?


80

Чи можна налаштувати програму JAX-RS, використовуючи лише анотації? (за допомогою Servlet 3.0 та JAX-RS Jersey 1.1.0)

Я намагався і мені не пощастило. Використання деяких web.xmlвидається необхідним.


Конфігурація A (працює, але має конфігурацію web.xml)

web.xml

   ...
   <servlet>
      <servlet-name>org.foo.rest.MyApplication</servlet-name>
   </servlet>
   <servlet-mapping>
       <servlet-name>org.foo.rest.MyApplication</servlet-name>
       <url-pattern>/*</url-pattern>
   </servlet-mapping>
   ...

Java

@ApplicationPath("/")
public class MyApplication extends Application {
    ...
}

Конфігурація B (не працює, виключення)

@ApplicationPath("/")
@WebServlet("/*") // <-- 
public class MyApplication extends Application {
    ...
}

Останнє, схоже, наполягає на тому, що Додаток буде підкласом Servlet (виняток не залишає здогадок)

java.lang.ClassCastException: org.foo.rest.MyApplication cannot be cast to javax.servlet.Servlet

Питання

  1. Чому визначення web.xml працювало, а анотація ні? Яка різниця?

  2. Чи є спосіб зробити так, щоб він працював, наприклад, мати додаток JAX-RS без web.xml?


1
Якщо ви можете спробувати з NetBeans, є майстер для створення веб-служб RESTFul. Здається, те, що ви намагаєтесь зробити, - це те, що робить цей майстер у версії 6.8. Я використовую 7.0.1, і новий підхід простіший, але використовує один сервлет для цієї мети, тобто com.sun.jersey.spi.container.servlet.ServletContainer, але його `` визначено в web.xml
perissf

Відповіді:


168

** БУДЬ ЛАСКА, ЧИ ВИ ВИКОРИСТОВУЄТЕ TOMCAT АБО JETTY! **

Прийнятий відповідь робить роботу, але тільки якщо веб - додаток розгорнуто на сервер додатків , як Glassfish або Wildfly, і , можливо , сервлет з ЕЕ розширеннями як TomEE. Це не працює у стандартних контейнерах сервлетів, таких як Tomcat, який, я впевнений, більшість людей, які шукають тут рішення, хочуть використовувати.

Якщо ви використовуєте стандартну інсталяцію Tomcat (або інший контейнер сервлета), вам потрібно включити реалізацію REST, оскільки Tomcat не постачається з нею. Якщо ви використовуєте Maven, додайте це до dependenciesрозділу:

<dependencies>
  <dependency>
    <groupId>org.glassfish.jersey.bundles</groupId>
    <artifactId>jaxrs-ri</artifactId>
    <version>2.13</version>
  </dependency>
  ...
</dependencies>

Потім просто додайте клас конфігурації програми до свого проекту. Якщо у вас немає особливих потреб конфігурації, крім встановлення контекстного шляху для інших служб, клас може бути порожнім. Після додавання цього класу не потрібно нічого налаштовувати web.xml(або взагалі його мати):

package com.domain.mypackage;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("rest") // set the path to REST web services
public class ApplicationConfig extends Application {}

Після цього оголошення ваших веб-служб відбувається прямо за допомогою стандартних анотацій JAX-RS у ваших класах Java:

package com.domain.mypackage;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.Path;

// It's good practice to include a version number in the path so you can have
// multiple versions deployed at once. That way consumers don't need to upgrade
// right away if things are working for them.
@Path("calc/1.0")
public class CalculatorV1_0 {
  @GET
  @Consumes("text/plain")
  @Produces("text/plain")
  @Path("addTwoNumbers")
  public String add(@MatrixParam("firstNumber") int n1, @MatrixParam("secondNumber") int n2) {
    return String.valueOf(n1 + n2);
  }
}

Це має бути все, що вам потрібно. Якщо ваша інсталяція Tomcat працює локально на порту 8080, і ви розгортаєте файл WAR у контексті myContext, збираєтеся ...

http://localhost:8080/myContext/rest/calc/1.0/addTwoNumbers;firstNumber=2;secondNumber=3

... повинен дати очікуваний результат (5).


6
@JavaDude - Ви повинні налаштувати Maven для створення файлу WAR, навіть якщо його web.xmlнемає. У вашому pom.xml, в розділі «збирання> плагін», додайте (якщо вже не існує): <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.3</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin>.
Елвін Томпсон,

6
@JavaDude - важлива частина - це <failOnMissingWebXml>false</fai‌​lOnMissingWebXml>варіант.
Елвін Томпсон,

3
@JavaDude - Якщо це не все, ви, швидше за все, не створили клас, який розширюється, Applicationі додали до нього @ApplicationPathанотацію. Клас може бути порожнім, але він повинен бути там.
Елвін Томпсон,

3
Досить лише додавати jersey-container-servlet, не тягнучи за собою всю jaxrs-riзалежність. Наприклад, у моєму випадку це було 'org.glassfish.jersey.core:jersey-server:2.18'+ 'org.glassfish.jersey.containers:jersey-container-servlet:2.18'.
leveluptor

3
Оскільки питання чітко позначене як "java-ee", я не розумію суті щодо надання та підтримання відповіді, яка НЕ ​​стосується середовища jee. -1
Ян Галинський

51

Здається, все, що мені потрібно було зробити, це (Servlet 3.0 і вище)

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/*")
public class MyApplication extends Application {
    ...
}

І ніякої конфігурації web.xml, мабуть, не було потрібно (спробував на Tomcat 7)


1
Не розумієте, як це працює, ви можете використовувати лише анотацію без будь-якої іншої конфігурації? Я пробував так і досі не працюю ...
Філіпе

2
@Filipe: Я здогадуюсь, що ви використовуєте Tomcat або інший контейнер сервлету. Це насправді не працює на контейнерах сервлетів, таких як Tomcat - воно працює лише з серверами додатків, такими як Glassfish або Wildfly, і, можливо, TomEE. Якщо ви використовуєте Tomcat, дивіться мою (пізню) відповідь нижче.
Елвін Томпсон,

8
Ця відповідь НЕ працює для Tomcat або Jetty! Будь ласка, перегляньте мою відповідь, щоб щось працювати в цих (та інших) контейнерах сервлетів.
Елвін Томпсон,

1
В залежності від реалізації, ви дійсно потребуєте web.xml, хоча порожній один буде досить. Див. Docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html_single/…
Бенджамін

Це працює на WebSphere Liberty, але не на WebSphere 8.x та 9.0 Classic.
Архімед Траяно

15

У розділі 2 специфікації JAX-RS: Java ™ API для специфікації веб-служб RESTful описується процес публікації програми JAX-RS у середовищі сервлету (розділ 2.3.2 Сервлет у специфікації).

Зверніть увагу, що середовище Servlet 3 рекомендовано лише (розділ 2.3.2 Servlet, стор. 6):

РЕКОМЕНДОВАНО, що реалізації підтримують механізм підключення фреймворка Servlet 3, щоб забезпечити перенесення між контейнерами та скористатися засобами сканування класів, що постачаються в контейнери.

Коротше кажучи, якщо ви хочете використовувати підхід no-web.xml, це можливо за допомогою спеціальної реалізації javax.ws.rs.core.Application, яка реєструє RESTful сервісні ресурси з анотацією javax.ws.rs.ApplicationPath .

@ApplicationPath("/rest")

Хоча ви запитували конкретно про Джерсі, вам також може сподобатися прочитати статтю Впровадження RESTful сервісів з JAX-RS та WebSphere 8.5 Liberty Profile, в якій я описав процес публікації no-web.xml для WebSphere Liberty Profile (з Apache Wink як реалізацію JAX-RS).


1
Дякуємо !, у мене є ще одне запитання, яке сильно пов’язане, і що зводить мене з розуму, чи є спосіб мати шлях у корені (наприклад, @ApplicationPath ("/ *")) і при цьому обслуговувати JSP, використовуючи лише Анотації? (хоча навіть з конфігурацією web.xml я не зміг цього здійснити) - питання тут: stackoverflow.com/questions/10874188/… , оскільки ви, здається, досить добре знаєте JAX-RS, не могли б ви поглянути? :) можливо, ви побачите, чого мені не вистачає ... дякую!
Еран Медан,

Не знаю. Кишкові почуття підказують мені, що це повинно працювати без додаткової конфігурації, оскільки процес вирішення ресурсу для обробки запиту відбувається з точної відповідності шаблонам URL-адрес. Я подивлюсь і відповім. Дякуємо за заохочення розширити свої знання! :-)
Яцек Ласковський

Я використовую, @ApplicationPath("")щоб мої служби REST були в кореневій системі (щодо контексту-кореня веб-додатка) на JBoss EAP 7. У мене немає beans.xmlні web.xml.
Жульєн Кронегг

7

Вам потрібно встановити правильні залежності в pom.xml

<dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
    </dependency>

Детальніше тут: Початковий приклад для jax-rs


Чи можу я видалити web.xml, якщо використовується ResourceConfig / Application?
BAE

так, але вам потрібно додати це в pom.xml i fusnig mave:<failOnMissingWebXml>
ACV

Дякую. але чи може щось зробити web.xml, але ResourceConfig не може?
BAE

Ні, я думаю, оскільки сервлет spec 3.0 web.xml більше не потрібен. Але іноді зручніше використовувати web.xml, оскільки він не вимагає перекомпіляції, якщо ви хочете щось змінити.
ACV

А що, якщо ви не використовуєте Maven ? Зараз мій проект занадто великий, щоб повернутися назад.
TheRealChx101

1

Згадані раніше залежності для мене не працювали. З посібника користувача Джерсі:

Джерсі пропонує два модулі сервлету. Перший модуль - це основний модуль сервлету Джерсі, який забезпечує основну підтримку інтеграції сервлетів і необхідний у будь-якому контейнері сервлету 2.5 або новішої версії:

<dependency>
 <groupId>org.glassfish.jersey.containers</groupId>
 <artifactId>jersey-container-servlet-core</artifactId>
</dependency>

Для підтримки додаткових режимів розгортання Servlet 3.x та асинхронної моделі програмування ресурсів JAX-RS потрібен додатковий модуль Джерсі:

<dependency>
 <groupId>org.glassfish.jersey.containers</groupId>
 <artifactId>jersey-container-servlet</artifactId>
</dependency>

Модуль jersey-container-servlet-сервер залежить від модуля jersey-container-servlet-core, тому, коли він використовується, не потрібно чітко оголошувати залежність jersey-container-servlet-core.

https://jersey.github.io/documentation/latest/deployment.html#deployment.servlet.3


0

Як зазначив @ Eran-Medan, JBoss EAP 7.1 (примітка без веб-програми, тому без сервлету, я робив це в проекті EJB 3.2), мені довелося додати атрибут "value" як такий, оскільки я отримував виняток необхідний атрибут value.

Це спрацювало для мене

    @ApplicationPath(value="/*")
        public class MyApplication extends Application {

            private Set singletons = new HashSet();

            public MyApplication() {
                singletons.add(new MyService());
            }

            ...
    }

Трасування стека

    Caused by: java.lang.annotation.IncompleteAnnotationException: javax.ws.rs.ApplicationPath missing element value
        at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:80)
        at com.sun.proxy.$Proxy141.value(Unknown Source)
        ... 21 more
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.