Подход 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 здесь .

