1. Обзор

Jersey — это платформа с открытым исходным кодом для разработки веб-сервисов RESTful. Он служит эталонной реализацией JAX-RS.

В этой статье мы рассмотрим создание веб-службы RESTful с использованием Джерси 2. Кроме того, мы будем использовать Spring Dependency Injection (DI) с конфигурацией Java.

2. Зависимости Maven

Давайте начнем с добавления зависимостей в pom.xml:

Кроме того, для интеграции Spring нам нужно добавить зависимость jersey-spring4:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.26</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.26</version>
</dependency>

Последняя версия этих зависимостей доступна в jersey-container-servlet, jersey-media-json-jackson и jersey-spring4.

<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-spring4</artifactId>
    <version>2.26</version>
</dependency>

3. Веб-конфигурация

Далее нам нужно настроить веб-проект для настройки сервлета. Для этого мы будем использовать WebApplicationInitializer Spring:

Здесь мы добавляем аннотацию @Order(Ordered.HIGHEST_PRECEDENCE), чтобы убедиться, что наш инициализатор выполняется до инициализатора Jersey-Spring по умолчанию.

@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationInitializer 
  implements WebApplicationInitializer {
 
    @Override
    public void onStartup(ServletContext servletContext) 
      throws ServletException {
 
        AnnotationConfigWebApplicationContext context 
          = new AnnotationConfigWebApplicationContext();
 
        servletContext.addListener(new ContextLoaderListener(context));
        servletContext.setInitParameter(
          "contextConfigLocation", "com.baeldung.server");
    }
}

4. Сервис, использующий Jersey JAX-RS

4.1. Класс представления ресурсов

Давайте воспользуемся примером класса представления ресурсов:

Обратите внимание, что аннотации JAXB, такие как @XmlRootElement, требуются только в том случае, если требуется поддержка XML (в дополнение к JSON).

@XmlRootElement
public class Employee {
    private int id;
    private String firstName;

    // standard getters and setters
}

4.2. Реализация службы

Давайте теперь посмотрим, как мы можем использовать аннотации JAX-RS для создания веб-служб RESTful:

Аннотация @Path предоставляет относительный путь URI к службе. Мы также можем встраивать переменные в синтаксис URI, как показывает переменная {id}. Затем переменные будут заменены во время выполнения. Чтобы получить значение переменной, мы можем использовать аннотацию @PathParam.

@Path("/employees")
public class EmployeeResource {
 
    @Autowired
    private EmployeeRepository employeeRepository;

    @GET
    @Path("/{id}")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Employee getEmployee(@PathParam("id") int id) {
        return employeeRepository.getEmployee(id);
    }

    @POST
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Response addEmployee(
      Employee employee, @Context UriInfo uriInfo) {
 
        employeeRepository.addEmployee(new Employee(employee.getId(), 
          employee.getFirstName(), employee.getLastName(), 
          employee.getAge()));
 
        return Response.status(Response.Status.CREATED.getStatusCode())
          .header(
            "Location", 
            String.format("%s/%s",uriInfo.getAbsolutePath().toString(), 
            employee.getId())).build();
    }
}

@GET, @PUT, @POST, @DELETE и @HEAD определяют HTTP-метод запроса, который будет обрабатываться аннотированными методами.

Аннотация @Produces определяет тип ответа конечной точки (медиа-тип MIME). В нашем примере мы настроили его для возврата JSON или XML в зависимости от значения HTTP-заголовка Accept (application/json или application/xml).

С другой стороны, аннотация @Consumes определяет типы мультимедиа MIME, которые может использовать служба. В нашем примере служба может использовать JSON или XML в зависимости от типа содержимого HTTP-заголовка (application/json или application/xml).

Аннотация @Context используется для вставки информации в поле класса, свойство bean-компонента или параметр метода. В нашем примере мы используем его для внедрения UriInfo. Мы также можем использовать его для внедрения ServletConfig, ServletContext, HttpServletRequest и HttpServletResponse.

5. Использование ExceptionMapper

ExceptionMapper позволяет нам перехватывать исключения и возвращать клиенту соответствующий код ответа HTTP. В следующем примере код ответа HTTP 404 возвращается, если выдается исключение EmployeeNotFound:

6. Управление классами ресурсов

@Provider
public class NotFoundExceptionHandler 
  implements ExceptionMapper<EmployeeNotFound> {
 
    public Response toResponse(EmployeeNotFound ex) {
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}

Наконец, давайте свяжем все классы реализации службы и преобразователи исключений с путем приложения: ~~ ~

7. Тестирование API

@ApplicationPath("/resources")
public class RestConfig extends Application {
    public Set<Class<?>> getClasses() {
        return new HashSet<Class<?>>(
          Arrays.asList(
            EmployeeResource.class, 
            NotFoundExceptionHandler.class, 
            AlreadyExistsExceptionHandler.class));
    }
}

Теперь давайте проверим API с помощью нескольких живых тестов:

8. Заключение

public class JerseyApiLiveTest {

    private static final String SERVICE_URL
      = "http://localhost:8082/spring-jersey/resources/employees";

    @Test
    public void givenGetAllEmployees_whenCorrectRequest_thenResponseCodeSuccess() 
      throws ClientProtocolException, IOException {
 
        HttpUriRequest request = new HttpGet(SERVICE_URL);

        HttpResponse httpResponse = HttpClientBuilder
          .create()
          .build()
          .execute(request);

        assertEquals(httpResponse
          .getStatusLine()
          .getStatusCode(), HttpStatus.SC_OK);
    }
}

В этой статье мы представили платформу Jersey и разработали простой API. Мы использовали Spring для функций внедрения зависимостей. Мы также видели использование ExceptionMapper.

Как всегда, полный исходный код доступен в этом проекте Github.

«