Java2012.03.06 15:05
Java에서 Rest API로 가장 많이 사용하는 것은 Apache CXF이다. CXF는 Server모듈을 만들수 있고, 쉽게 client 프로그래밍을 할 수 있다. 그런데 Java가 아닌 다른 언어로 제공되는 Rest를 사용할 경우, 다른 서버의 url을 바로 호출할 경우 사용 할수 있는 것이 바로  HttpClient이다.

HttpClient 객체에는 HttpGet, HttpHead, HttpPost, HttpPut, HttpDelete가 있는데, 이 메소드들은 Android에서도 많이 사용되고 있는 통신 방법이다. 어떻게 보면 CXF Restful과도 같아 보인다.

- HttpGet : 데이터를 조회할 때 주로 사용한다.
- HttpHead : 조회하고자 하는 데이터의 메타데이터나 인증정보, 혹은 세션값을 확인 할 때 사용한다.
- HttpPost : 데이터의 메타데이터 등을 수정할 때 사용한다.
- HttpPut : 새로운 데이터를 생성할 때 사용한다.
- HttpDelete : 데이터 삭제시 사용하는 메소드이다.
 
그럼 이제 OpenStack Swift Client Java API 예제와 함께 자주 사용하는 HttpClient 메소드들을 알아보도록 하자.

** 아래 예제 샘플은  http://wiki.openstack.org/SwiftAPI 에 가면 다운로드 받을 수 있다.




HttpGet 

/**
 로그인된 Account의 Container 리스트를 조회하는 메소드로 HttpGet을 사용하였다.
*/

public List<FilesContainer> listContainers(int limit, String marker) throws IOException, HttpException, FilesException

{
        //로그인이 되었는지를 체크한다. 

if (!this.isLoggedin()) {

    throw new FilesAuthorizationException("You must be logged in", null, null);

}

HttpGet method = null;

try {

LinkedList<NameValuePair> parameters = new LinkedList<NameValuePair>();

    if(limit > 0) {
                        //파라메터로 받은 limit를 추가한다. 

parameters.add(new BasicNameValuePair("limit", String.valueOf(limit)));

}

    if(marker != null) {
                        //파라메터로 받은 marker를 추가한다.  

parameters.add(new BasicNameValuePair("marker", marker));

}

    //위에서 생성한 parameters는 URI를 생성할때 사용이 된다.

    String uri = parameters.size() > 0 ? makeURI(storageURL, parameters) : storageURL;
                //위에서 선언한 HttpGet 객체를 생성한다.

method = new HttpGet(uri);

method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);
                //헤더에 인증 Token를 추가한다.  

method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);
                
                //여기서 사용되는 FilesResponse는  HttpClient로 실행한 결과값을 담아놓는 HttpResponse로 보                    면 된다.

FilesResponse response = new FilesResponse(client.execute(method));

    if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {

//상태코드가 401로 인증되지 않았을 경우 

}

if (response.getStatusCode() == HttpStatus.SC_OK)

{

//상태코드가 200으로 성공했을 경우

}

else if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT)

{

//상태코드 204 로 새로운 정보가 없을 경우

}

else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND)

{

//상태코드가 404 Not Found가 나왔을 경우

}

else {

//응답코드가 없을 경우

}

}

catch (Exception ex) {

ex.printStackTrace();

throw new FilesException("Unexpected error, probably parsing Server XML", ex);

}

finally {

if (method != null) method.abort();

}

} 


HttpHead

 /**
 로그인된 Account의 MetaData 정보를 조회할 때 HttpHead를 사용하였다.
*/ 
public FilesAccountInfo getAccountInfo() throws IOException, HttpException, FilesAuthorizationException, FilesException

{
        //로그인이 되었을 경우에만 아래 프로세스를 수행한다. 

if (this.isLoggedin()) {

HttpHead method = null;


try {

method = new HttpHead(storageURL);

method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);
                        //해당 storageURL의 MetaData를 조회한다.

FilesResponse response = new FilesResponse(client.execute(method));
 

if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
                                //401 인증이 되지 않았을경우 Header를 삭제하고 다시 로그인을 한다.

method.removeHeaders(FilesConstants.X_AUTH_TOKEN);

if(login()) {

method.abort();

method = new HttpHead(storageURL);

method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);
                                        //다시 해당 storageURL의 MetaData를 조회한다. 

response = new FilesResponse(client.execute(method));

}

else {
                                        //인증이 되지 않으면 오류처리한다. 

throw new FilesAuthorizationException("Re-login failed", response.getResponseHeaders(), response.getStatusLine());

}

}

                        // 기존 정보와 변동이 없으면 기존 정보를 조회하여 리턴한다. 

if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT)

{

int nContainers = response.getAccountContainerCount();

long totalSize  = response.getAccountBytesUsed();

return new FilesAccountInfo(totalSize,nContainers);

}

else {

throw new FilesException("Unexpected return from server", response.getResponseHeaders(), response.getStatusLine());

}

}

finally {

if (method != null) method.abort();

}

}

else {

    throw new FilesAuthorizationException("You must be logged in", null, null);

}

}


HttpPost

 /**
 Object Metadata 정보를 수정할 때 HttpPost를 사용한다.
*/  
public boolean updateObjectMetadataAndManifest(String container, String object, 

Map<String,String> metadata, String manifest) throws FilesAuthorizationException, 

HttpException, IOException, FilesInvalidNameException {

        FilesResponse response;

        //로그인이 되어 있는지 체크한다.

if (!isLoggedin) {

    throw new FilesAuthorizationException("You must be logged in", 

    null, null);

}
        //수정될 Container가 있는지 체크한다. 

if (!isValidContainerName(container))

throw new FilesInvalidNameException(container);     
 
       //수정될 Object가 있는지 체크한다.

if (!isValidObjectName(object))

           throw new FilesInvalidNameException(object);


//Post 될 Url를 생성한다.

String postUrl = storageURL + "/"+FilesClient.sanitizeForURI(container) +

"/"+FilesClient.sanitizeForURI(object);

HttpPost method = null;

try {

          method = new HttpPost(postUrl);

        if (manifest != null){

        method.setHeader(FilesConstants.MANIFEST_HEADER, manifest);

        }

  method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

  method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);
                //HttpPost에 파라메터, 헤더, metadata값을 추가한다. 

  if (!(metadata == null || metadata.isEmpty())) {

  for(String key:metadata.keySet())

  method.setHeader(FilesConstants.X_OBJECT_META+key, 

  FilesClient.sanitizeForURI(metadata.get(key)));

  }
                //HttpPost를 HttpClient로 실행한다. 

HttpResponse resp = client.execute(method);

response = new FilesResponse(resp);

if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
                        //인증이 되지 않았으면 처음부터 다시 실행한다. 

method.abort(); 

if(login()) {

method = new HttpPost(postUrl);

  method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

  method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);

  if (!(metadata == null || metadata.isEmpty())) {

  for(String key:metadata.keySet())

  method.setHeader(FilesConstants.X_OBJECT_META+key, 

  FilesClient.sanitizeForURI(metadata.get(key)));

  }

    client.execute(method);

}

}

return true;

} finally {

if (method != null) 

method.abort();

}

}


HttpPut

 /**
 Container를 생성할 때 HttpPut 메소드를 사용한다.
*/   
public void createContainer(String name) throws IOException, HttpException, FilesAuthorizationException, FilesException

{
        //우선 로그인이 되었는지 먼저 체크한다. 

if (this.isLoggedin())

{
                //생성가능한 container명인지 체크한다. 

if (isValidContainerName(name))

{
                        //해당 storageUrl로 container 생성을 요청할 준비를 한다.

HttpPut method = new HttpPut(storageURL+"/"+sanitizeForURI(name));

method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);

try {
                                // 준비된 요청을 실행한다.

FilesResponse response = new FilesResponse(client.execute(method));    

              if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {

              // 402 인증이 안되었을 경우

            }


          if (response.getStatusCode() == HttpStatus.SC_CREATED)

         {
                                        //  201 Container 생성 성공

          return;

         }

         else if (response.getStatusCode() == HttpStatus.SC_ACCEPTED)

         {

         // 202 이미 Container가 있을 경우

         }

         else {

        // 기타는 에러로 간주

         }

}

finally {

method.abort();

}

}

else

{

throw new FilesInvalidNameException(name);

}

}

else {

    throw new FilesAuthorizationException("You must be logged in", null, null);

}

}



HttpDelete

  /**
 Container를 삭제할 때 HttpDelete 메소드를 사용한다.
*/  
public boolean deleteContainer(String name) throws IOException, HttpException, FilesAuthorizationException, FilesInvalidNameException, FilesNotFoundException, FilesContainerNotEmptyException

{
        //로그인이 되었는지 체크한다. 

if (this.isLoggedin())

{
                //삭제 가능한 Container명인지 체크한다. 

if (isValidContainerName(name))

{
                        // 해당 storageURL로 container를 삭제할 준비를 한다. 

HttpDelete method = new HttpDelete(storageURL+"/"+sanitizeForURI(name));

try {

method.getParams().setIntParameter("http.socket.timeout", connectionTimeOut);

  method.setHeader(FilesConstants.X_AUTH_TOKEN, authToken);
                                // 준비된 요청을 실행한다.

        FilesResponse response = new FilesResponse(client.execute(method));


          if (response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {

        // 402 인증이 안되었을 경우 

        }


          if (response.getStatusCode() == HttpStatus.SC_NO_CONTENT)

       {

       // container가 삭제되었다.

         return true;

       }

       else if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND)

       {
                           //삭제 할 container가 없을 경우 

       logger.debug ("Container does not exist !");

       

       }

       else if (response.getStatusCode() == HttpStatus.SC_CONFLICT)

       {
                           //삭제 할 container가 empty가 아닐 경우 에러를 발생한다.

       logger.debug ("Container is not empty, can not delete a none empty container !");

       }

}

finally {

method.abort();

}

}

else

{

        throw new FilesInvalidNameException(name);

}

}

else

{

    throw new FilesAuthorizationException("You must be logged in", null, null);

}

return false;

}


 
Posted by 나리 짱!!! naleejang