Jersey 1.0은 JAX-RS, 즉 RESTful 웹 서비스용 자바 API(JSR-311)의 즉시 운영 가능한 오픈 소스 참조 구현입니다. Jersey를 사용하면 자바 기술을 이용해 RESTful 웹 서비스를 쉽게 만들 수 있습니다.
이전의 테크팁, 자바로 RESTful 웹 서비스 구현(Implementing RESTful Web Services in Java)에서 RESTful 웹 서비스, JAX-RS 및 Jersey를 다룬 바 있습니다. 또한 이 팁에서는자바 기술을 사용하여 JAX-RS 사양을 준수하는 RESTful 웹 서비스를 작성하는 방법도 소개했습니다. 또 다른 팁, Jersey 1.0에서 RESTful 웹 서비스를 위한 JSON 구성(Configuring JSON for RESTful Web Services in Jersey 1.0)에서는 Jersey 1.0을 사용하여 JSON(JavaScript Object Notation)에서 데이터를 구성하는 방법을 설명했습니다.
이번 팁에서는 Jersey 1.0.2 클라이언트 API를 사용하여 HTTP 기반 RESTful 웹 서비스를 이용하는 방법을 알아 보겠습니다. Jersey 1.0.2 클라이언트 API는 사용하기 편리한 고급 자바 기술 API로서 HTTP 기반 RESTful 웹 서비스용 클라이언트를 작성하는 데 도움이 됩니다. 이 API는 REST의 핵심 원칙 중 하나인 단일 인터페이스(uniform interface) 개념을 기반으로 합니다. 이 단일 인터페이스 개념은 REST 기반 애플리케이션이 어떤 URI에 액세스하든 상관없이 그 URI와의 인터페이스는 동일해야 한다는 것입니다.
Jersey 클라이언트 API의 기초
Jersey 클라이언트 API를 사용하려면 com.sun.jersey.api.client.Client 클래스의 인스턴스를 생성해야 합니다. 가장 간단한 방법은 다음과 같습니다.
import com.sun.jersey.api.client.Client;
Client client = Client.create();
Client 클래스는 RESTful 웹 서비스 클라이언트를 빌드하기 위한 기본 구성 지점입니다. 이 클래스를 사용하여 다양한 클라이언트 등록 정보와 기능을 구성하고 어떤 리소스 공급자를 사용할 것인지 나타냅니다. Client 인스턴스 작성은 비용이 많이 드는 작업이므로, 불필요한 클라이언트 인스턴스를 작성하지 않도록 하십시오. 가능하다면 기존 인스턴스를 다시 사용하는 것도 좋은 방법입니다.
Client 인스턴스를 작성했으면 사용할 수 있습니다. 그러나 요청을 보내려면 클라이언트를 위한 웹 리소스를 캡슐화하는 WebResource 개체를 만들어야 합니다. 예를 들어, 다음 코드를 통해 URI가 http://example.com/base인 웹 리소스를 위한 WebResource 개체를 만들 수 있습니다.
http://example.com/base");
import com.sun.jersey.api.client.WebResource;
WebResource webResource = client.resource("
WebResource 개체를 사용하여 웹 리소스에 보낼 요청을 빌드하고 웹 리소스에서 반환된 응답을 처리합니다. 예를 들어, WebResource 개체를 HTTP GET, PUT, POST 및 DELETE 요청에 사용할 수 있습니다.
GET 요청: WebResource 클래스의 get() 메소드를 사용하여 웹 리소스에 HTTP GET 요청을 보냅니다.
String s = webResource.get(String.class);
이는 WebResource 개체의 URI가 http://example.com/base인 경우 URI이 http://example.com/base인 리소스로 HTTP GET 요청이 보내진다는 의미입니다. 명령줄 HTTP 도구인 curl에 익숙하다면 다음이
String s = webResource.get(String.class);
다음 curl 명령에 해당한다는 사실을 알 수 있습니다.
http://example.com/base
curl
get() 요청에서 쿼리 매개 변수를 지정할 수 있습니다. 예를 들어, 다음 코드에서는 get() 요청에서 두 개의 쿼리 매개 변수를 지정합니다.
MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("param1", "val1");
queryParams.add("param2", "val2");
String s = webResource.queryParams(queryParams).get(String.class);
이는 다음 curl 명령에 해당합니다.
http://example.com/base?param1=val1¶m2=val2
curl
또한 응답에 허용되는 MIME 유형도 지정할 수 있습니다. 예를 들어, 다음 코드에서는 허용되는 MIME 유형의 텍스트를 지정합니다.
String s = webResource.accept("text/plain").get(String.class);
이는 다음 curl 명령에 해당합니다.
http://example.com/base
curl -HAccept:text/plain
또한 해당 요청의 HTTP 상태 코드를 가져올 수 있습니다. 예를 들어, 다음은 텍스트 엔터티와 상태 코드를 반환하는 요청입니다.
ClientResponse response = webResource.accept("text/plain").get(ClientResponse.class);
int status = response.getStatus();
String textEntity = response.getEntity(String.class); 개체는 클라이언트에서 HTTP 응답을 나타냅니다.
ClientResponse
PUT 요청: WebResource 클래스의 put() 메소드를 사용하여 웹 리소스에 HTTP PUT 요청을 보냅니다. 예를 들어, 다음 요청은 텍스트 엔터티 foo:bar를 웹 리소스에 추가합니다.
ClientResponse response = webResource.type("text/plain").put(ClientResponse.class, "foo:bar");
이는 다음 curl 명령에 해당합니다.
curl -XPUT -HContent-type:text/plain --data "foo:bar" http://example.com/base 요청에서 쿼리 매개 변수를 지정할 수도 있습니다. 그 방법은
put()get() 요청의 쿼리 매개 변수를 지정하는 것과 비슷합니다. 다음 예제에서는 이전의 get() 메소드 예제에 쓰인 동일한 쿼리 매개 변수가 put() 요청에서도 지정됩니다.
MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("param1", "val1");
queryParams.add("param2", "val2");
ClientResponse response = webResource.queryParams(queryParams).put(ClientResponse.class, "foo:bar");
이는 다음 curl 명령에 해당합니다.
http://example.com/base?param1=val1¶m2=val2
curl -XPUT -HContent-type:text/plain --data "foo:bar"
POST 요청: POST 요청은 GET 요청과 PUT 요청의 구문 조합입니다. 즉, POST 요청을 사용하여 웹 리소스에 엔터티를 보내고 다른 엔터티를 받을 수 있습니다. WebResource 클래스의 post() 메소드를 사용하여 웹 리소스에 HTTP POST 요청을 보냅니다. 예를 들어, 다음 코드에서는 쿼리 매개 변수 및 URL 인코딩된 양식 데이터와 함께 POST 요청을 보냅니다.
MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("name1", "val1");
formData.add("name2", "val2");
ClientResponse response = webResource.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);
이는 다음 curl 명령에 해당합니다.
http://example.com/base
curl -d name1=val1 -d name2=val2
DELETE 요청: WebResource 클래스의 delete() 메소드를 사용하여 웹 리소스에 HTTP DELETE 요청을 보냅니다. 예를 들어, 다음 요청을 통해 URI가 http://example.com/base/user/123인 리소스를 삭제합니다.
ClientResponse response = webResource.path("user/123").delete(ClientResponse.class);
이는 다음 curl 명령에 해당합니다.
http://example.com/base/user/123
curl -XDELETE
모든 HTTP 요청 메소드에서도 사용 가능한 WebResource.path() 메소드를 이용하면 요청된 웹 리소스의 추가 경로를 지정할 수 있습니다. 또 다른 WebResource 메소드인 header()를 사용하면 HTTP 헤더를 요청에 추가할 수 있습니다.
Jersey 클라이언트 구성
요청을 보내기 전에 클라이언트 구성이 필요할 수 있습니다. 이때 공급자 등록을 해야 할 수 있습니다. 또한 필터 추가 옵션도 있습니다. 가능한 모든 옵션에 대한 개요는 Jersey 1.0.2 클라이언트 API에서 확인하십시오.
공급자 등록: JAX-RS에서 공급자(provider)는 JAX-RS 확장의 구현입니다. 공급자 클래스는 @Provider 주석으로 표시합니다. Jersey 서버는 공급자를 위한 인프라를 제공합니다. JAX-RS 구현 시 Jersey에는 표준 공급자 클래스가 있습니다. Jersey 클라이언트 API에서는 Jersey 서버와 동일한 공급자 인프라를 다시 사용합니다. 하지만 클라이언트 측에서 어떤 자동 클래스 경로 검사도 이루어지지 않으므로 모든 비표준 공급자는 명시적으로 등록해야 합니다.
공급자를 등록하려면 그 공급자 클래스를 Client 인스턴스의 ClientConfig 개체에 추가해야 합니다. ClientConfig 클래스는 Client 개체에서 사용할 수 있는 공통적인 등록 정보 이름, 기능, 등록 정보, 공급자 클래스 및 단일 공급자 인스턴스를 선언합니다. 예를 들어, 다음 코드에서는 Client 개체에서 사용하기 위한 JSON 공급자 클래스를 등록합니다.
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(JSONRootElementProvider.class);
Client client = Client.create(config);
DefaultClientConfig 클래스를 사용한다는 점을 눈여겨 보십시오. 이 클래스는 기본 클라이언트 구성을 선언합니다.
필터 추가: 클라이언트를 구성할 때 클라이언트 인스턴스에 필터를 추가하는 옵션도 사용할 수 있습니다. 필터는 리소스 클래스를 대상으로 하는 요청과 응답을 동적으로 인터셉트하며, 그 요청이나 응답을 수정하는 데 사용할 수 있습니다. Jersey 클라이언트 API에서는 필터를 구현하는 수많은 클래스를 제공합니다. 그 중 하나가 로깅 필터를 구현하는 LoggingFilter입니다. 로깅 필터를 사용하면 클라이언트와 서버 애플리케이션 간의 통신을 추적할 수 있는데, 이는 디버깅에 유용할 수 있습니다. 다음은 클라이언트에 로깅 필터를 추가하는 방법입니다.
import com.sun.jersey.api.client.filter.LoggingFilter
client.addFilter(new LoggingFilter());
Jersey 기반 클라이언트 예제
Jersey 클라이언트 API를 사용하여 인기 있는 Twitter 웹 서비스에 액세스하는 애플리케이션 예제가 이 팁과 함께 제공됩니다. 이 예제에서는 Jersey 클라이언트 API에서 실제 HTTP 기반 웹 서비스를 사용할 수 있음을 보여 줍니다. 애플리케이션 예제는 Twitter 클라이언트 ZIP 아카이브 형태로 다운로드할 수 있습니다. 아카이브를 확장하면 클라이언트의 소스 코드를 검사할 수 있습니다. 또한 실행 가능한 Twitter 클라이언트 JAR 파일을 다운로드하여 애플리케이션을 테스트하고 그 작동 방식을 확인할 수 있습니다. 애플리케이션을 실행하려면 Java SE Runtime Environment (JRE) 6가 필요합니다.
Twitter: Twitter는 친구, 동료, 가족을 비롯한 다른 사람들과 간단한 문자 메시지를 주고 받을 수 있는 서비스입니다. 이 메시지들은 "What are you doing?"이라는 질문에 답하는 메시지입니다. 다음은 Twitter에 표시되는 메시지의 예입니다.
Twitter 메시지
또한 Twitter에서는 공용 Twitter API도 제공하는데, Twitter 메시지를 프로그래밍 방식으로 작성하거나 사용하고 서비스의 다른 요소에 액세스할 때 이 API를 사용할 수 있습니다. Twitter API를 사용할 경우 고려해야 할 사항 중 하나는 Twitter의 인증/보안 메커니즘과 요구 사항입니다.
Twitter 인증과 보안: Twitter에서는 기본 HTTP 인증 스키마를 사용합니다. 즉, API를 통해 Twitter에 액세스할 경우 특수한 Authorization 헤더를 요청에 추가해야 합니다. 그런 다음 SSL(Secure Sockets Layer)을 사용하여 통신 보안을 구현해야 할 것입니다. 간단하게 다음 코드로 해결할 수 있습니다.
ClientConfig config = new DefaultClientConfig();
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, myTrustManager, null);
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hostnameVerifier, ctx));
Client client = Client.create(config);
클라이언트 검사: Twitter 클라이언트 ZIP 아카이브를 다운로드하고 확장합니다. src\main\java\com\sun\jersey\techtips\twitter 디렉토리의 TwitterClient 클래스를 탐색합니다. 이는 Jersey 기반의 애플리케이션용 클라이언트입니다.
TwitterClient 클래스의 소스 코드를 검사할 때 특히 다음 사항에 유의하십시오. -Client 및 WebResource 개체를 만드는 코드:
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
private static final String BaseURI = "https://twitter.com";
private final WebResource wr;
Client client = Client.create(config);
wr = client.resource(BaseURI);
-클라이언트를 구성하는 코드:
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(hv, ctx));
config.getClasses().add(JAXBContextResolver.class);
-GET 요청을 보내는 코드:
public List<StatusBean> getFriendsTimelineJson() {
return wr.path("statuses/friends_timeline.json")
.header(AUTHENTICATION_HEADER, authentication)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(new GenericType<List<StatusBean>>() {
});
}
요청에 Authentication 헤더가 추가되는 점에 유의하십시오.
애플리케이션 예제 실행
애플리케이션 예제를 실행하려면 다음과 같이 하십시오.
1.JRE 6가 설치되지 않은 경우 다운로드하여 설치합니다.
2.Twitter 클라이언트 JAR 파일을 다운로드합니다.
3.명령줄에서 다음 명령을 실행합니다.
java -jar jersey-twitter-client-1.0-SNAPSHOT-jar-with-dependencies.jar
그러면 Twitter 사용자 이름과 암호를 입력하라는 메시지가 나타납니다. 지시대로 하면 타임스탬프와 함께 Twitter 메시지가 나타납니다. 다음은 그 예입니다.
http://jersey.dev.java.net) based twitter client
Simple Jersey (
Twitter username:mytwitter
Password:
Hello mytwitter!
Status will get updated every 60 secs.
Enter !exit to finish the session.
Arun Gupta (1238705837), at: Mon Feb 23 00:04:40 +0000 2009:
#slumdog is a favorite ... have not seen the movie yet but would be great if it
's the first Indian movie to win ... fingers crossed!
LarryLary (1238103969), at: Mon Feb 23 00:07:33 +0000 2009:
Gonna go for a walk. Need some fresh air.
kmollo (1239025876), at: Mon Feb 23 01:43:34 +0000 2009:
enjoying everyone's '15 Albums That Changed Your Life' lists. I have been so
bored, it's nice to have some 'new' music to check out!
iFab @fauntleroy (1239103887), at: Mon Feb 23 02:02:20 +0000 2009:
It's a beautiful day
JessicaxG (1239248068), at: Mon Feb 23 02:36:34 +0000 2009:
Shop. Shop. Shop. Another way to avoid things I need to do.
DoughJoe (1239571723), at: Mon Feb 23 03:55:39 +0000 2009:
Slumdog grabs it all
> Congratulations to Kate Winslet on her best actress Oscar.
Posted at: Tue Feb 24 16:54:17 +0000 2009
>!exit
bye
클라이언트에서 직접 메시지를 입력할 수도 있습니다.
추가 자료
Jersey에 대한 자세한 내용은 다음 자료를 참조하십시오.
Jersey 1.0.2 클라이언트 API
Jersey 프로젝트
Jersey 1.0에서 RESTful 웹 서비스를 위한 JSON 구성
자바로 RESTful 웹 서비스 구현
저자 정보
Jakub Podlesak은 Jersey 프로젝트 팀원으로 활동 중입니다. 그는 WS-Policy 팀원으로 GlassFish 웹 서비스 스택인 Metro의 개발에 참여하기도 했습니다. 그의 블로그를 둘러보십시오.
이 글의 영문 원본은
Consuming RESTful Web Services With the Jersey Client API
에서 보실 수 있습니다.
"Java EE" 카테고리의 다른 글
- JAX-WS 핸들러 구성, 패키징, 배치하기 (댓글 2개 / 트랙백 0개) 2006/10/19
- Enterprise Bean에서 보안 주석 사용하기 (댓글 4개 / 트랙백 0개) 2007/05/28
- 엔터프라이즈용 Java Application Verification Kit, 2부 (댓글 1개 / 트랙백 0개) 2005/10/05
- Java Persistence를 최상으로 구현하는 방법 (댓글 12개 / 트랙백 0개) 2007/07/23
- SAAJ 소개 (댓글 1개 / 트랙백 0개) 2005/06/08
- 커스텀 ELResolver를 이용하여 통합 EL 확장하기 (댓글 4개 / 트랙백 0개) 2006/10/19
- JAX-WS를 이용한 웹 서비스 개발 (댓글 1개 / 트랙백 0개) 2006/01/18
- JAXR (JAVA API FOR XML REGISTRIES) (댓글 1개 / 트랙백 0개) 2005/05/18
- GlassFish에서 호출 흐름 모니터링하기 (댓글 3개 / 트랙백 0개) 2006/06/16
- Groovy, Grails, MySQL 및 Java Persistence API의 조합 (댓글 0개 / 트랙백 0개) 2008/08/20
댓글을 달아 주세요