1. 소개
이전 기사에서는 JAX -RS 2.0 의 RESTEasy 서버 측 구현에 중점을 두었습니다 .
JAX-RS 2.0 은 원격 RESTful 웹 서비스에 대한 HTTP 요청을 작성할 수 있도록 새로운 클라이언트 API를 도입합니다. Jersey, Apache CXF, Restlet 및 RESTEasy는 가장 널리 사용되는 구현의 하위 집합일 뿐입니다.
이 기사에서는 RESTEasy API 로 요청을 전송 하여 REST API 를 사용하는 방법을 살펴보겠습니다 .
2. 프로젝트 설정
pom.xml 에 다음 의존성 을 추가합니다 .
<properties>
<resteasy.version>4.7.2.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
...
</dependencies>
3. 클라이언트 측 코드
클라이언트 구현은 매우 작으며 3개의 주요 클래스로 구성됩니다.
-
- 고객
- 웹타깃
- 응답
클라이언트 인터페이스는 WebTarget 인스턴스 의 빌더입니다.
WebTarget 은 더 많은 하위 리소스 WebTarget을 구축하거나 요청을 호출할 수 있는 고유한 URL 또는 URL 템플릿을 나타냅니다.
클라이언트를 만드는 방법에는 실제로 두 가지가 있습니다.
- 표준 방식은 org.jboss.resteasy.client.ClientRequest 를 사용하는 것입니다.
- RESTeasy 프록시 프레임워크 : ResteasyClientBuilder 클래스 사용
여기서는 RESTEasy 프록시 프레임워크에 중점을 둘 것입니다.
들어오는 요청을 RESTFul 웹 서비스 메서드에 매핑하기 위해 JAX-RS 어노테이션을 사용하는 대신 클라이언트 프레임워크는 원격 RESTful 웹 서비스에서 호출하는 데 사용하는 HTTP 요청을 빌드합니다.
이제 Java 인터페이스 작성을 시작하고 메소드와 인터페이스에서 JAX-RS 어노테이션을 사용해 봅시다.
3.1. 서비스 클라이언트 인터페이스
@Path("/movies")
public interface ServicesInterface {
@GET
@Path("/getinfo")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Movie movieByImdbId(@QueryParam("imdbId") String imdbId);
@POST
@Path("/addmovie")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Response addMovie(Movie movie);
@PUT
@Path("/updatemovie")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
Response updateMovie(Movie movie);
@DELETE
@Path("/deletemovie")
Response deleteMovie(@QueryParam("imdbId") String imdbId);
}
3.2. 영화 수업
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "movie", propOrder = { "imdbId", "title" })
public class Movie {
protected String imdbId;
protected String title;
// getters and setters
}
3.3. 요청 생성
이제 API를 사용하는 데 사용할 수 있는 프록시 클라이언트를 생성합니다.
String transformerImdbId = "tt0418279";
Movie transformerMovie = new Movie("tt0418279", "Transformer 2");
UriBuilder FULL_PATH = UriBuilder.fromPath("http://127.0.0.1:8082/resteasy/rest");
ResteasyClient client = (ResteasyClient)ClientBuilder.newClient();
ResteasyWebTarget target = client.target(FULL_PATH);
ServicesInterface proxy = target.proxy(ServicesInterface.class);
// POST
Response moviesResponse = proxy.addMovie(transformerMovie);
System.out.println("HTTP code: " + moviesResponse.getStatus());
moviesResponse.close();
// GET
Movie movies = proxy.movieByImdbId(transformerImdbId);
// PUT
transformerMovie.setTitle("Transformer 4");
moviesResponse = proxy.updateMovie(transformerMovie);
moviesResponse.close();
// DELETE
moviesResponse = proxy.deleteMovie(batmanMovie.getImdbId());
moviesResponse.close();
RESTEasy 클라이언트 API는 Apache HttpClient 를 기반으로 합니다 .
또한 각 작업 후에 새 작업을 수행하기 전에 응답을 닫아야 합니다. 이는 기본적으로 클라이언트에 사용 가능한 단일 HTTP 연결만 있기 때문에 필요합니다.
마지막으로 DTO와 직접 작업하는 방법에 주목하십시오. JSON 또는 XML 에 대한 마샬링/언마샬링 로직을 처리하지 않습니다 . 이는 Movie 클래스에 적절하게 어노테이션이 추가 되었기 때문에 JAXB 또는 Jackson 을 사용하여 장면 뒤에서 발생합니다 .
3.4. 연결 풀을 사용한 요청 생성
이전 예제의 한 가지 참고 사항은 단일 연결만 사용할 수 있다는 것입니다. 예를 들어, 우리는 다음을 시도합니다.
Response batmanResponse = proxy.addMovie(batmanMovie);
Response transformerResponse = proxy.addMovie(transformerMovie);
batmanResponse 에서 close() 를 호출하지 않고 – 두 번째 줄이 실행될 때 예외가 발생합니다.
java.lang.IllegalStateException:
Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
다시 말하지만 이는 RESTEasy에서 사용 하는 기본 HttpClient 가 org.apache.http.impl.conn.SingleClientConnManager 이기 때문에 발생합니다 . 물론 단일 연결만 사용할 수 있습니다.
이제 이러한 제한을 해결하려면 RestEasyClient 인스턴스를 다르게 생성해야 합니다(연결 풀 포함).
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
cm.setMaxTotal(200); // Increase max total connection to 200
cm.setDefaultMaxPerRoute(20); // Increase default max connection per route to 20
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
ResteasyClient client = ((ResteasyClientBuilder) ClientBuilder.newBuilder()).httpEngine(engine).build();
ResteasyWebTarget target = client.target(FULL_PATH);
ServicesInterface proxy = target.proxy(ServicesInterface.class);
이제 적절한 연결 풀의 이점을 누릴 수 있으며 매번 연결을 해제하지 않고도 클라이언트를 통해 여러 요청을 실행할 수 있습니다.
4. 결론
이 빠른 사용방법(예제)에서는 RESTEasy 프록시 프레임워크 를 소개하고 이를 사용하여 매우 간단한 클라이언트 API를 구축했습니다.
프레임워크는 클라이언트를 구성하기 위한 몇 가지 헬퍼 메서드를 더 제공하며 JAX-RS 서버 측 사양과 반대되는 미러로 정의할 수 있습니다.
이 문서에 사용된 예제는 GitHub 에서 샘플 프로젝트 로 제공됩니다 .