Java2014. 10. 26. 16:28
반응형

 최근 서버/클라이언트 어플리케이션 개발을 진행하다 보면 스마트폰, 태블릿 등 다양한 클라이언트가 생김으로서 이기종간의 호환성 유지를 위해 클라이언트에서 서버로의 요청을 json을 이용하여 개발하는 경우가 있다. 이 경우 서버 시스템 테스트를 위해서 클라이언트측 요청을 별도로 구현해야 하는 경우가 있다. 이때 apache재단의 오픈소스를 이용하여 간단하게 구현할 수 있다. 


 먼저 필요한 라이브러리를 추가할 필요가 있다.(현 시점의 안정화 최신버전 리스트)

  • Apache HttpClient (httpclient-4.3.5.jar)
  • HttpComponents Core (httpcore-4.3.2.jar)
  • Apache HttpClient Mime (httpmime-4.3.5.jar)


위의 라이브러리를 추가할 필요가 있으며 의존관계로 commons-logging, commons-codec 라이브러리도 필요하다. MAVEN을 이용하여 간단하게 의존라이브러리를 추가하는게 편할 듯하다.


httpclient 추가

    
        org.apache.httpcomponents
        httpclient
        4.3.5
    

httpmime 추가

    
        org.apache.httpcomponents
        httpmime
        4.3.5
    

위의 두개의 의존 라이브러리를 추가하면 나머지는 의존 관계에 따라서 자동으로 추가된다.


먼저 application/json 타입의 요청을 하기 위한 간단한 소스코드는 아래와 같다. 요청을 생성하고 JSON문자열을 문자열 엔티티로 추가한후 컨텐츠 타입 헤더를 application/json으로 지정했다.

		try {
			RequestConfig.Builder requestBuilder = RequestConfig.custom();
			HttpClientBuilder builder = HttpClientBuilder.create();
			builder.setDefaultRequestConfig(requestBuilder.build());
			HttpClient client = builder.build();

			String requestJson = "{\"test\":\"test\"}";
			StringEntity stringEntity = new StringEntity(requestJson);

			HttpPost httpost = new HttpPost(new URI("요청할URL"));
			httpost.addHeader("Content-Type", "application/json");

			httpost.setEntity(stringEntity);

			client.execute(httpost);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

  다음으로 json데이터와 함께 파일도 업로드 하여야 할 경우 multipart/mixed 타입으로 컨텐츠 타입을 지정해서 요청하면 된다. 아래 소스코드를 살펴보자.

	
		try {
			RequestConfig.Builder requestBuilder = RequestConfig.custom();
			HttpClientBuilder builder = HttpClientBuilder.create();
			builder.setDefaultRequestConfig(requestBuilder.build());
			HttpClient client = builder.build();

			String requestJson = "요청할 json데이터 문자열";

			HttpPost httpost = new HttpPost(new URI("요청할 URI"));
			httpost.addHeader("Content-Type", "multipart/mixed; boundary=바운더리 문자열");
			MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();

			entityBuilder.addPart("jsonpart", new StringBody(requestJson, ContentType.APPLICATION_JSON));
			entityBuilder.setBoundary("위의 헤더에 지정한 바운더리 문자열");
			entityBuilder.addPart("file1", new FileBody(new File("파일경로"), ContentType.create("파일타입"), "파일명"));
			httpost.setEntity(entityBuilder.build());
			HttpResponse response = client.execute(httpost);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}


 Java계열의 서블릿 컨테이너를 이용중이라면 multipart요청은 서블릿 스펙3.0(톰캣의 경우 7이상)을 지원하는 컨테이너에서 처리 가능하다. 위의 소스코드상에서 바운더리 문자열을 지정했는데 Content-Type헤더를 위처럼 별도 지정하지 않았을 경우 multipart/form-data로 지정되면 바운더리도 자동으로 지정되므로 크게 신경스지 않아도 될듯하다. 톰캣이나 스프링의 멀티파트 리졸버 상에는 multipart/로 시작되는 Content-Type헤더를 가진 요청은 동일하게 처리하는듯하니 상황에 따라 지정해서 구현하면 될듯하고 별도로 지정하는 경우는 org.apache.http.entity.mime.MultipartEntityBuilder#generateBoundary의 구현을 참조하여 바운더리를 지정하면 되겠다.



※바운더리란 간단히 요약하면 여러 조각(Part)의 요청을 보낼경우 경계를 구분하기 위한 문자열로 '--바운더리 문자열'로 각 조각을 경계지으면 최종적으로 '--바운더리 문자열--'로 최종경계가 표현된다.


'Java' 카테고리의 다른 글

apache httpclient 요청 디버깅  (0) 2014.11.27
Java8 Base64 Encoder/Decoder  (0) 2014.11.19
Apache Commons Codec Base64 Encoding/Decoding  (0) 2014.11.17
Eclipse java Access restriction rt.jar  (0) 2013.12.04
Java7 zip 파일 압축  (0) 2013.11.26
Posted by Reiphiel