Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Распределенные сервис-ориентированные системы..pdf
Скачиваний:
16
Добавлен:
05.02.2023
Размер:
9.2 Mб
Скачать

Теперь, проведем демонстративную реализацию нашего учебного сервиса, используя указанные классические ограничения.

6.3.2 Полная реализация RESTfull-сервиса

Реализация RESTful-сервиса должна следовать ряду общих правил, обеспечивающих выполнение операций типа CRUD.

Учитывая большое многообразие возможных реализаций Web-служб в стиле RESTful, ограничимся рассмотрением эталонного примера, который поддерживает только набор операций типа CRUD. Для изучения других примеров следует воспользоваться специальной литературой или примерами удачных проектов, опубликованных в различных источниках.

Реализацию учебного примера проведем посредством модификации класса LetsRestService, который был представлен в подразделе 6.1 и уже не раз подвергался модификации в подразделе 6.2.

Реализация операций типа CRUD на основе протокола HTTP должна удовлетворять требованиям спецификаций этого протокола.

Спецификации протокола HTTP определяют какие коды состояния требуется возвращать сервером потребителю сервиса при успешном и других вариантах ответов. В нашем случае, это касается методов GET, POST, PUT и DELETE.

Методы GET возврашают клиенту любую информацию в виде объекта или списка объектов, на которую указывает запрошенный URI. Во всех этих случаях метод GET должен возвращать код: 200 Хорошо.

Метод POST используется для создания нового ресурса, идентифицируемого URI-запроса. Сервер должен принимать в качестве ресурса сохраняемый объект, а в ответ должны возвращаться коды:

1)код 201 — Создано с URI нового ресурса, если метод создал ресурс, а в качестве тела должен возвратиться URI созданного ресурса;

2)код 204 — Нет содержимого, если метод не создал ресурса, который можно было бы идентифицировать по URI.

Метод DELETE требует, чтобы сервер удалил ресурс, на который указывает содержащийся в запросе URI. Сервер должен возвращать один из трех вариантов ответа:

1)код 200 — Хорошо, если в ответе содержится объект;

2)код 202 — Принято, если действие пока не запущено;

3)код 204 — Нет содержимого, если действие было запущено, но в ответе отсутствует объект.

267

Метод PUT ссылается на уже существующий ресурс, который необходимо обновить. Если обновляется существующий ресурс, то должен быть возвращен один из следующих кодов состояния:

1)код 200 — Хорошо, если в ответе возвращается модифицированный объект;

2)код 204 — Нет содержимого, если в ответе модифицированный объект отсутствует.

Коды состояния протокола HTTP не характеризуют полностью прикладной результат выполненного запроса.

Все приведенные выше коды состояния считаются успешным выполнением запроса клиента. Обратите внимание, что в реальных сложных приложениях сам сервис передает конечную реализацию другим объектам, например, EJBкомпонентам, которые реализуют запрос на более низких уровнях. Кроме того, запросы клиента сначала обрабатываются контейнерами Web-сервисов и могут сами генерировать ответы без участия RESTful-компоненты сервиса.

Чтобы устранить все возможные неопределенности, при реализации учебного сервиса LetsRestService, будем предполагать, что:

1)все запросы и ответы сервиса реализуются в виде представления XML;

2)положительный прикладной ответ должен содержать тело объекта;

3)негативный прикладной ответ не содержит тело объекта.

Более точно алгоритм класса LetsRestService, показан на листинге 6.11.

Листинг 6.11 — Полная реализация класса LetsRestService.java проекта lab9

package rsos.lab9; import java.net.URI; import java.util.Date; import java.util.List; import javax.ejb.EJB;

import javax.ejb.Stateless; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces;

import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo;

268

/**

*Аннотации, определяющие сервлет типа RESTful, который

*доступен по адресу: http://localhost:8080/lab9.

*Формат представления данных - XML.

*/ @Path("/") @Stateless

public class LetsRestService

{

//Инъекция EJB-компоненты @EJB

Lets9 lets;

//Инъекция объекта контекста @Context

UriInfo uriInfo;

//Простой тест

/**

*Простейшая демонстрация доступа по методу GET, доступная

*по адресу: http://localhost:8080/lab9/test

*/

@GET @Path("/test")

@Produces(MediaType.TEXT_PLAIN) public String testRS()

{

if(lets == null)

System.out.println("Объект типа Lets9 - не существует!");

else

System.out.println("Объект типа Lets9 - подключен!");

return "Проверка технологии JAX-RS";

}

// Получение списка записей /**

*Доступ по методу GET, читающий весь список записе, при

*обращении по адресу: http://localhost:8080/lab9/letter.

*Всегда возвращает код 200 - Хорошо.

*/

@GET @Path("/letter")

public Response getLets()

{

return Response

.ok(new ListLets(lets.getList()), MediaType.APPLICATION_XML)

.build();

}

// Получение записи по идентификатору id /**

*Доступ по методу GET, читающий только одну запись, при

*обращении по адресу: http://localhost:8080/lab9/letter/{id}

*Должен использоваться один параметр типа int.

*Возвращает код 200, если объект найден, иначе возвращает

*код 204 - Нет содержимого.

*/

269

@GET

@Path("/letter/{id : \\d+}")

public Response getLetter(@PathParam("id") int id)

{

Letter l =

lets.getLetter(id); if(l == null)

return Response // код 204

.noContent().build();

return Response // код 200

.ok(l, MediaType.APPLICATION_XML)

.build();

}

// Добавление новой записи /**

*Демонстрация метода POST, добавляющего одну запись, при

*обращении по адресу: http://localhost:8080/lab9/letter

*Должен получать объект типа Letter и сохранять его данные:

*date и text.

*После сохранения объекта в базе данных, необходимо прочитать

*весь список объектов.

*Первый объект в списке должен быть новым созданным, тогда

*возвращаем код 201 - Создано с URI Нового ресурса и сам адрес

*ресурса, иначе - только код 204 - Нет содержимого.

*/

@POST @Path("/letter")

@Consumes(MediaType.APPLICATION_XML) public Response addLetter(Letter let)

{

// Сохраняем данные запроса Date date = let.getDate(); String text = let.getText();

lets.addLetter(let);

// Сохраняем новый объект

List<Letter> ls =

 

lets.getList();

// Поучаем список всех объектов

if(ls.isEmpty())

 

return Response

// код 204

.noContent().build();

Letter l =

 

ls.get(0);

// Получаем первый элемент списка

if(date != l.getDate() || !text.equals(l.getText()))

return Response

// код 204

.noContent().build();

// Создаем объект адреса нового ресурса String tt =

"/letter/" + new Integer(l.getId()).toString(); URI uri = UriBuilder

.fromResource(LetsRestService.class)

.path(tt).build();

return // код 201 - Создан с URI нового ресурса Response.created(uri).build();

}

270

// Удаление записи по идентификатору id /**

*Доступ по методу DELETE, удаляющий конкретную запись, при

*обращении по адресу: http://localhost:8080/lab9/letter/{id}

*Сначала запись читается и, если она отсутствует, то возвращается

*код 204 - Нет содержимого.

*Полученная запись сохраняется и удаляется из базы данных.

*В результате, возвращается запись и код 200 - Хорошо.

*/

@DELETE

@Path("/letter/{id : \\d+}") @Produces(MediaType.APPLICATION_XML)

public Response deleteLetter(@PathParam("id") int id)

{

Letter let = lets.getLetter(id);

if(let == null)

 

return Response

// код 204

.noContent().build();

// Удаляем запись

 

lets.deleteLetter(id);

 

return Response

// код 200

.ok(let, MediaType.APPLICATION_XML)

.build();

}

// Модификация записи по содержимому объекта /**

*Демонстрация метода PUT, изменяющего одну запись, при

*обращении по адресу: http://localhost:8080/lab9/letter

*Должен получать объект типа Letter.

*После изменения объекта методом lets.modLetter(...), необходимо

*прочитать измененный объект по его идентификатору id.

*Если объект прочитан, то возвращаем его с кодом 200 - Хорошо,

*иначе возвращаем код 204 - Нет содержимого.

*/

@PUT @Path("/letter")

@Consumes(MediaType.APPLICATION_XML) public Response modLetter(Letter let)

{

if(let == null)

//

Проверяем аргумент

return Response

//

код 204

.noContent().build();

// Модифицируем запись lets.modLetter(let);

Letter lx =

lets.getLetter(let.getId());

if(lx == null)

 

 

 

return Response

//

код

204

.noContent().build();

return Response

//

код

200

.ok(lx, MediaType.APPLICATION_XML)

271