Java에서 Relay 하이브리드 연결 HTTP 요청 시작
이 빠른 시작에서는 HTTP 프로토콜을 사용하여 메시지를 보내고 받는 Java 발신자 및 수신자 애플리케이션을 만듭니다. 애플리케이션은 Azure Relay 하이브리드 연결 기능을 사용합니다. Azure Relay에 대한 일반적인 내용은 Azure Relay를 참조하세요.
이 빠른 시작에서 수행하는 단계는 다음과 같습니다.
- Azure Portal을 사용하여 Relay 네임스페이스를 만듭니다.
- Azure Portal을 사용하여 해당 네임스페이스에 하이브리드 연결을 만듭니다.
- 메시지를 수신하는 서버(수신기) 콘솔 애플리케이션을 작성합니다.
- 메시지를 보내는 클라이언트(발신자) 콘솔 애플리케이션을 작성합니다.
- 애플리케이션을 실행합니다.
필수 조건
- Java. JDK 1.8 이상을 실행 중인지 확인
- Maven Maven이 설치되어 있는지 확인
- Azure Relay SDK. Java SDK 검토
- Azure 구독 구독이 없으면 시작하기 전에 계정을 만드세요.
Azure Portal을 사용하여 네임스페이스 만들기
Azure Portal에 로그인합니다.
왼쪽 메뉴에서 모든 서비스를 선택합니다. 통합을 선택하고 릴레이를 검색한 다음, 릴레이 위로 마우스 커서를 이동하여 만들기를 선택합니다.
네임스페이스 만들기 페이지에서 다음 단계를 수행합니다.
네임스페이스를 만들 Azure 구독을 선택합니다.
리소스 그룹의 경우 네임스페이스를 배치할 기존 리소스 그룹을 선택하거나 새 리소스 그룹을 만듭니다.
릴레이 네임스페이스의 이름을 입력합니다.
네임스페이스를 호스팅해야 하는 지역을 선택합니다.
페이지 아래쪽에서 검토 + 만들기를 선택합니다.
리뷰 + 생성 페이지에서 생성를 선택합니다.
몇 분 후에 네임스페이스에 대한 릴레이 페이지가 표시됩니다.
관리 자격 증명 가져오기
릴레이 페이지의 왼쪽 메뉴에서 공유 액세스 정책을 선택합니다.
공유 액세스 정책 페이지에서 RootManageSharedAccessKey를 선택합니다.
정책: RootManageSharedAccessKey 아래에서 기본 연결 문자열 옆에 있는 복사 단추를 선택합니다. 이 작업은 나중에 사용할 연결 문자열을 클립보드에 복사합니다. 메모장이나 기타 다른 위치에 임시로 이 값을 붙여 넣습니다.
앞의 단계를 반복하여 나중에 사용할 기본 키의 값을 복사하여 임시 위치에 붙여넣습니다.
Azure Portal을 사용하여 하이브리드 연결 만들기
네임스페이스의 릴레이 페이지에서 다음 단계에 따라 하이브리드 연결을 만듭니다.
왼쪽 메뉴의 엔터티에서 하이브리드 연결을 선택한 다음, + 하이브리드 연결을 선택합니다.
하이브리드 연결 만들기 페이지에서 하이브리드 연결 이름을 입력하고 만들기를 선택합니다.
서버 애플리케이션(수신기) 만들기
릴레이에서 메시지를 수신하고 받으려면 Java 콘솔 애플리케이션을 작성합니다.
Java 애플리케이션 만들기
릴레이를 만들 때 [클라이언트 인증 필요] 옵션을 사용하지 않도록 설정한 경우 임의 브라우저로 요청을 하이브리드 연결 URL에 보낼 수 있습니다. 보호된 엔드포인트에 액세스하기 위해서는 여기 표시된 ServiceBusAuthorization
헤더에 토큰을 만들고 전달해야 합니다.
다음은 Azure Relay 라이브러리를 활용하는 클라이언트 권한 부여를 사용하여 하이브리드 연결 URL로 요청을 보내는 방법을 보여 주는 간단한 Maven 프로젝트 구조 및 Java 클래스입니다.
릴레이 패키지 추가
Azure Relay 패키지를 포함하도록 Maven 애플리케이션 패키지의 pom.xml 파일을 수정합니다.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-relay</artifactId>
<version>0.0.6</version>
</dependency>
mvn 프로젝트에서 mvn dependency:copy-dependencies -DoutputDirectory=lib
을(를) 실행하여 프로젝트의 라이브러리 디렉터리에 종속성 jar 파일을 추가합니다. azure-relay
mvn 패키지의 모든 종속성을 가져옵니다. 이 패키지는 Relay URI(Uniform Resource Identifier) 및 토큰을 구성하는 함수를 제공합니다.
메시지를 보내는 코드 작성
종속성 jar 파일을
Listener.java
파일의 ClassPath에 추가합니다.javac -cp lib/* src/main/java/com/example/listener/Listener.Java
종속성을
Listener.java
클래스로 가져옵니다.import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; import java.util.Scanner; import com.microsoft.azure.relay.HybridConnectionListener; import com.microsoft.azure.relay.RelayConnectionStringBuilder; import com.microsoft.azure.relay.RelayedHttpListenerResponse; import com.microsoft.azure.relay.TokenProvider;
하이브리드 연결 세부 정보를 위해
createConnectionString
java 함수에 대한Listener.java
파일의 맨 위에 다음constants
을(를) 추가합니다.public static String createConnectionString(){ StringBuilder connectionString = new StringBuilder(); connectionString.append("Endpoint=sb://"); connectionString.append("{namespace}"); connectionString.append(".servicebus.windows.net/;SharedAccessKeyName="); connectionString.append("{keyrule}"); connectionString.append(";SharedAccessKey="); connectionString.append("{key}"); connectionString.append(";EntityPath="); connectionString.append("{path}"); return connectionString.toString(); }
대괄호 안의 자리 표시자를 하이브리드 연결을 만들 때 얻은 값으로 바꿉니다.
namespace
- 릴레이 네임스페이스 정규화된 네임스페이스 이름을 사용해야 합니다. 예:{namespace}.servicebus.windows.net
path
- 하이브리드 연결의 이름keyrule
- 공유 액세스 정책 키의 이름(기본적으로RootManageSharedAccessKey
)입니다.nst key
- 이전에 저장한 네임스페이스의 기본 키입니다.
Listener.java
파일에 다음 코드를 추가합니다. main 함수는 다음 코드와 같아야 합니다.public static void main( String[] args ) throws URISyntaxException { String CONNECTION_STRING_ENV_VARIABLE_NAME = createConnectionString(); RelayConnectionStringBuilder connectionParams = new RelayConnectionStringBuilder(CONNECTION_STRING_ENV_VARIABLE_NAME); TokenProvider tokenProvider = TokenProvider.createSharedAccessSignatureTokenProvider( connectionParams.getSharedAccessKeyName(), connectionParams.getSharedAccessKey()); HybridConnectionListener listener = new HybridConnectionListener(new URI(connectionParams.getEndpoint().toString() + connectionParams.getEntityPath()), tokenProvider); // The "context" object encapsulates both the incoming request and the outgoing response listener.setRequestHandler((context) -> { String receivedText = ""; if (context.getRequest().getInputStream() != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(context.getRequest().getInputStream(), "UTF8"))) { StringBuilder builder = new StringBuilder(); String inputLine; while ((inputLine = reader.readLine()) != null) { builder.append(inputLine); } receivedText = builder.toString(); } catch (IOException e) { System.out.println(e.getMessage()); } } System.out.println("requestHandler received " + receivedText); RelayedHttpListenerResponse response = context.getResponse(); response.setStatusCode(202); response.setStatusDescription("OK"); try { response.getOutputStream().write(("Echo: " + receivedText).getBytes()); } catch (IOException e) { e.printStackTrace(); } // The context MUST be closed for the message to be sent response.close(); }); listener.openAsync().join(); Scanner in = new Scanner(System.in); System.out.println("Press ENTER to terminate this program."); in.nextLine(); listener.close(); in.close(); }
Listener.java
파일은 다음과 같습니다.package com.example.listener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; import java.util.Scanner; import com.microsoft.azure.relay.HybridConnectionListener; import com.microsoft.azure.relay.RelayConnectionStringBuilder; import com.microsoft.azure.relay.RelayedHttpListenerResponse; import com.microsoft.azure.relay.TokenProvider; public class Listener { public static String createConnectionString(){ StringBuilder connectionString = new StringBuilder(); connectionString.append("Endpoint=sb://"); connectionString.append("{namespace}"); connectionString.append(".servicebus.windows.net/;SharedAccessKeyName="); connectionString.append("{keyrule}"); connectionString.append(";SharedAccessKey="); connectionString.append("{key}"); connectionString.append(";EntityPath="); connectionString.append("{path}"); return connectionString.toString(); } public static void main( String[] args ) throws URISyntaxException { String CONNECTION_STRING_ENV_VARIABLE_NAME = createConnectionString(); RelayConnectionStringBuilder connectionParams = new RelayConnectionStringBuilder(CONNECTION_STRING_ENV_VARIABLE_NAME); TokenProvider tokenProvider = TokenProvider.createSharedAccessSignatureTokenProvider( connectionParams.getSharedAccessKeyName(), connectionParams.getSharedAccessKey()); HybridConnectionListener listener = new HybridConnectionListener(new URI(connectionParams.getEndpoint().toString() + connectionParams.getEntityPath()), tokenProvider); // The "context" object encapsulates both the incoming request and the outgoing response listener.setRequestHandler((context) -> { String receivedText = ""; if (context.getRequest().getInputStream() != null) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(context.getRequest().getInputStream(), "UTF8"))) { StringBuilder builder = new StringBuilder(); String inputLine; while ((inputLine = reader.readLine()) != null) { builder.append(inputLine); } receivedText = builder.toString(); } catch (IOException e) { System.out.println(e.getMessage()); } } System.out.println("requestHandler received " + receivedText); RelayedHttpListenerResponse response = context.getResponse(); response.setStatusCode(202); response.setStatusDescription("OK"); try { response.getOutputStream().write(("Echo: " + receivedText).getBytes()); } catch (IOException e) { e.printStackTrace(); } // The context MUST be closed for the message to be sent response.close(); }); listener.openAsync().join(); Scanner in = new Scanner(System.in); System.out.println("Press ENTER to terminate this program."); in.nextLine(); listener.close(); in.close(); } }
클라이언트 애플리케이션(보낸 사람) 만들기
Relay에 메시지를 보내려면 HTTP 클라이언트를 사용하거나 Java 콘솔 애플리케이션을 작성합니다.
Java 애플리케이션 만들기
릴레이를 만들 때 [클라이언트 인증 필요] 옵션을 사용하지 않도록 설정한 경우 임의 브라우저로 요청을 하이브리드 연결 URL에 보낼 수 있습니다. 보호된 엔드포인트에 액세스하기 위해서는 여기 표시된 ServiceBusAuthorization
헤더에 토큰을 만들고 전달해야 합니다.
다음은 Azure Relay 라이브러리를 활용하는 클라이언트 권한 부여를 사용하여 하이브리드 연결 URL로 요청을 보내는 방법을 보여 주는 간단한 Maven 프로젝트 구조 및 Java 클래스입니다.
릴레이 패키지 추가
Azure Relay 패키지를 포함하도록 Maven 애플리케이션 패키지의 pom.xml 파일을 수정합니다.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-relay</artifactId>
<version>0.0.6</version>
</dependency>
mvn 프로젝트에서 mvn dependency:copy-dependencies -DoutputDirectory=lib
을(를) 실행하여 프로젝트의 라이브러리 디렉터리에 종속성 jar 파일을 추가합니다. 또한 azure-relay
mvn 패키지의 모든 종속성을 가져옵니다. 이 패키지는 Relay URI(Uniform Resource Identifier) 및 토큰을 구성하는 함수를 제공합니다.
메시지를 보내는 코드 작성
종속성 jar 파일을
Sender.java
파일의 ClassPath에 추가합니다.javac -cp lib/* src/main/java/com/example/sender/Sender.Java
종속성을
Sender.java
클래스로 가져옵니다.import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.util.Scanner; import com.microsoft.azure.relay.RelayConnectionStringBuilder; import com.microsoft.azure.relay.TokenProvider;
하이브리드 연결 세부 정보를 위해
createConnectionString
java 함수에 대한Sender.java
파일의 맨 위에 다음constants
을(를) 추가합니다.public static String createConnectionString(){ StringBuilder connectionString = new StringBuilder(); connectionString.append("Endpoint=sb://"); connectionString.append("{namespace}"); connectionString.append(".servicebus.windows.net/;SharedAccessKeyName="); connectionString.append("{keyrule}"); connectionString.append(";SharedAccessKey="); connectionString.append("{key}"); connectionString.append(";EntityPath="); connectionString.append("{path}"); return connectionString.toString(); }
대괄호 안의 자리 표시자를 하이브리드 연결을 만들 때 얻은 값으로 바꿉니다.
namespace
- 릴레이 네임스페이스 정규화된 네임스페이스 이름을 사용해야 합니다. 예:{namespace}.servicebus.windows.net
path
- 하이브리드 연결의 이름keyrule
- 공유 액세스 정책 키의 이름(기본적으로RootManageSharedAccessKey
)입니다.nst key
- 이전에 저장한 네임스페이스의 기본 키입니다.
Sender.java
파일에 다음 코드를 추가합니다. main 함수는 다음 코드와 같아야 합니다.public static void main(String[] args) throws IOException { String CONNECTION_STRING_ENV_VARIABLE_NAME = createConnectionString(); if (CONNECTION_STRING_ENV_VARIABLE_NAME == null || CONNECTION_STRING_ENV_VARIABLE_NAME.isEmpty()){ System.err.println("Connection string is null or empty. Please check your createConnectionString method."); return; } RelayConnectionStringBuilder connectionParams = new RelayConnectionStringBuilder(CONNECTION_STRING_ENV_VARIABLE_NAME); TokenProvider tokenProvider = TokenProvider.createSharedAccessSignatureTokenProvider( connectionParams.getSharedAccessKeyName(), connectionParams.getSharedAccessKey()); URL url = buildHttpConnectionURL(connectionParams.getEndpoint().toString(), connectionParams.getEntityPath()); String tokenString = tokenProvider.getTokenAsync(url.toString(), Duration.ofHours(1)).join().getToken(); Scanner in = new Scanner(System.in); while (true) { System.out.println("Press ENTER to terminate this program."); String message = in.nextLine(); int value = System.in.read(); if (value == '\n' || value == '\r') { System.out.println("Terminating the program..."); break;} // Starting a HTTP connection to the listener HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Sending an HTTP request to the listener // To send a message body, use POST conn.setRequestMethod((message == null || message.length() == 0) ? "GET" : "POST"); conn.setRequestProperty("ServiceBusAuthorization", tokenString); conn.setDoOutput(true); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); out.write(message, 0, message.length()); out.flush(); out.close(); // Reading the HTTP response String inputLine; BufferedReader reader = null; StringBuilder responseBuilder = new StringBuilder(); try { InputStream inputStream = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println("status code: " + conn.getResponseCode()); while ((inputLine = reader.readLine()) != null) { responseBuilder.append(inputLine); } System.out.println("received back " + responseBuilder.toString()); } catch (IOException e) { System.out.println("The listener is offline or could not be reached."); break; } finally { if (reader != null) { reader.close(); } } } in.close(); } static URL buildHttpConnectionURL(String endpoint, String entity) throws MalformedURLException { StringBuilder urlBuilder = new StringBuilder(endpoint + entity); // For HTTP connections, the scheme must be https:// int schemeIndex = urlBuilder.indexOf("://"); if (schemeIndex < 0) { throw new IllegalArgumentException("Invalid scheme from the given endpoint."); } urlBuilder.replace(0, schemeIndex, "https"); return new URL(urlBuilder.toString()); }
Sender.java
파일은 다음과 같습니다.package com.example.sender; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; import java.util.Scanner; import com.microsoft.azure.relay.RelayConnectionStringBuilder; import com.microsoft.azure.relay.TokenProvider; public class Sender { public static String createConnectionString(){ StringBuilder connectionString = new StringBuilder(); connectionString.append("Endpoint=sb://"); connectionString.append("{namespace}"); connectionString.append(".servicebus.windows.net/;SharedAccessKeyName="); connectionString.append("{keyrule}"); connectionString.append(";SharedAccessKey="); connectionString.append("{key}"); connectionString.append(";EntityPath="); connectionString.append("{path}"); return connectionString.toString(); } public static void main(String[] args) throws IOException { String CONNECTION_STRING_ENV_VARIABLE_NAME = createConnectionString(); if (CONNECTION_STRING_ENV_VARIABLE_NAME == null || CONNECTION_STRING_ENV_VARIABLE_NAME.isEmpty()){ System.err.println("Connection string is null or empty. Please check your createConnectionString method."); return; } RelayConnectionStringBuilder connectionParams = new RelayConnectionStringBuilder(CONNECTION_STRING_ENV_VARIABLE_NAME); TokenProvider tokenProvider = TokenProvider.createSharedAccessSignatureTokenProvider( connectionParams.getSharedAccessKeyName(), connectionParams.getSharedAccessKey()); URL url = buildHttpConnectionURL(connectionParams.getEndpoint().toString(), connectionParams.getEntityPath()); String tokenString = tokenProvider.getTokenAsync(url.toString(), Duration.ofHours(1)).join().getToken(); Scanner in = new Scanner(System.in); while (true) { System.out.println("Press ENTER to terminate this program."); String message = in.nextLine(); int value = System.in.read(); if (value == '\n' || value == '\r') { System.out.println("Terminating the program..."); break;} // Starting a HTTP connection to the listener HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Sending an HTTP request to the listener // To send a message body, use POST conn.setRequestMethod((message == null || message.length() == 0) ? "GET" : "POST"); conn.setRequestProperty("ServiceBusAuthorization", tokenString); conn.setDoOutput(true); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream()); out.write(message, 0, message.length()); out.flush(); out.close(); // Reading the HTTP response String inputLine; BufferedReader reader = null; StringBuilder responseBuilder = new StringBuilder(); try { InputStream inputStream = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println("status code: " + conn.getResponseCode()); while ((inputLine = reader.readLine()) != null) { responseBuilder.append(inputLine); } System.out.println("received back " + responseBuilder.toString()); } catch (IOException e) { System.out.println("The listener is offline or could not be reached."); break; } finally { if (reader != null) { reader.close(); } } } in.close(); } static URL buildHttpConnectionURL(String endpoint, String entity) throws MalformedURLException { StringBuilder urlBuilder = new StringBuilder(endpoint + entity); // For HTTP connections, the scheme must be https:// int schemeIndex = urlBuilder.indexOf("://"); if (schemeIndex < 0) { throw new IllegalArgumentException("Invalid scheme from the given endpoint."); } urlBuilder.replace(0, schemeIndex, "https"); return new URL(urlBuilder.toString()); } }
참고 항목
이 문서의 샘플 코드는 연결 문자열 사용하여 Azure Relay 네임스페이스에 인증하여 자습서를 단순하게 유지합니다. 더 쉽게 손상될 수 있는 연결 문자열 또는 공유 액세스 서명을 사용하는 대신 프로덕션 환경에서 Microsoft Entra ID 인증을 사용하는 것이 좋습니다. Microsoft Entra ID 인증을 사용하는 방법에 대한 자세한 정보 및 샘플 코드는 Azure Relay 엔터티에 액세스하고 Microsoft Entra ID를 사용하여 관리 ID를 인증하여 Azure Relay 리소스에 액세스하기 위해 Microsoft Entra ID로 애플리케이션 인증 및 권한을 부여합니다.
애플리케이션 실행
- Java 명령 프롬프트 형식
java -cp <jar_dependency_path> com.example.listener.Listener.java
의 서버 애플리케이션을 실행합니다. - Java 명령 프롬프트 형식
java -cp <jar_dependency_path> com.example.sender.Sender.java
의 클라이언트 애플리케이션을 실행하고 일부 텍스트를 입력합니다. - 서버 애플리케이션 콘솔이 클라이언트 애플리케이션에 입력된 텍스트를 출력하는지 확인합니다.
축하합니다. Java를 사용하여 엔드투엔드 하이브리드 연결 애플리케이션을 만들었습니다.
다음 단계
이 빠른 시작에서는 메시지를 보내고 받는 데 HTTP를 사용한Java 클라이언트 및 서버 애플리케이션을 만들었습니다. Azure Relay의 하이브리드 연결 기능은 또한 WebSockets를 사용하여 메시지를 보내고 받을 수 있도록 지원합니다. Azure Relay 하이브리드 연결에 WebSockets를 사용하는 방법에 대한 자세한 내용은 WebSockets 빠른 시작을 참조하세요.
이 빠른 시작에서는 클라이언트 및 서버 애플리케이션을 만드는 데 Java를 사용했습니다. .NET Framework를 사용하여 클라이언트 및 서버 애플리케이션을 작성하는 방법은 .NET WebSockets 빠른 시작 또는 .NET HTTP 빠른 시작을 참조하세요.