Статьи

Отдых с использованием Джерси — полное руководство с JAXB, обработкой исключений и клиентской программой

Недавно я начал работать над проектом веб-сервиса Restful, используя Jersey API . В Интернете есть несколько учебных пособий, но я столкнулся с некоторыми проблемами при обработке исключений, и я не нашел нигде законченного проекта, использующего JaxB и обеспечивающего подход к обработке исключений. Поэтому, когда мне удалось создать веб-сервис Restful с использованием API-интерфейса Jersey с обработкой исключений и клиентской программой, я решил написать это руководство, чтобы помочь каждому начать работу с Jersey.

Кто должен использовать этот учебник

Это руководство предназначено для Java-программистов, которые заинтересованы в разработке и развертывании Restful Web Services с использованием Jersey API и JaxB.

Предпосылки

Целью данного руководства является использование API-интерфейса Jersey для создания веб-служб Restful и вызова веб-службы с помощью клиентской программы Java и тестирования веб-службы с помощью инструмента. Базовое понимание Java, веб-сервисов, XML, Maven и любого сервера приложений (JBoss / Tomcat) необходимо для легкого понимания учебника.

Программное обеспечение и инструменты, используемые

  • JDK версия 1.6.0_37
  • Apache Maven 3.0.3
  • Mac OS X 10.8.2
  • JBoss 4.2.2 (Вы можете использовать любой сервер приложений, например Tomcat, Glassfish и т. Д.)
  • Eclipse Indigo (любая Java IDE с поддержкой Maven)

Создание проекта Maven в Eclipse и Джерси

Создайте проект maven в Eclipse, и он предоставит вам базовую структуру проекта. Я дал GroupId как «JD» и artifactID как «my-jersey-project», но вы можете дать все, что захотите. Как только мы завершим разработку нашего проекта, он будет выглядеть как на картинке ниже.

Описание проекта веб-сервиса Джерси

pom.xml : детали конфигурации проекта, обратите внимание на предоставленные зависимости джерси, другие детали являются общими для любого проекта 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
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
  <modelVersion>4.0.0</modelVersion>
  <groupId>JD</groupId>
  <artifactId>my-jersey-project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.14</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.14</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.14</version>
        </dependency>
  </dependencies>
 
  <build>
        <finalName>${artifactId}-${version}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1-alpha-2</version>
                <configuration>
                    <packagingExcludes>
                        WEB-INF/lib/servlet-api-*.jar
                </packagingExcludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.0</version>
                <executions>
                    <execution>
                        <id>unpack</id>
                        <phase>install</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>${groupId}</groupId>
                                    <artifactId>${artifactId}</artifactId>
                                    <version>${version}</version>
                                    <type>${packaging}</type>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.directory}/${artifactId}-${version}-exploded.${packaging}</outputDirectory>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

EmpRequest.java : Java Bean для объекта запроса. Здесь важно отметить аннотацию @XmlRootElement для сопоставления класса с элементом 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
package com.jd.model;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name = 'empRequest')
public class EmpRequest {
    private int id;
    private String name;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

EmpResponse.java : Java-бин для объекта ответа.

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
package com.jd.model;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name = 'empResponse')
public class EmpResponse {
    private int id;
    private String name;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}

ErrorResponse.java : Java Bean, который будет отправлен как ответ в случае исключения.

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
package com.jd.model;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement(name = 'errorResponse')
public class ErrorResponse {
 
    private String errorCode;
    private int errorId;
 
    public String getErrorCode() {
        return errorCode;
    }
 
    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }
 
    public int getErrorId() {
        return errorId;
    }
 
    public void setErrorId(int errorId) {
        this.errorId = errorId;
    }
 
}

EmpNotFoundException.java : обычный класс исключений, создаваемый в веб-службе.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package com.jd.exception;
 
public class EmpNotFoundException extends Exception {
 
    private static final long serialVersionUID = 4351720088030656859L;
    private int errorId;
 
    public int getErrorId() {
        return errorId;
    }
 
    public EmpNotFoundException(String msg, int errorId) {
        super(msg);
        this.errorId = errorId;
    }
 
    public EmpNotFoundException(String msg, Throwable cause) {
        super(msg, cause);
    }
}

jboss-web.xml : для определения контекста сервлета JBoss для веб-службы.

1
2
3
<jboss-web>
   <context-root>jd</context-root>
</jboss-web>

web.xml : дескриптор развертывания для веб-службы. Поэтому любой запрос с URI «http: // <HOST>: <POST> / jd / rest / *» будет обрабатываться сервлетом Jersey ServletContainer. Важно отметить, что значение init-param передается для com.sun.jersey.config.property.packages. Это определяет, в каком пакете Джерси будет искать классы веб-сервисов. Это свойство должно указывать на ваши классы ресурсов. Он также ищет классы ресурсов в подпакетах.

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
<?xml version='1.0' encoding='UTF-8'?>
<web-app id='WebApp_ID' version='2.5'
    xsi:schemaLocation='http://java.sun.com/xml/ns/javaee
 
 
    <display-name>My Jersey Project</display-name>
 
    <!-- Jersey Servlet configurations -->
    <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.jd</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <!-- Jersey Servlet configurations -->
 
</web-app>

EmpRouter.java : класс ресурсов, обрабатывающий различные типы запросов.

  • @Path («/ emp») — все запросы с URI http: // <HOST>: <PORT> / jd / rest / emp / будут обрабатываться этим классом ресурсов.
  • @Path («/ getEmp») — все запросы с URI http: // <HOST>: <PORT> / jd / rest / emp / getEmp будут обрабатываться этим методом.
  • @POST — эта аннотация определяет, что используемый метод HTTP должен быть POST. Некоторые другие возможные значения: @GET, @PUT, @DELETE
  • @Consumes (MediaType.APPLICATION_XML) — метод принимает элемент XML
  • @Produces (MediaType.APPLICATION_XML) — метод возвращает элемент 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
package com.jd.router;
 
import com.jd.exception.EmpNotFoundException;
import com.jd.model.*;
 
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBElement;
 
@Path('/emp')
public class EmpRouter {
 
    @POST
    @Path('/getEmp')
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response getEmp(JAXBElement<EmpRequest> empRequest)
            throws EmpNotFoundException {
        EmpResponse empResponse = new EmpResponse();
        if (empRequest.getValue().getId() == 1) {
            empResponse.setId(empRequest.getValue().getId());
            empResponse.setName(empRequest.getValue().getName());
        } else {
            throw new EmpNotFoundException('Wrong ID', empRequest.getValue()
                    .getId());
        }
        return Response.ok(empResponse).build();
    }
}

EmpNotFoundExceptionMapper.java : класс сопоставления исключений, который сопоставляет EmpNotFoundException с объектом Response. Класс должен иметь аннотацию @Provider. Этот класс должен быть в пакете, предусмотренном для классов ресурсов в web.xml. Реализация метода toResponse () генерирует объект ErrorResponse и устанавливает его как объект в объекте ответа со статусом INTERNAL_SERVER_ERROR.

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
package com.jd.exceptionmapper;
 
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
 
import com.jd.exception.EmpNotFoundException;
import com.jd.model.ErrorResponse;
 
@Provider
public class EmpNotFoundExceptionMapper implements
        ExceptionMapper<EmpNotFoundException> {
 
    public EmpNotFoundExceptionMapper() {
    }
 
    public Response toResponse(
            EmpNotFoundException empNotFoundException) {
        ErrorResponse errorResponse = new ErrorResponse();
        errorResponse.setErrorId(empNotFoundException.getErrorId());
        errorResponse.setErrorCode(empNotFoundException.getMessage());
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
                errorResponse).type(
                MediaType.APPLICATION_XML).build();
 
    }
 
}

Наш веб-сервис готов, просто создайте его, чтобы создать файл WAR и развернуть его на сервере приложений.

EmpClient.java : это пример Java-программы, с помощью которой вызывается наш веб-сервис. Мы используем клиентский API-интерфейс jersey для вызова службы и, основываясь на состоянии ответа, анализируем сущность ответа в классе EmpResponse или ErrorResponse.

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
package com.jd.client;
 
import javax.ws.rs.core.MediaType;
 
import com.jd.model.EmpRequest;
import com.jd.model.EmpResponse;
import com.jd.model.ErrorResponse;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
 
public class EmpClient {
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        String uri = 'http://localhost:8080/jd/rest/emp/getEmp';
        EmpRequest request = new EmpRequest();
        //set id as 1 for OK response
        request.setId(2);
        request.setName('PK');
        try{
        Client client = Client.create();
        WebResource r=client.resource(uri);
        ClientResponse response = r.type(MediaType.APPLICATION_XML).post(ClientResponse.class,request );
        System.out.println(response.getStatus());
        if(response.getStatus() == 200){
            EmpResponse empResponse = response.getEntity(EmpResponse.class);
            System.out.println(empResponse.getId() + '::'+empResponse.getName());
        }else{
            ErrorResponse exc = response.getEntity(ErrorResponse.class);
            System.out.println(exc.getErrorCode());
            System.out.println(exc.getErrorId());
        }
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }
 
}

Я надеюсь, что учебник достаточно прост, чтобы следовать и написать свой первый веб-сервис Restful, используя Джерси.
Пожалуйста, дайте мне знать, если у вас возникнут какие-либо проблемы или вам нужны дальнейшие объяснения.

Ссылка: Отдых с использованием Джерси — полное руководство с JAXB, обработкой исключений и клиентской программой от нашего партнера JCG Панкаджа Кумара в блоге Developer Recipes .