原文链接:Ten ways in which JMS 2.0 means writing less code

这里有十个简单的例子,说明 JMS 2.0 比 JMS 1.1 需要更少的代码。

单一 JMSContext 而不是单独的 Connection 和 Session 对象

JMS 2.0 简化 API 引入了一个新对象, JMSContext 它提供了与 JMS 1.1 API 中的分隔 Connection 对象 Session 相同的功能:

JMS 1.1

1
2
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

JMS 2.0

1
JMSContext context = connectionFactory.createContext(JMSContext.SESSION_TRANSACTED);

使用 try-with-resources 块意味着不需要调用 close

使用后未能关闭Connection可能会导致您的应用程序耗尽资源。

JMS 1.1

在 JMS 1.1 中,确保使用后关闭连接的最佳方法是调用close()一个finally块:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
try {
  Connection connection = connectionFactory.createConnection();
  try {
    Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
    ... etc ...
  } finally {
    connection.close();
  }
} catch (JMSException ex) {
  ex.printStackTrace();
}

这太冗长了。更糟糕的是,如果您在块主体中遇到异常try,然后在中遇到异常close(),则第一个异常将会丢失,即使第一个异常可能是失败的根本原因。

JMS 2.0

在 JMS 2.0 中,Connection对象实现了java.lang.AutoCloseable接口。这意味着,如果您Connection 在 try-with-resources 块中创建对象,则该close方法将在该块的末尾自动调用。

1
2
3
4
5
try (Connection connection = connectionFactory.createConnection();){
  ... etc ...
} catch (JMSException ex) {
  ex.printStackTrace();
}

这需要更少的代码。此外,它还可以更好地处理异常:如果您在 try 块主体中遇到异常,随后在 中遇到异常close(),则第一个异常将很好地嵌套在第一个异常中,因此您可以轻松识别根本原因。

创建时可以使用相同的语法JMSContext

在 Java SE 中创建会话时无需传递两个参数

你只需要一个:

JMS 1.1

1
Session session = connection.createSession(true,Session.SESSION_TRANSACTED);

JMS 2.0

1
Session session = connection.createSession(Session.SESSION_TRANSACTED);

有类似的方法可以创建JMSContext

在 Java EE 事务中创建会话时无需传递任何参数

如果您在 Java EE 事务中创建Session,则将忽略的参数createSession。EJB 3.1 规范中是这么说的。

JMS 1.1

但是 JMS 1.1 仍然要求您传递两个参数,即使它们会被忽略。

1
2
// both parameters will be ignored; transactional behaviour is determined by the container
Session session = connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);

JMS 2.0

JMS 2.0 提供了一种没有参数的方法:

1
2
// transactional behaviour is determined by the container
Session session = connection.createSession();

新的 JMSProducer 对象支持方法链

JMSProducer对象允许使用方法链在一行代码中指定消息头、消息属性和传递选项

JMS 1.1

1
2
3
4
5
MessageProducer messageProducer = session.createProducer(demoQueue);
messageProducer.setPriority(1);
TextMessage textMessage = session.createTextMessage(body);
textMessage.setStringProperty("foo", "bar");
messageProducer.send(textMessage);

JMS 2.0

1
TextMessage textMessage = context.createTextMessage(body); context.createProducer().setPriority(1).setProperty("foo", "bar").send(demoQueue, textMessage);

无需将 JMSProducer 保存在变量中;只需即时实例化即可

JMSProducer对象是轻量级对象,因此无需将其保存在变量中;只需在需要时动态实例化一个即可

JMS 1.1

MessageProducer很贵所以需要重复使用。

1
2
3
MessageProducer messageProducer = session.createProducer(demoQueue);
messageProducer.send(message1);
messageProducer.send(message2);

JMS 2.0

JMSProducer成本低廉,无需保存在变量中

1
2
context.createProducer().send(demoQueue,message1);
context.createProducer().send(demoQueue,message2);

在 Java EE 中,注入 JMSContext 意味着您不需要创建或关闭它

JMS 1.1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
try {
  Connection connection = connectionFactory.createConnection();
  try {
    Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
    MessageProducer messageProducer = session.createProducer(demoQueue);
    TextMessage textMessage = session.createTextMessage(body);
    messageProducer.send(textMessage);
  } finally {
    connection.close();
  }
} catch (JMSException ex) {
  ex.printStackTrace();
}

JMS 2.0

1
2
3
4
5
try {
  context.createProducer().send(inboundQueue, body);
} catch (JMSRuntimeException ex){
  ex.printStackTrace();
}

发送时不需要实例化Message对象

JMS 1.1

需要创建适当类型的消息对象,然后设置其正文:

1
2
3
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage("Hello world");
messageProducer.send(textMessage);

JMS 2.0

在 JMS 2.0 中,只需将消息正文传递到send方法中:

1
context.createProducer().send(demoQueue,"Hello world");

请注意,即使您想要设置消息属性,您也可以这样做,因为这些属性可以在 上设置JMSProducer

同步接收,可直接接收消息载荷

JMS 1.1

当同步接收时,您会得到一个Message对象,并且需要将其转换为适当的子类型,然后才能提取其主体:

1
2
3
4
5
6
7
MessageConsumer messageConsumer = session.createConsumer(demoQueue);
TextMessage textMessage = (TextMessage) messageConsumer.receive(1000);
if (textMessage==null){
  return "Received null";
} else {
  return "Received "+textMessage.getText();
}

JMS 2.0

JMS 2.0 允许您直接接收消息正文。

1
2
JMSConsumer consumer = context.createConsumer(demoQueue);
return "Received " + consumer.receiveBody(String.class, 1000);

请注意缺少强制类型转换,或者特殊的空处理。

异步接收:提取消息正文之前无需进行强制转换。

JMS 1.1

异步接收消息时,传递给方法的消息onMessagejavax.jms.Message您需要将其转换为预期的子类型,然后才能提取正文。如果消息是 ,ObjectMessage这会为您提供一个Serializable正文,您必须再次将其转换为预期的正文类型。

1
2
3
public void onMessage(Message m){
  MyObject myObj = (MyObject)((ObjectMessage)m).getObject();
    ...

JMS 2.0

一种新方法getBody允许您从中提取正文,而Message无需先将其转换为适当的子类型。这对于 ObjectMessages 特别方便,因为它避免了双重转换来提取对象有效负载

1
2
3
public void onMessage(Message m){
  MyObject myObj = m.getBody(MyObject.class);
    ...

相关页面