如何使用JMS/ActiveMQ发送带图片、视频片段附件的MMS消息?
嘿,这个问题我之前帮不少开发者解决过——确实,绝大多数JMS入门示例都只展示文本消息,但要发送带图片、视频附件的MMS其实核心思路很清晰,就是把MMS的多部分内容打包成二进制流,通过JMS的二进制消息类型来传输。下面给你一步步拆解具体怎么做:
MMS本质上是多部分MIME消息,包含文本正文和二进制附件(图片、视频片段等)。我们可以先用Java的邮件API构建这种MIME结构,再把它转换成二进制流,通过JMS的BytesMessage(推荐)或BlobMessage(大附件场景)发送。
1. 构建MIME多部分消息
首先用MimeMultipart来组装文本内容和各种附件,这里需要用到Jakarta Mail(或旧版javax.mail)的API:
import jakarta.mail.BodyPart; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeBodyPart; import jakarta.mail.internet.MimeMultipart; import jakarta.mail.util.ByteArrayDataSource; import java.io.File; import java.io.FileInputStream; import java.io.IOException; // 创建MIME多部分容器 MimeMultipart multipart = new MimeMultipart(); // 添加MMS文本正文 BodyPart textBodyPart = new MimeBodyPart(); textBodyPart.setText("这是一条带附件的MMS消息"); multipart.addBodyPart(textBodyPart); // 添加图片附件 BodyPart imagePart = new MimeBodyPart(); File imageFile = new File("/path/to/your/photo.jpg"); ByteArrayDataSource imageSource = new ByteArrayDataSource( new FileInputStream(imageFile), "image/jpeg"); imagePart.setDataHandler(new jakarta.activation.DataHandler(imageSource)); imagePart.setFileName(imageFile.getName()); multipart.addBodyPart(imagePart); // 添加视频片段附件 BodyPart videoPart = new MimeBodyPart(); File videoClip = new File("/path/to/your/clip.mp4"); ByteArrayDataSource videoSource = new ByteArrayDataSource( new FileInputStream(videoClip), "video/mp4"); videoPart.setDataHandler(new jakarta.activation.DataHandler(videoSource)); videoPart.setFileName(videoClip.getName()); multipart.addBodyPart(videoPart);
2. 用JMS BytesMessage发送MIME内容
把构建好的MIME多部分消息转换成字节数组,写入BytesMessage后发送到ActiveMQ:
import org.apache.activemq.ActiveMQConnectionFactory; import jakarta.jms.*; import java.io.ByteArrayOutputStream; import java.io.IOException; // 初始化ActiveMQ连接 ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616"); Connection connection = connectionFactory.createConnection(); connection.start(); // 创建会话和生产者 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Destination mmsQueue = session.createQueue("MMS_Delivery_Queue"); MessageProducer producer = session.createProducer(mmsQueue); // 将MIME消息转为字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); multipart.writeTo(baos); byte[] mmsBytes = baos.toByteArray(); // 创建BytesMessage并写入内容 BytesMessage mmsMessage = session.createBytesMessage(); mmsMessage.writeBytes(mmsBytes); // 添加消息属性,方便接收端识别MIME类型 mmsMessage.setStringProperty("Content-Type", multipart.getContentType()); // 发送消息 producer.send(mmsMessage); // 释放资源 producer.close(); session.close(); connection.close();
3. 接收端解析MMS消息
接收端读取BytesMessage的字节数组,再转回MimeMultipart来提取文本和附件:
import jakarta.jms.*; import org.apache.activemq.ActiveMQConnectionFactory; import jakarta.mail.BodyPart; import jakarta.mail.internet.MimeMultipart; import jakarta.mail.util.ByteArrayDataSource; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; Connection connection = connectionFactory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(mmsQueue); Message receivedMsg = consumer.receive(); if (receivedMsg instanceof BytesMessage) { BytesMessage bytesMsg = (BytesMessage) receivedMsg; byte[] mmsBytes = new byte[(int) bytesMsg.getBodyLength()]; bytesMsg.readBytes(mmsBytes); // 转回MIME多部分消息 ByteArrayDataSource dataSource = new ByteArrayDataSource( new ByteArrayInputStream(mmsBytes), bytesMsg.getStringProperty("Content-Type") ); MimeMultipart receivedMultipart = new MimeMultipart(dataSource); // 遍历各部分提取内容 for (int i = 0; i < receivedMultipart.getCount(); i++) { BodyPart part = receivedMultipart.getBodyPart(i); if (part.isMimeType("text/plain")) { System.out.println("MMS正文:" + part.getContent()); } else if (part.isMimeType("image/*") || part.isMimeType("video/*")) { // 保存附件到本地 String fileName = part.getFileName(); FileOutputStream fos = new FileOutputStream("/path/to/save/" + fileName); part.getDataHandler().writeTo(fos); fos.close(); System.out.println("已保存附件:" + fileName); } } } // 释放资源 consumer.close(); session.close(); connection.close();
依赖配置:确保项目引入ActiveMQ客户端和Jakarta Mail依赖(Maven示例):
<!-- ActiveMQ客户端 --> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-client</artifactId> <version>5.16.7</version> </dependency> <!-- Jakarta Mail --> <dependency> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> <version>2.0.1</version> </dependency>大附件优化:如果附件很大(比如几百MB的视频),建议用ActiveMQ的
BlobMessage替代BytesMessage——它支持把大对象存储到文件系统或数据库,不会把整个内容加载到内存:BlobMessage blobMsg = session.createBlobMessage(new File("/path/to/large-mms.mime")); producer.send(blobMsg);注意:使用
BlobMessage需要在ActiveMQ配置文件中开启相关支持。消息大小限制:ActiveMQ默认限制单条消息大小为100MB,如果你的MMS超过这个值,需要修改
activemq.xml中的systemUsage配置,调整memoryUsage和storeUsage的上限。
内容的提问来源于stack exchange,提问作者sunshine

