

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 将 JMS 与 Amazon SQS 结合使用
<a name="sqs-java-message-service-jms-client"></a>

Amazon SQS Java Messaging Library 是适用于 Amazon SQS 的 Java Message Service (JMS) 接口，允许您在已经使用 JMS 的应用程序中利用 Amazon SQS。利用此接口，对代码稍作更改即可将 Amazon SQS 用作 JMS 提供程序。结合使用 适用于 Java 的 AWS SDK 与 Amazon SQS Java Messaging Library，您可以创建 JMS 连接和会话以及与 Amazon SQS 队列之间收发消息的创建者和使用者。

此库支持依据 [JMS 1.1 规范](http://docs.oracle.com/javaee/6/api/javax/jms/package-summary.html)的队列消息收发（JMS 点对点模式）；该库支持将文本、字节或对象消息同步发送到 Amazon SQS 队列。还支持同步或异步接收对象。

有关支持 JMS 1.1 规范的 Amazon SQS Java Messaging Library 特征的信息，请参阅[Amazon SQS 支持的 JMS 1.1 实现](supported-implementations.md)和 [Amazon SQS 常见问题](https://aws.amazon.com/sqs/faqs/)。

# 使用 JMS 和 Amazon SQS 的先决条件
<a name="prerequisites"></a>

在开始之前，您必须满足以下先决条件：
+ **适用于 Java 的 SDK**

  可通过两种不同的方式将适用于 Java 的 SDK 包含在项目中：
  + 下载并安装适用于 Java 的 SDK。
  + 使用 Maven 获取 Amazon SQS Java Messaging Library。
**注意**  
适用于 Java 的 SDK 作为一个依赖项包含在内。  
[适用于 Java 的 SDK](https://aws.amazon.com/sdkforjava/) 和适用于 Java 的 Amazon SQS 扩展型客户端库需要使用 J2SE Development Kit 8.0 或更高版本。

    有关下载适用于 Java 的 SDK 的信息，请参阅[适用于 Java 的 SDK](https://aws.amazon.com/sdkforjava/)。
+ **Amazon SQS Java Messaging Library** 

  如果未使用 Maven，则必须将 `amazon-sqs-java-messaging-lib.jar` 程序包添加到 Java 类路径中。有关下载该库的信息，请参阅 [Amazon SQS Java Messaging Library](https://github.com/awslabs/amazon-sqs-java-messaging-lib)。
**注意**  
Amazon SQS Java Messaging Library 包括对 [Maven](http://maven.apache.org/) 和 [Spring Framework](http://projects.spring.io/spring-framework/) 的支持。  
有关使用 Maven、Spring Framework 和 Amazon SQS Java Messaging Library 的代码示例，请参阅[实际可用的 Java 示例：将 JMS 与 Amazon SQS 标准队列相结合使用](sqs-jms-code-examples.md)。  

  ```
  <dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>amazon-sqs-java-messaging-lib</artifactId>
    <version>1.0.4</version>
    <type>jar</type>
  </dependency>
  ```
+ **Amazon SQS 队列**

  使用适用于 Amazon SQS 的 AWS 管理控制台、`CreateQueue` API 或 Amazon SQS Java Messaging Library 中包括的封装 Amazon SQS 客户端，创建队列。
  + 有关使用 AWS 管理控制台或 `CreateQueue` API 创建用于 Amazon SQS 的队列的信息，请参阅[创建队列](creating-sqs-standard-queues.md#step-create-standard-queue)。
  + 有关使用 Amazon SQS Java Messaging Library 的信息，请参阅[使用 Amazon SQS Java Messaging Library](getting-started.md)。

# 使用 Amazon SQS Java Messaging Library
<a name="getting-started"></a>

要开始结合使用 Java Message Service (JMS) 与 Amazon SQS，请使用本节中的代码示例。以下部分介绍如何创建 JMS 连接和会话以及如何发送和接收消息。

Amazon SQS Java Messaging Library 中包含了封装的 Amazon SQS 客户端对象，该对象会检查是否存在 Amazon SQS 队列。如果队列不存在，客户端将创建它。

## 创建 JMS 连接
<a name="creating-connection"></a>

在开始之前，请先查看[使用 JMS 和 Amazon SQS 的先决条件](prerequisites.md)中的先决条件。

1. 创建连接工厂并对该工厂调用 `createConnection` 方法。

   ```
   // Create a new connection factory with all defaults (credentials and region) set automatically
   SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
           new ProviderConfiguration(),
           AmazonSQSClientBuilder.defaultClient()
           );
    
   // Create the connection.
   SQSConnection connection = connectionFactory.createConnection();
   ```

   `SQSConnection` 类对 `javax.jms.Connection` 进行了扩展。除了 JMS 标准连接方法，`SQSConnection` 还提供其他一些方法，例如 `getAmazonSQSClient` 和 `getWrappedAmazonSQSClient`。这两种方法均可让您执行未包含在 JMS 规范中的管理操作，例如创建新队列。不过，`getWrappedAmazonSQSClient` 方法还提供当前连接使用的 Amazon SQS 客户端的封装版本。该包装程序将客户端中的每个异常转变为 `JMSException`，从而让预期有 `JMSException` 发生的现有代码更方便地使用该异常。

1. 您可以使用从 `getAmazonSQSClient` 和 `getWrappedAmazonSQSClient` 返回的客户端对象来执行未包含在 JMS 规范中的管理操作（例如，可以创建 Amazon SQS 队列）。

    如果您现有的代码需要 JMS 异常，则应使用 `getWrappedAmazonSQSClient`：
   + 如果您使用 `getWrappedAmazonSQSClient`，则返回的客户端对象会将所有异常转变成 JMS 异常。
   + 如果您使用 `getAmazonSQSClient`，则这些异常将全部为 Amazon SQS 异常。

## 创建 Amazon SQS 队列
<a name="creating-queue"></a>

包装的客户端对象将检查是否存在 Amazon SQS 队列。

如果队列不存在，客户端将创建它。如果队列存在，则该功能不会返回任何值。有关更多信息，请参阅 [TextMessageSender.java](sqs-jms-code-examples.md#example-sender) 示例中的“根据需要创建队列”一节。

### 创建标准队列
<a name="creating-queue-standard"></a>

```
// Get the wrapped client
AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();
 
// Create an SQS queue named MyQueue, if it doesn't already exist
if (!client.queueExists("MyQueue")) {
    client.createQueue("MyQueue");
}
```

### 创建 FIFO 队列
<a name="creating-queue-FIFO"></a>

```
// Get the wrapped client
AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();

// Create an Amazon SQS FIFO queue named MyQueue.fifo, if it doesn't already exist
if (!client.queueExists("MyQueue.fifo")) {
    Map<String, String> attributes = new HashMap<String, String>();
    attributes.put("FifoQueue", "true");
    attributes.put("ContentBasedDeduplication", "true");
    client.createQueue(new CreateQueueRequest().withQueueName("MyQueue.fifo").withAttributes(attributes));
}
```

**注意**  
FIFO 队列名称必须以 `.fifo` 后缀结尾。  
有关 `ContentBasedDeduplication` 属性的更多信息，请参阅[Amazon SQS 中的仅处理一次](FIFO-queues-exactly-once-processing.md)。

## 同步发送消息
<a name="send-messages-synchronously"></a>

1. 当连接和基础 Amazon SQS 队列准备就绪时，将创建一个具有 `AUTO_ACKNOWLEDGE` 模式的非事务性 JMS 会话。

   ```
   // Create the nontransacted session with AUTO_ACKNOWLEDGE mode
   Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
   ```

1. 为了向队列发送文本消息，将创建一个 JMS 队列标识和消息创建者。

   ```
   // Create a queue identity and specify the queue name to the session
   Queue queue = session.createQueue("MyQueue");
    
   // Create a producer for the 'MyQueue'
   MessageProducer producer = session.createProducer(queue);
   ```

1. 创建文本消息并将它发送到队列。
   + 要向标准队列发送消息，您无需设置任何其他参数。

     ```
     // Create the text message
     TextMessage message = session.createTextMessage("Hello World!");
      
     // Send the message
     producer.send(message);
     System.out.println("JMS Message " + message.getJMSMessageID());
     ```
   + 要向 FIFO 队列发送消息，必须设置消息组 ID。您也可以设置消息重复数据删除 ID。有关更多信息，请参阅[Amazon SQS FIFO 队列关键术语](FIFO-key-terms.md)。

     ```
     // Create the text message
     TextMessage message = session.createTextMessage("Hello World!");
     
     // Set the message group ID
     message.setStringProperty("JMSXGroupID", "Default");
     
     // You can also set a custom message deduplication ID
     // message.setStringProperty("JMS_SQS_DeduplicationId", "hello");
     // Here, it's not needed because content-based deduplication is enabled for the queue
     
     // Send the message
     producer.send(message);
     System.out.println("JMS Message " + message.getJMSMessageID());
     System.out.println("JMS Message Sequence Number " + message.getStringProperty("JMS_SQS_SequenceNumber"));
     ```

## 同步接收消息
<a name="receive-messages-synchronously"></a>

1. 要接收消息，可为同一队列创建一个使用者，然后调用 `start` 方法。

   您可以随时对连接调用 `start` 方法。不过，使用者不会开始接收消息，直至调用此方法。

   ```
   // Create a consumer for the 'MyQueue'
   MessageConsumer consumer = session.createConsumer(queue);
   // Start receiving incoming messages
   connection.start();
   ```

1. 在超时设为 1 秒钟的情况下对该使用者调用 `receive` 方法，然后输出收到的消息内容。
   + 收到来自标准队列的消息后，可以访问消息的内容。

     ```
     // Receive a message from 'MyQueue' and wait up to 1 second
     Message receivedMessage = consumer.receive(1000);
      
     // Cast the received message as TextMessage and display the text
     if (receivedMessage != null) {
         System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
     }
     ```
   + 在收到来自 FIFO 队列的消息后，您可以访问消息的内容和其他特定于 FIFO 的消息属性，例如消息组 ID、消息重复数据删除 ID 和序列号。有关更多信息，请参阅 [Amazon SQS FIFO 队列关键术语](FIFO-key-terms.md)。

     ```
     // Receive a message from 'MyQueue' and wait up to 1 second
     Message receivedMessage = consumer.receive(1000);
     
     // Cast the received message as TextMessage and display the text
     if (receivedMessage != null) {
         System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
         System.out.println("Group id: " + receivedMessage.getStringProperty("JMSXGroupID"));
         System.out.println("Message deduplication id: " + receivedMessage.getStringProperty("JMS_SQS_DeduplicationId"));
         System.out.println("Message sequence number: " + receivedMessage.getStringProperty("JMS_SQS_SequenceNumber"));
     }
     ```

1. 关闭连接和会话。

   ```
   // Close the connection (and the session).
   connection.close();
   ```

输出看上去类似于以下内容：

```
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
```

**注意**  
您可以使用 Spring Framework 初始化这些对象。  
有关其他信息，请参阅 `SpringExampleConfiguration.xml`、`SpringExample.java`，以及`ExampleConfiguration.java`部分中的 `ExampleCommon.java` 和 [实际可用的 Java 示例：将 JMS 与 Amazon SQS 标准队列相结合使用](sqs-jms-code-examples.md) 中的其他帮助程序类。

有关发送和接收对象的完整示例，请参阅 [TextMessageSender.java](sqs-jms-code-examples.md#example-sender) 和 [SyncMessageReceiver.java](sqs-jms-code-examples.md#example-synchronous-message-receiver)。

## 异步接收消息
<a name="receive-messages-asynchronously"></a>

在 [使用 Amazon SQS Java Messaging Library](#getting-started)中的示例中，消息发送到 `MyQueue` 并被同步接收。

以下示例介绍如何通过监听器异步接收消息。

1. 实施 `MessageListener` 接口。

   ```
   class MyListener implements MessageListener {
    
       @Override
       public void onMessage(Message message) {
           try {
               // Cast the received message as TextMessage and print the text to screen.
               System.out.println("Received: " + ((TextMessage) message).getText());
           } catch (JMSException e) {
               e.printStackTrace();
           }
       }
   }
   ```

   在收到消息时，调用 `onMessage` 接口的 `MessageListener` 方法。在此监听器实现中，输出保存在消息中的文本。

1. 对 `receive` 实现实例设置使用者消息监听器，而不是对使用者显式调用 `MyListener` 方法。主线程会等待一秒钟。

   ```
   // Create a consumer for the 'MyQueue'.
   MessageConsumer consumer = session.createConsumer(queue);
    
   // Instantiate and set the message listener for the consumer.
   consumer.setMessageListener(new MyListener());
    
   // Start receiving incoming messages.
   connection.start();
    
   // Wait for 1 second. The listener onMessage() method is invoked when a message is received.
   Thread.sleep(1000);
   ```

其余步骤与 [使用 Amazon SQS Java Messaging Library](#getting-started)示例中的步骤相同。有关异步使用者的完整示例，请参阅`AsyncMessageReceiver.java`中的 [实际可用的 Java 示例：将 JMS 与 Amazon SQS 标准队列相结合使用](sqs-jms-code-examples.md)。

此示例的输出将与以下内容类似：

```
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
```

## 使用客户端确认模式
<a name="using-client-acknowledge-mode"></a>

[使用 Amazon SQS Java Messaging Library](#getting-started)中的示例使用 `AUTO_ACKNOWLEDGE` 模式，该模式会自动确认收到的每条消息（因此会从基础 Amazon SQS 队列中删除消息）。

1. 要在消息处理完毕后显式确认消息，则必须创建具有 `CLIENT_ACKNOWLEDGE` 模式的会话。

   ```
   // Create the non-transacted session with CLIENT_ACKNOWLEDGE mode.
   Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
   ```

1. 收到消息时，显示消息，然后显式确认消息。

   ```
   // Cast the received message as TextMessage and print the text to screen. Also acknowledge the message.
   if (receivedMessage != null) {
       System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
       receivedMessage.acknowledge();
       System.out.println("Acknowledged: " + message.getJMSMessageID());
   }
   ```
**注意**  
在此模式下，当确认某条消息时，也会隐式确认在该消息之前收到的所有消息。例如，如果收到 10 条消息，则仅确认第 10 条消息（按接收消息的顺序），然后还会确认先前的所有 9 条消息。

其余步骤与 [使用 Amazon SQS Java Messaging Library](#getting-started)示例中的步骤相同。有关具有客户端确认模式的同步使用者的完整示例，请参阅`SyncMessageReceiverClientAcknowledge.java`中的 [实际可用的 Java 示例：将 JMS 与 Amazon SQS 标准队列相结合使用](sqs-jms-code-examples.md)。

此示例的输出将与以下内容类似：

```
JMS Message ID:4example-aa0e-403f-b6df-5e02example5
Received: Hello World!
Acknowledged: ID:4example-aa0e-403f-b6df-5e02example5
```

## 使用无序确认模式
<a name="using-unordered-acknowledge-mode"></a>

在使用 `CLIENT_ACKNOWLEDGE` 模式时，将自动确认在显式确认的消息之前收到的所有消息。有关更多信息，请参阅 [使用客户端确认模式](#using-client-acknowledge-mode)。

Amazon SQS Java Messaging Library 提供另一种确认模式。在使用 `UNORDERED_ACKNOWLEDGE` 模式时，客户端必须单独显式确认收到的所有消息，不管消息的接收顺序如何。为此，请使用 `UNORDERED_ACKNOWLEDGE` 模式创建会话。

```
// Create the non-transacted session with UNORDERED_ACKNOWLEDGE mode.
Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
```

其余步骤与 [使用客户端确认模式](#using-client-acknowledge-mode)示例中的步骤相同。有关具有 `UNORDERED_ACKNOWLEDGE` 模式的同步使用者的完整示例，请参阅 `SyncMessageReceiverUnorderedAcknowledge.java`。

此示例中的输出将与以下内容类似：

```
JMS Message ID:dexample-73ad-4adb-bc6c-4357example7
Received: Hello World!
Acknowledged: ID:dexample-73ad-4adb-bc6c-4357example7
```

# 将 Java Message Service 客户端与其他 Amazon SQS 客户端配合使用
<a name="sqs-jms-client-with-sqs-clients"></a>

使用带软件开发工具包的亚马逊 SQS Java 消息服务 (JMS) 客户端将亚马逊 AWS SQS 消息大小限制为 256 KB。不过，您可以使用任何 Amazon SQS 客户端创建 JMS 提供程序。例如，可以使用 JMS 客户端与适用于 Java 的 Amazon SQS 扩展型客户端库来发送包含对 Amazon S3 中的消息负载（最大为 2 GB）的引用的 Amazon SQS 消息。有关更多信息，请参阅 [使用 Java 和 Amazon S3 管理大型 Amazon SQS 消息](sqs-s3-messages.md)。

以下 Java 代码示例将为扩展型客户端库创建 JMS 提供程序。

在测试此示例之前，请参阅[使用 JMS 和 Amazon SQS 的先决条件](prerequisites.md)中的先决条件。

```
AmazonS3 s3 = new AmazonS3Client(credentials);
Region s3Region = Region.getRegion(Regions.US_WEST_2);
s3.setRegion(s3Region);
 
// Set the Amazon S3 bucket name, and set a lifecycle rule on the bucket to
// permanently delete objects a certain number of days after each object's creation date.
// Next, create the bucket, and enable message objects to be stored in the bucket.
BucketLifecycleConfiguration.Rule expirationRule = new BucketLifecycleConfiguration.Rule();
expirationRule.withExpirationInDays(14).withStatus("Enabled");
BucketLifecycleConfiguration lifecycleConfig = new BucketLifecycleConfiguration().withRules(expirationRule);
 
s3.createBucket(s3BucketName);
s3.setBucketLifecycleConfiguration(s3BucketName, lifecycleConfig);
System.out.println("Bucket created and configured.");

// Set the SQS extended client configuration with large payload support enabled.
ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration()
    .withLargePayloadSupportEnabled(s3, s3BucketName);
 
AmazonSQS sqsExtended = new AmazonSQSExtendedClient(new AmazonSQSClient(credentials), extendedClientConfig);
Region sqsRegion = Region.getRegion(Regions.US_WEST_2);
sqsExtended.setRegion(sqsRegion);
```

以下 Java 代码示例将创建连接工厂：

```
// Create the connection factory using the environment variable credential provider.
// Pass the configured Amazon SQS Extended Client to the JMS connection factory.
SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
        new ProviderConfiguration(),
        sqsExtended
        );
 
// Create the connection.
SQSConnection connection = connectionFactory.createConnection();
```

# 实际可用的 Java 示例：将 JMS 与 Amazon SQS 标准队列相结合使用
<a name="sqs-jms-code-examples"></a>

以下代码示例说明如何结合使用 Java Message Service (JMS) 与 Amazon SQS 标准队列。有关使用 FIFO 队列的更多信息，请参阅[创建 FIFO 队列](getting-started.md#creating-queue-FIFO)、[同步发送消息](getting-started.md#send-messages-synchronously)和[同步接收消息](getting-started.md#receive-messages-synchronously)。（标准队列和 FIFO 队列的同步接收消息是相同的。但是，FIFO 队列中的消息包含更多属性。）

在测试以下示例之前，请参阅[使用 JMS 和 Amazon SQS 的先决条件](prerequisites.md)中的先决条件。

## ExampleConfiguration.java
<a name="example-configuration"></a>

以下 Java SDK（版本 1.x）代码示例设置将用于其他 Java 示例的默认队列名称、区域和凭证。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

public class ExampleConfiguration {
    public static final String DEFAULT_QUEUE_NAME = "SQSJMSClientExampleQueue";
    
    public static final Region DEFAULT_REGION = Region.getRegion(Regions.US_EAST_2);
    
    private static String getParameter( String args[], int i ) {
        if( i + 1 >= args.length ) {
            throw new IllegalArgumentException( "Missing parameter for " + args[i] );
        }
        return args[i+1];
    }
    
    /**
     * Parse the command line and return the resulting config. If the config parsing fails
     * print the error and the usage message and then call System.exit
     * 
     * @param app the app to use when printing the usage string
     * @param args the command line arguments
     * @return the parsed config
     */
    public static ExampleConfiguration parseConfig(String app, String args[]) {
        try {
            return new ExampleConfiguration(args);
        } catch (IllegalArgumentException e) {
            System.err.println( "ERROR: " + e.getMessage() );
            System.err.println();
            System.err.println( "Usage: " + app + " [--queue <queue>] [--region <region>] [--credentials <credentials>] ");
            System.err.println( "  or" );
            System.err.println( "       " + app + " <spring.xml>" );
            System.exit(-1);
            return null;
        }
    }
    
    private ExampleConfiguration(String args[]) {
        for( int i = 0; i < args.length; ++i ) {
            String arg = args[i];
            if( arg.equals( "--queue" ) ) {
                setQueueName(getParameter(args, i));
                i++;
            } else if( arg.equals( "--region" ) ) {
                String regionName = getParameter(args, i);
                try {
                    setRegion(Region.getRegion(Regions.fromName(regionName)));
                } catch( IllegalArgumentException e ) {
                    throw new IllegalArgumentException( "Unrecognized region " + regionName );  
                }
                i++;
            } else if( arg.equals( "--credentials" ) ) {
                String credsFile = getParameter(args, i);
                try {
                    setCredentialsProvider( new PropertiesFileCredentialsProvider(credsFile) );
                } catch (AmazonClientException e) {
                    throw new IllegalArgumentException("Error reading credentials from " + credsFile, e );
                }
                i++;
            } else {
                throw new IllegalArgumentException("Unrecognized option " + arg);
            }
        }
    }
    
    private String queueName = DEFAULT_QUEUE_NAME;
    private Region region = DEFAULT_REGION;
    private AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain();
    
    public String getQueueName() {
        return queueName;
    }
    
    public void setQueueName(String queueName) {
        this.queueName = queueName;
    }
    
    public Region getRegion() {
        return region;
    }
    
    public void setRegion(Region region) {
        this.region = region;
    }
 
    public AWSCredentialsProvider getCredentialsProvider() {
        return credentialsProvider;
    }
    
    public void setCredentialsProvider(AWSCredentialsProvider credentialsProvider) {
        // Make sure they're usable first
        credentialsProvider.getCredentials();
        this.credentialsProvider = credentialsProvider;
    }
}
```

## TextMessageSender.java
<a name="example-sender"></a>

以下 Java 代码示例创建文本消息创建者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

public class TextMessageSender {
    public static void main(String args[]) throws JMSException {
        ExampleConfiguration config = ExampleConfiguration.parseConfig("TextMessageSender", args);
        
        ExampleCommon.setupLogging();
        
        // Create the connection factory based on the config       
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
        
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
        
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
            
        // Create the session
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer = session.createProducer( session.createQueue( config.getQueueName() ) );
        
        sendMessages(session, producer);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println( "Connection closed" );
    }
 
    private static void sendMessages( Session session, MessageProducer producer ) {
        BufferedReader inputReader = new BufferedReader(
            new InputStreamReader( System.in, Charset.defaultCharset() ) );
        
        try {
            String input;
            while( true ) { 
                System.out.print( "Enter message to send (leave empty to exit): " );
                input = inputReader.readLine();
                if( input == null || input.equals("" ) ) break;
                
                TextMessage message = session.createTextMessage(input);
                producer.send(message);
                System.out.println( "Send message " + message.getJMSMessageID() );
            }
        } catch (EOFException e) {
            // Just return on EOF
        } catch (IOException e) {
            System.err.println( "Failed reading input: " + e.getMessage() );
        } catch (JMSException e) {
            System.err.println( "Failed sending message: " + e.getMessage() );
            e.printStackTrace();
        }
    }
}
```

## SyncMessageReceiver.java
<a name="example-synchronous-message-receiver"></a>

以下 Java 代码示例创建同步消息使用者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

public class SyncMessageReceiver {
public static void main(String args[]) throws JMSException {
    ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiver", args);
    
    ExampleCommon.setupLogging();
    
    // Create the connection factory based on the config
    SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
            new ProviderConfiguration(),
            AmazonSQSClientBuilder.standard()
                    .withRegion(config.getRegion().getName())
                    .withCredentials(config.getCredentialsProvider())
            );
    
    // Create the connection
    SQSConnection connection = connectionFactory.createConnection();
    
    // Create the queue if needed
    ExampleCommon.ensureQueueExists(connection, config.getQueueName());
        
    // Create the session
    Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    MessageConsumer consumer = session.createConsumer( session.createQueue( config.getQueueName() ) );

    connection.start();
    
    receiveMessages(session, consumer);

    // Close the connection. This closes the session automatically
    connection.close();
    System.out.println( "Connection closed" );
}

private static void receiveMessages( Session session, MessageConsumer consumer ) {
    try {
        while( true ) {
            System.out.println( "Waiting for messages");
            // Wait 1 minute for a message
            Message message = consumer.receive(TimeUnit.MINUTES.toMillis(1));
            if( message == null ) {
                System.out.println( "Shutting down after 1 minute of silence" );
                break;
            }
            ExampleCommon.handleMessage(message);
            message.acknowledge();
            System.out.println( "Acknowledged message " + message.getJMSMessageID() );
        }
    } catch (JMSException e) {
        System.err.println( "Error receiving from SQS: " + e.getMessage() );
        e.printStackTrace();
    }
}
}
```

## AsyncMessageReceiver.java
<a name="example-asynchronous-message-receiver"></a>

以下 Java 代码示例创建异步消息使用者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

public class AsyncMessageReceiver {
    public static void main(String args[]) throws JMSException, InterruptedException {
        ExampleConfiguration config = ExampleConfiguration.parseConfig("AsyncMessageReceiver", args);
         
        ExampleCommon.setupLogging();          
         
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
         
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
         
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
             
        // Create the session
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer( session.createQueue( config.getQueueName() ) );
         
        // No messages are processed until this is called
        connection.start();

        ReceiverCallback callback = new ReceiverCallback();
        consumer.setMessageListener( callback );
         
        callback.waitForOneMinuteOfSilence();
        System.out.println( "Returning after one minute of silence" );

        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println( "Connection closed" );
    }
    
    
    private static class ReceiverCallback implements MessageListener {
        // Used to listen for message silence
        private volatile long timeOfLastMessage = System.nanoTime();
         
        public void waitForOneMinuteOfSilence() throws InterruptedException {
            for(;;) {
                long timeSinceLastMessage = System.nanoTime() - timeOfLastMessage;
                long remainingTillOneMinuteOfSilence = 
                    TimeUnit.MINUTES.toNanos(1) - timeSinceLastMessage;
                if( remainingTillOneMinuteOfSilence < 0 ) {
                    break;
                }
                TimeUnit.NANOSECONDS.sleep(remainingTillOneMinuteOfSilence);
            }
        }
         

        @Override
        public void onMessage(Message message) {
            try {
                ExampleCommon.handleMessage(message);
                message.acknowledge();
                System.out.println( "Acknowledged message " + message.getJMSMessageID() );
                timeOfLastMessage = System.nanoTime();
            } catch (JMSException e) {
                System.err.println( "Error processing message: " + e.getMessage() );
                e.printStackTrace();
            }
        }
    }
}
```

## SyncMessageReceiverClientAcknowledge.java
<a name="example-synchronous-receiver-client-acknowledge-mode"></a>

以下 Java 代码示例创建具有客户端确认模式的同步使用者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

/**
 * An example class to demonstrate the behavior of CLIENT_ACKNOWLEDGE mode for received messages. This example
 * complements the example given in {@link SyncMessageReceiverUnorderedAcknowledge} for UNORDERED_ACKNOWLEDGE mode.
 *
 * First, a session, a message producer, and a message consumer are created. Then, two messages are sent. Next, two messages
 * are received but only the second one is acknowledged. After waiting for the visibility time out period, an attempt to
 * receive another message is made. It's shown that no message is returned for this attempt since in CLIENT_ACKNOWLEDGE mode,
 * as expected, all the messages prior to the acknowledged messages are also acknowledged.
 *
 * This ISN'T the behavior for UNORDERED_ACKNOWLEDGE mode. Please see {@link SyncMessageReceiverUnorderedAcknowledge}
 * for an example.
 */
public class SyncMessageReceiverClientAcknowledge {
 
    // Visibility time-out for the queue. It must match to the one set for the queue for this example to work.
    private static final long TIME_OUT_SECONDS = 1;
 
    public static void main(String args[]) throws JMSException, InterruptedException {
        // Create the configuration for the example
        ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiverClientAcknowledge", args);
 
        // Setup logging for the example
        ExampleCommon.setupLogging();
 
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
 
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
 
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
 
        // Create the session  with client acknowledge mode
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
 
        // Create the producer and consume
        MessageProducer producer = session.createProducer(session.createQueue(config.getQueueName()));
        MessageConsumer consumer = session.createConsumer(session.createQueue(config.getQueueName()));
 
        // Open the connection
        connection.start();
 
        // Send two text messages
        sendMessage(producer, session, "Message 1");
        sendMessage(producer, session, "Message 2");
 
        // Receive a message and don't acknowledge it
        receiveMessage(consumer, false);
 
        // Receive another message and acknowledge it
        receiveMessage(consumer, true);
 
        // Wait for the visibility time out, so that unacknowledged messages reappear in the queue
        System.out.println("Waiting for visibility timeout...");
        Thread.sleep(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        // Attempt to receive another message and acknowledge it. This results in receiving no messages since
        // we have acknowledged the second message. Although we didn't explicitly acknowledge the first message,
        // in the CLIENT_ACKNOWLEDGE mode, all the messages received prior to the explicitly acknowledged message
        // are also acknowledged. Therefore, we have implicitly acknowledged the first message.
        receiveMessage(consumer, true);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println("Connection closed.");
    }
 
    /**
     * Sends a message through the producer.
     *
     * @param producer Message producer
     * @param session Session
     * @param messageText Text for the message to be sent
     * @throws JMSException
     */
    private static void sendMessage(MessageProducer producer, Session session, String messageText) throws JMSException {
        // Create a text message and send it
        producer.send(session.createTextMessage(messageText));
    }
 
    /**
     * Receives a message through the consumer synchronously with the default timeout (TIME_OUT_SECONDS).
     * If a message is received, the message is printed. If no message is received, "Queue is empty!" is
     * printed.
     *
     * @param consumer Message consumer
     * @param acknowledge If true and a message is received, the received message is acknowledged.
     * @throws JMSException
     */
    private static void receiveMessage(MessageConsumer consumer, boolean acknowledge) throws JMSException {
        // Receive a message
        Message message = consumer.receive(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        if (message == null) {
            System.out.println("Queue is empty!");
        } else {
            // Since this queue has only text messages, cast the message object and print the text
            System.out.println("Received: " + ((TextMessage) message).getText());
 
            // Acknowledge the message if asked
            if (acknowledge) message.acknowledge();
        }
    }
}
```

## SyncMessageReceiverUnorderedAcknowledge.java
<a name="example-synchronous-receiver-unordered-acknowledge-mode"></a>

以下 Java 代码示例创建具有无序确认模式的同步使用者。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

/**
 * An example class to demonstrate the behavior of UNORDERED_ACKNOWLEDGE mode for received messages. This example
 * complements the example given in {@link SyncMessageReceiverClientAcknowledge} for CLIENT_ACKNOWLEDGE mode.
 *
 * First, a session, a message producer, and a message consumer are created. Then, two messages are sent. Next, two messages
 * are received but only the second one is acknowledged. After waiting for the visibility time out period, an attempt to
 * receive another message is made. It's shown that the first message received in the prior attempt is returned again
 * for the second attempt. In UNORDERED_ACKNOWLEDGE mode, all the messages must be explicitly acknowledged no matter what
 * the order they're received.
 *
 * This ISN'T the behavior for CLIENT_ACKNOWLEDGE mode. Please see {@link SyncMessageReceiverClientAcknowledge}
 * for an example.
 */
public class SyncMessageReceiverUnorderedAcknowledge {
 
    // Visibility time-out for the queue. It must match to the one set for the queue for this example to work.
    private static final long TIME_OUT_SECONDS = 1;
 
    public static void main(String args[]) throws JMSException, InterruptedException {
        // Create the configuration for the example
        ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiverUnorderedAcknowledge", args);
 
        // Setup logging for the example
        ExampleCommon.setupLogging();
 
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
 
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
 
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
 
        // Create the session  with unordered acknowledge mode
        Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
 
        // Create the producer and consume
        MessageProducer producer = session.createProducer(session.createQueue(config.getQueueName()));
        MessageConsumer consumer = session.createConsumer(session.createQueue(config.getQueueName()));
 
        // Open the connection
        connection.start();
 
        // Send two text messages
        sendMessage(producer, session, "Message 1");
        sendMessage(producer, session, "Message 2");
 
        // Receive a message and don't acknowledge it
        receiveMessage(consumer, false);
 
        // Receive another message and acknowledge it
        receiveMessage(consumer, true);
 
        // Wait for the visibility time out, so that unacknowledged messages reappear in the queue
        System.out.println("Waiting for visibility timeout...");
        Thread.sleep(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        // Attempt to receive another message and acknowledge it. This results in receiving the first message since
        // we have acknowledged only the second message. In the UNORDERED_ACKNOWLEDGE mode, all the messages must
        // be explicitly acknowledged.
        receiveMessage(consumer, true);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println("Connection closed.");
    }
 
    /**
     * Sends a message through the producer.
     *
     * @param producer Message producer
     * @param session Session
     * @param messageText Text for the message to be sent
     * @throws JMSException
     */
    private static void sendMessage(MessageProducer producer, Session session, String messageText) throws JMSException {
        // Create a text message and send it
        producer.send(session.createTextMessage(messageText));
    }
 
    /**
     * Receives a message through the consumer synchronously with the default timeout (TIME_OUT_SECONDS).
     * If a message is received, the message is printed. If no message is received, "Queue is empty!" is
     * printed.
     *
     * @param consumer Message consumer
     * @param acknowledge If true and a message is received, the received message is acknowledged.
     * @throws JMSException
     */
    private static void receiveMessage(MessageConsumer consumer, boolean acknowledge) throws JMSException {
        // Receive a message
        Message message = consumer.receive(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        if (message == null) {
            System.out.println("Queue is empty!");
        } else {
            // Since this queue has only text messages, cast the message object and print the text
            System.out.println("Received: " + ((TextMessage) message).getText());
 
            // Acknowledge the message if asked
            if (acknowledge) message.acknowledge();
        }
    }
}
```

## SpringExampleConfiguration.xml
<a name="example-spring-configuration"></a>

以下 XML 代码示例是 [SpringExample.java](#example-spring) 的 Bean 配置文件。

```
<!--
    Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License").
    You may not use this file except in compliance with the License.
    A copy of the License is located at

    https://aws.amazon.com/apache2.0

    or in the "license" file accompanying this file. This file is distributed
    on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
    express or implied. See the License for the specific language governing
    permissions and limitations under the License.
-->

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
    ">
    
    <bean id="CredentialsProviderBean" class="com.amazonaws.auth.DefaultAWSCredentialsProviderChain"/>
    
    <bean id="ClientBuilder" class="com.amazonaws.services.sqs.AmazonSQSClientBuilder" factory-method="standard">
        <property name="region" value="us-east-2"/>
        <property name="credentials" ref="CredentialsProviderBean"/>               
    </bean>
    
    <bean id="ProviderConfiguration" class="com.amazon.sqs.javamessaging.ProviderConfiguration">
        <property name="numberOfMessagesToPrefetch" value="5"/>
    </bean>
    
    <bean id="ConnectionFactory" class="com.amazon.sqs.javamessaging.SQSConnectionFactory">
        <constructor-arg ref="ProviderConfiguration" />
        <constructor-arg ref="ClientBuilder" />
    </bean>
    
    <bean id="Connection" class="javax.jms.Connection"
        factory-bean="ConnectionFactory"
        factory-method="createConnection"
        init-method="start"
        destroy-method="close" />
    
    <bean id="QueueName" class="java.lang.String">
        <constructor-arg value="SQSJMSClientExampleQueue"/>
    </bean>
</beans>
```

## SpringExample.java
<a name="example-spring"></a>

以下 Java 代码示例使用 Bean 配置文件来初始化您的对象。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */
                
public class SpringExample {
    public static void main(String args[]) throws JMSException {
        if( args.length != 1 || !args[0].endsWith(".xml")) {
            System.err.println( "Usage: " + SpringExample.class.getName() + " <spring config.xml>" );
            System.exit(1);
        }
        
        File springFile = new File( args[0] );
        if( !springFile.exists() || !springFile.canRead() ) {
            System.err.println( "File " + args[0] + " doesn't exist or isn't readable.");
            System.exit(2);
        }
        
        ExampleCommon.setupLogging();
        
        FileSystemXmlApplicationContext context = 
            new FileSystemXmlApplicationContext( "file://" + springFile.getAbsolutePath() );
        
        Connection connection;
        try {
            connection = context.getBean(Connection.class);
        } catch( NoSuchBeanDefinitionException e ) {
            System.err.println( "Can't find the JMS connection to use: " + e.getMessage() );
            System.exit(3);
            return;
        }
        
        String queueName;
        try {
            queueName = context.getBean("QueueName", String.class);
        } catch( NoSuchBeanDefinitionException e ) {
            System.err.println( "Can't find the name of the queue to use: " + e.getMessage() );
            System.exit(3);
            return;
        }
        
        if( connection instanceof SQSConnection ) {
            ExampleCommon.ensureQueueExists( (SQSConnection) connection, queueName );
        }
        
        // Create the session
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer( session.createQueue( queueName) );
        
        receiveMessages(session, consumer);
 
        // The context can be setup to close the connection for us
        context.close();
        System.out.println( "Context closed" );
    }
 
    private static void receiveMessages( Session session, MessageConsumer consumer ) {
        try {
            while( true ) {
                System.out.println( "Waiting for messages");
                // Wait 1 minute for a message
                Message message = consumer.receive(TimeUnit.MINUTES.toMillis(1));
                if( message == null ) {
                    System.out.println( "Shutting down after 1 minute of silence" );
                    break;
                }
                ExampleCommon.handleMessage(message);
                message.acknowledge();
                System.out.println( "Acknowledged message" );
            }
        } catch (JMSException e) {
            System.err.println( "Error receiving from SQS: " + e.getMessage() );
            e.printStackTrace();
        }
    }
}
```

## ExampleCommon.java
<a name="example-common"></a>

以下 Java 代码示例首先查看 Amazon SQS 队列是否存在，如果不存在，则会创建一个。它还包含示例日历记录代码。

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

public class ExampleCommon {
    /**
     * A utility function to check the queue exists and create it if needed. For most  
     * use cases this is usually done by an administrator before the application is run. 
     */
    public static void ensureQueueExists(SQSConnection connection, String queueName) throws JMSException {
        AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();
        
        /**
         * In most cases, you can do this with just a createQueue call, but GetQueueUrl 
         * (called by queueExists) is a faster operation for the common case where the queue 
         * already exists. Also many users and roles have permission to call GetQueueUrl
         * but don't have permission to call CreateQueue.
         */
        if( !client.queueExists(queueName) ) {
            client.createQueue( queueName );
        }
    }
 
    public static void setupLogging() {
        // Setup logging
        BasicConfigurator.configure();
        Logger.getRootLogger().setLevel(Level.WARN);
    }
 
    public static void handleMessage(Message message) throws JMSException {
        System.out.println( "Got message " + message.getJMSMessageID() );
        System.out.println( "Content: ");
        if( message instanceof TextMessage ) {
            TextMessage txtMessage = ( TextMessage ) message;
            System.out.println( "\t" + txtMessage.getText() );
        } else if( message instanceof BytesMessage ){
            BytesMessage byteMessage = ( BytesMessage ) message;
            // Assume the length fits in an int - SQS only supports sizes up to 256k so that
            // should be true
            byte[] bytes = new byte[(int)byteMessage.getBodyLength()];
            byteMessage.readBytes(bytes);
            System.out.println( "\t" +  Base64.encodeAsString( bytes ) );
        } else if( message instanceof ObjectMessage ) {
            ObjectMessage objMessage = (ObjectMessage) message;
            System.out.println( "\t" + objMessage.getObject() );
        }
    }
}
```

# Amazon SQS 支持的 JMS 1.1 实现
<a name="supported-implementations"></a>

Amazon SQS Java Messaging Library 支持以下 [JMS 1.1 实施](http://docs.oracle.com/javaee/6/api/javax/jms/package-summary.html)。有关 Amazon SQS Java Messaging Library 支持的特征和功能的更多信息，请参阅 [Amazon SQS 常见问题](https://aws.amazon.com/sqs/faqs/)。

## 支持的常用接口
<a name="supported-common-interfaces"></a>
+ `Connection`
+ `ConnectionFactory`
+ `Destination`
+ `Session`
+ `MessageConsumer`
+ `MessageProducer`

## 支持的消息类型
<a name="supported-message-types"></a>
+ `ByteMessage`
+ `ObjectMessage`
+ `TextMessage`

## 支持的消息确认模式
<a name="supported-message-acknowledgement-modes"></a>
+ `AUTO_ACKNOWLEDGE`
+ `CLIENT_ACKNOWLEDGE`
+ `DUPS_OK_ACKNOWLEDGE`
+ `UNORDERED_ACKNOWLEDGE`

**注意**  
`UNORDERED_ACKNOWLEDGE` 模式不属于 JMS 1.1 规范。此模式有助于 Amazon SQS 允许 JMS 客户端显式确认消息。

## JMS 定义的标头和预留属性
<a name="jms-defined-headers-reserved-properties"></a>

### 发送消息
<a name="for-sending-messages"></a>

在发送消息时，您可以为每条消息设置以下标头和属性：
+ `JMSXGroupID`（对于 FIFO 队列是必需的，对于标准队列是不允许的）
+ `JMS_SQS_DeduplicationId`（对于 FIFO 队列是可选的，对于标准队列是不允许的）

在发送消息后，Amazon SQS 将为每条消息设置以下标头和属性：
+ `JMSMessageID`
+ `JMS_SQS_SequenceNumber`（仅适用于 FIFO 队列）

### 接收消息
<a name="for-receiving-messages"></a>

在接收消息时，Amazon SQS 将为每条消息设置以下标头和属性：
+ `JMSDestination`
+ `JMSMessageID`
+ `JMSRedelivered`
+ `JMSXDeliveryCount`
+ `JMSXGroupID`（仅适用于 FIFO 队列）
+ `JMS_SQS_DeduplicationId`（仅适用于 FIFO 队列）
+ `JMS_SQS_SequenceNumber`（仅适用于 FIFO 队列）