- PVSM.RU - https://www.pvsm.ru -
Выросло данное API из JSR 311: JAX-RS: The Java API for RESTful Web Services [1] и вошло в Java SE 5. Как видно из названия, предназначено оно для разработки RESTful веб-сервисов.
Основная цель данной статьи — познакомить читателя с основами JAX-RS API. Изначально я планировал написать о некоторых проблемах работы форм при использование JAX-RS сервиса. Не обнаружив на Хабре почти ничего, касающегося данной технологии понял, что введением к статье отделаться не удастся.
Будут представлены основы JAX-RS API, реализация от JBoss и дано небольшое введение в клиентскую часть фреймворка Resteasy.
Представлено оно набором классов в javax.ws.rs.*, в случае современных AppServer'ов предоставляемое окружением (можно использовать <scope>provided</scope>
в maven [2]. Для приложений в сервлет-контейнерах есть несколько реализаций:
Эта технология позволяет экспортировать методы произвольного бина, используя специальный сервлет, предоставляемый реализаций JAX-RS. Приведу пример. Для использования в клиентской части выделим интерфейс:
package com.example;
import javax.ws.rs.*;
@Path("/")
public interface RestService {
@GET
@Path("echo")
String echo(@QueryParam("q") String original);
}
И реализацию:
package com.example;
import javax.enterprise.ApplicationScoped;
import javax.ws.rs.*;
@ApplicationScoped
@Path("/")
public class Rest implements RestService{
@GET
@Path("echo")
@Override
public String echo(@QueryParam("q") String original) {
return original;
}
}
Как к самому бину, так к его методам добавляющтся аннотации, описывающие его поведение: @Path
, например, указывает относительный или абсолютный путь к данному ресурсу; группа аннотаций @GET
, @POST
, @PUT
, @DELETE
отвечает за тип HTTP
запроса релевантный этому методу.
Очевидно, что для передачи проивольных данных, необходима сериализация — перевод данных из объектного представления в набор байт. Дальнейшее повествование я буду вести с оглядкой на Resteasy.
В этом случае для сериализации/десериализации используются специальные провайдеры. Аннотации @Produces
и @Consumes
, в которых указывается MIME-type содержимого результата/данных. Соответственно класс данных должен быть аннотирован JAXB [7]. Стандартными провайдерами в JBoss AS 7 являются resteasy-jaxb-provider (xml-маршаллер/анмаршаллер) и resteasy-jettison-provider (json). Эти два провайдера позволяют интергрироваться с большим количество внешних сервисов, предоставлять XML и JSON API наружу.
Что делать, если мы хотим вернуть нестандартный ответ или HTTP код? При Exception'е из аннотированного JAX-RS метода результатом будет 500 ошибка. Для кастомизации достаточно возвращаемым типом указать javax.ws.rs.core.Response
:
@GET
@Path("file/get/{name}")
Response getFile(@PathParam("file") String fileName) {
if(!Files.exists(Paths.get(fileName)) {
return Response.status(422).entity("I'm a teapot");
} else {
Response.Builder response = Response.ok();
response.header("X-Some-Server-Header", "value");
response.entity(new StremingOutput() {
@Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
Files.copy(Paths.get(fileName), outputStream);
}
});
return response.build();
}
}
Вторым приятным моментом JBoss Resteasy является наличие удобного клиентского фреймворка. Работа с ним возможна на разных уровнях абстракции: начиная от низкоуровневых ClientRequest
, ClientResponse<T>
и заканчивая генерацией прокси-объектов по аннотированному JAX-RS интерфейсу. Для примера, используя интерфейс RestService
из первого примера:
RestService service = ProxyFactory.create(RestService.class, "http://localhost:8080/example");
log.info(service.echo("test message"));
Но иногда этого недостаточно. Например в этом случае при ошибке на стороне сервера прокси генерирует исключение. Для более низкоуровневой работы может использоваться ClientRequest
/ClientResponse<T>
, использующие apache httpcomponents (в Resteasy 2.3.x.GA) или apache-httpclient (в 2.2.x.GA). Пример использования выглядит следующим образом:
ClientRequest request = new ClientRequest(url);
request.header("X-Additional-Header", "header value");
// варьируется в зависимости от метода: GET, POST, PUT, DELETE
ClientResponse<String> response = request.get(String.class);
if(response.getCode() == 200) {
String result = response.getEntity();
log.info(result);
}
Такой подход позволяет установить произвольные поля, произвольно тело запроса и т. п.
Одной возникающей в этом случае проблеме будет посвящена следующая статья.
Автор: grossws
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/3743
Ссылки в тексте:
[1] JSR 311: JAX-RS: The Java API for RESTful Web Services: http://jcp.org/en/jsr/summary?id=311
[2] maven: http://maven.apache.org/
[3] Apache CXF: http://cxf.apache.org/
[4] Sun/Oracle Jersey: http://jersey.java.net/
[5] JBoss Resteasy: http://www.jboss.org/resteasy/
[6] Restlet: http://www.restlet.org/
[7] JAXB: http://jcp.org/en/jsr/summary?id=jaxb
Нажмите здесь для печати.