Подход RESTful к разработке веб-сервисов постоянно привлекает все больше и больше внимания и, кажется, подталкивает SOAP к устареванию. Я не буду обсуждать, какой подход лучше, но я полагаю, что мы все согласны с тем, что REST намного легче. В этом руководстве я собираюсь показать вам, как разрабатывать RESTful-сервисы с помощью RESTeasy и как их развертывать на сервере Tomcat. На этом пути также создается проект Maven на основе Eclipse.
Недавно я хотел протестировать REST-клиент, который планировал использовать в создаваемом приложении, поэтому мне нужен был быстрый способ настройки инфраструктуры RESTful. Джастин написал классное руководство о том, как использовать Spring для предоставления сервисов RESTful . Однако я хотел чего-то быстрее и не связываться с Spring ни разу. По этой причине я решил пойти с JBoss RESTeasy . С официального сайта:
RESTEasy — это проект JBoss, который предоставляет различные среды, помогающие создавать веб-службы RESTful и приложения Java RESTful. Это полностью сертифицированная и портативная реализация спецификации JAX-RS . JAX-RS — это новая спецификация JCP, которая предоставляет Java API для веб-служб RESTful по протоколу HTTP.
RESTEasy может работать в любом контейнере сервлетов, но также доступна более тесная интеграция с сервером приложений JBoss, чтобы сделать работу пользователей в этой среде более приятной.
Последнюю версию RESTeasy можно найти здесь и соответствующую документацию здесь . На данный момент последней версией является 2.1.0.GA. Вам также, вероятно, понадобится RESTeasy JavaDoc и JAX-RS JavaDoc .
Поскольку использование JBoss AS отменило бы всю «легковесную» концепцию, я решил пойти с нашим старым другом Tomcat. Я скачал последнюю версию (7.0.5 бета) контейнера любимого сервлета отсюда. Обратите внимание, что в настоящее время он находится в бета-фазе, но Tomcat оказался очень надежным, и я думаю, никаких проблем не должно возникнуть.
Начнем с создания проекта Maven на основе Eclipse под названием «RESTeasyProject». Используемый архетип «webapp-jee5», как показано на следующем рисунке:
Для параметров мы используем «com.javacodegeeks» в качестве идентификатора группы и «resteasy» в качестве идентификатора артефакта.
Следующим шагом является добавление зависимостей RESTeasy в наш файл pom.xml. URL хранилища: http://repository.jboss.org/maven2/, но, к сожалению, последняя версия, представленная в этом хранилище, — 2.0-beta-2. В любом случае, строки, которые нам нужно добавить в файл maven:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
…<repositories> <repository> <id>org.jboss.resteasy</id> </repository></repositories>…<dependencies>…<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>2.0-beta-2</version></dependency><dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>2.0-beta-2</version></dependency><dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jettison-provider</artifactId> <version>2.0-beta-2</version></dependency>…</dependencies>… |
Артефакт resteasy-jaxrs относится к базовому классу RESTeasy для реализации JAX-RS. Кроме того, мы используем как resteasy-jaxb-provider, так и resteasy-jettison-provider, поскольку мы хотим поддерживать форматы ответов XML и JSON. Архитектура JAXB используется для сериализации XML, а среда Jettison — для написания JSON.
Вот полный pom.xml:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks</groupId> <artifactId>resteasy</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>resteasy JEE5 Webapp</name> <repositories> <repository> <id>org.jboss.resteasy</id> </repository> </repositories> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>2.0-beta-2</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxb-provider</artifactId> <version>2.0-beta-2</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jettison-provider</artifactId> <version>2.0-beta-2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> <finalName>resteasy</finalName> </build></project> |
Давайте сначала посмотрим класс модели, который будет использоваться в нашем сервисе:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package com.javacodegeeks.resteasy.model;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "employee")public class Employee { private String employeeId; private String employeeName; private String job; @XmlElement public String getEmployeeId() { return employeeId; } public void setEmployeeId(String employeeId) { this.employeeId = employeeId; } @XmlElement public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } @XmlElement public String getJob() { return job; } public void setJob(String job) { this.job = job; } } |
Типичный класс модели с некоторыми полями и соответствующими методами получения / установки. Аннотации JAXB используются для указания, какие поля будут сериализованы и с какими элементами они будут отображаться. Более конкретно, аннотация XmlRootElement используется для указания элемента класса верхнего уровня. Аналогично, методы получения помечаются XmlElement для сопоставления соответствующего свойства JavaBean с элементом XML. По умолчанию используется имя свойства, но мы можем переопределить его, указав произвольное имя .
Давайте создадим наш первый класс с поддержкой RESTeasy, который называется «SampleService».
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package com.javacodegeeks.resteasy;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import com.javacodegeeks.resteasy.model.Employee;@Path("/sampleservice")public class SampleService { private static Map<String, Employee> employees = new HashMap<String, Employee>(); static { Employee employee1 = new Employee(); employee1.setEmployeeId("1"); employee1.setEmployeeName("Fabrizio"); employee1.setJob("Software Engineer"); employees.put(employee1.getEmployeeId(), employee1); Employee employee2 = new Employee(); employee2.setEmployeeId("2"); employee2.setEmployeeName("Justin"); employee2.setJob("Business Analyst"); employees.put(employee2.getEmployeeId(), employee2); } @GET @Path("/hello") @Produces("text/plain") public String hello(){ return "Hello World"; } @GET @Path("/echo/{message}") @Produces("text/plain") public String echo(@PathParam("message")String message){ return message; } @GET @Path("/employees") @Produces("application/xml") public List<Employee> listEmployees(){ return new ArrayList<Employee>(employees.values()); } @GET @Path("/employee/{employeeid}") @Produces("application/xml") public Employee getEmployee(@PathParam("employeeid")String employeeId){ return employees.get(employeeId); } @GET @Path("/json/employees/") @Produces("application/json") public List<Employee> listEmployeesJSON(){ return new ArrayList<Employee>(employees.values()); } @GET @Path("/json/employee/{employeeid}") @Produces("application/json") public Employee getEmployeeJSON(@PathParam("employeeid")String employeeId){ return employees.get(employeeId); } } |
Как видите, наш сервис сильно аннотирован. Мы можем определить декларативно метод HTTP, на который отвечает каждый метод, например, GET или POST . Для URL, по которому обслуживаются ресурсы, мы используем PATH , как на уровне сервиса, так и на уровне метода. Если метод принимает параметр или попадает под определенный сегмент пути, это обозначается PathParam . Наконец, аннотация Consumes определяет типы мультимедиа, которые могут принимать методы ресурса, а Produces определяет типы, которые могут быть созданы.
Давайте рассмотрим еще несколько деталей. Мы храним некоторые фиктивные данные на статической карте, которая в реальном приложении будет заменена на DAO . Обратите внимание, что классы моделей будут сериализованы библиотекой как для представлений XML, так и для JSON. Давайте теперь посмотрим на открытые методы:
- привет : метод, который просто печатает предопределенную строку с типом содержимого text / plain.
- echo : этот метод возвращает любой предоставленный аргумент. Обратите внимание, что имя поля в скобках должно совпадать с именем параметра. Подобный тип контента с выше.
- listEmployees : этот метод предоставляет XML-представление списка объектов модели. Формат указывается аннотацией Productions.
- getEmployee : то же самое с предыдущим, но возвращает только один объект модели на основе аргумента ID.
- listEmployeesJSON : аналогично XML-аналогу, но созданный формат — JSON.
- getEmployeeJSON : то же самое с предыдущим, но возвращает только один объект модели на основе аргумента ID.
Затем мы должны соответствующим образом настроить файл web.xml наших веб-приложений, чтобы RESTeasy позаботился о входящих REST-запросах. В нашем проекте Maven это можно найти в каталоге «src / main / webapp / WEB-INF». Вот как выглядит наш файл декларации:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<?xml version="1.0" encoding="UTF-8"?> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>resteasy</display-name> <listener> <listener-class> org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap </listener-class> </listener> <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/restful-services/*</url-pattern> </servlet-mapping> <context-param> <param-name>resteasy.scan</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>resteasy.servlet.mapping.prefix</param-name> <param-value>/restful-services</param-value> </context-param> </web-app> |
Прослушиватель контекста ResteasyBootstrap необходимо развернуть, чтобы создать реестр для resteasy, а сервлет HttpServletDispatcher используется для правильной маршрутизации входящих запросов в соответствующие службы. Мы настроили конкретный сервлет с именем «Resteasy» для перехвата запросов по пути «/ restful-services / *». Нам нужно определить это для инфраструктуры RESTeasy с помощью параметра конфигурации resteasy.servlet.mapping.prefix. Обратите внимание, что значение не содержит ни косую черту, ни подстановочный знак. Наконец, мы используем переключатель resteasy.scan для автоматического сканирования файлов WEB-INF / lib jars и каталога WEB-INF / classes для различных аннотированных классов. Существует также ряд других переключателей конфигурации RESTeasy, которые вы можете использовать для точной настройки поведения вашего приложения.
Последний шаг — построить проект и развернуть его в контейнере сервлеров. Запустите конфигурацию Eclipse и выберите «Установка Maven». При условии, что все в порядке, будет создан веб-архив с именем «resteasy.war» в папке «target» вашего проекта. Разорванная папка также может быть найдена в том же каталоге. Скопируйте файл WAR в репозиторий приложений Tomcat, то есть в папку «apache-tomcat-7.0.5 \ webapps». Запустите сервер, если вы этого еще не сделали, и вы должны увидеть следующую строку в консоли:
Добавление отсканированного ресурса: com.javacodegeeks.resteasy.SampleService
Теперь, когда приложение развернуто, давайте проверим его. Обратите внимание, что, поскольку все методы обрабатывают запросы GET, тестирование можно выполнить, используя ваш любимый браузер и просто написав URL. Для ленивого разработчика вот они (в случаях XML и JSON я также добавляю публичную ссылку с ожидаемым результатом):
HTTP: // локальный: 8080 / Resteasy / успокоительная-услуга / sampleservice / привет
HTTP: // локальный: 8080 / Resteasy / успокоительные-услуги / sampleservice / эхо / сообщение
http: // localhost: 8080 / resteasy / restful-services / sampleservice / employee ( ссылка )
http: // localhost: 8080 / resteasy / restful-services / sampleservice / employee / 1 ( ссылка )
http: // localhost: 8080 / resteasy / restful-services / sampleservice / json / employee ( ссылка )
http: // localhost: 8080 / resteasy / restful-services / sampleservice / json / employee / 1 ( ссылка )
Обратите внимание, что полный путь состоит из контекста веб-приложения («resteasy»), контекста, который мы определили для обработки RESTeasy («restful-services»), пути службы («sampleservice») и, наконец, соответствующего пути метода.
Это было бы все. Как всегда, вы можете найти проект Eclipse здесь .

