JMS实例

准备:myeclipse5.5+jdk1.5+JBoss 4.0.1

1.导入jms.jar文件,消息发送类
package com.test.common.msg;

import java.io.Serializable;
import java.util.Properties;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.jms.DeliveryMode;


public class MsgSender implements MessageListener {
private static Context context = null;

private boolean transacted = false;

private int acknowledgementMode = Session.AUTO_ACKNOWLEDGE;

private TopicConnectionFactory topicConnectionFactory = null;

private static TopicConnection topicConnection = null;

private TopicSession topicSession = null;

private TopicPublisher topicPublisher = null;

private Topic topic = null;

private String topicConnectionFactoryName = null;

private String publishTopicName = "topic/OPER_MSG";

private String subscribeTopicName = null;

private String clientId = null;

private String durableName = "";

private boolean durable = false;

private String provider_url = null;

private static MsgSender _instance = null;

/**
* 构造函数
*/
private MsgSender() {
provider_url = "jnp://127.0.0.1" + ":1099";
}

synchronized static public MsgSender instance() {
if (null == _instance) {
_instance = new MsgSender();
}
return _instance;
}

public void init(String serverIP) {
provider_url = "jnp://" + serverIP + ":1099";
}

public boolean isTransacted() {
return transacted;
}

public void setTransacted(boolean transacted) {
this.transacted = transacted;
}

public int getAcknowledgementMode() {
return acknowledgementMode;
}

public void setAcknowledgementMode(int acknowledgementMode) {
this.acknowledgementMode = acknowledgementMode;
}

public String getTopicConnectionFactoryName() {
return topicConnectionFactoryName;
}

public void setTopicConnectionFactoryName(String topicConnectionFactoryName) {
this.topicConnectionFactoryName = topicConnectionFactoryName;
}

public String getPublishTopicName() {
return publishTopicName;
}

public void setPublishTopicName(String publishTopicName) {
this.publishTopicName = publishTopicName;
}

public String getSubscribeTopicName() {
return subscribeTopicName;
}

public void setSubscribeTopicName(String subscribeTopicName) {
this.subscribeTopicName = subscribeTopicName;
}

public String getClientId() {
return clientId;
}

public void setClientId(String clientId) {
this.clientId = clientId;
}

public String getDurableName() {
return durableName;
}

public void setDurableName(String durableName) {
this.durableName = durableName;
}

public boolean isDurable() {
return durable;
}

public void setDurable(boolean durable) {
this.durable = durable;
}

private Context getInitialContext() throws Exception {
Properties properties = null;
try {

properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
properties.put(Context.PROVIDER_URL, provider_url);

return new InitialContext(properties);
} catch (Exception e) {
throw e;
}
}

private Context getContext() throws Exception {
if (context == null) {
try {
context = getInitialContext();
} catch (Exception ex) {
throw ex;
}
}
return context;
}

public TopicConnectionFactory getTopicConnectionFactory() throws Exception {
if (topicConnectionFactory == null) {
Object obj = getContext().lookup("ConnectionFactory");
topicConnectionFactory = (TopicConnectionFactory) obj;
}
return topicConnectionFactory;
}

public TopicConnection getTopicConnection(boolean consumer)
throws Exception {
if (topicConnection == null) {
topicConnection = getTopicConnectionFactory()
.createTopicConnection();
topicConnection.start();
}
return topicConnection;
}

public TopicConnection reConnection() throws Exception {
close();
topicConnection = getTopicConnectionFactory().createTopicConnection();
topicConnection.start();
return topicConnection;
}

public TopicSession getTopicSession(boolean consumer) throws Exception {
if (topicSession == null) {
topicSession = getTopicConnection(consumer).createTopicSession(
isTransacted(), getAcknowledgementMode());
}
return topicSession;
}

public Topic getPublishTopic() throws Exception {
if (topic == null) {
Object obj = getContext().lookup(publishTopicName);
topic = (Topic) obj;
}
return topic;
}

public Topic getSubscribeTopic() throws Exception {
if (topic == null) {
Object obj = getContext().lookup(subscribeTopicName);
topic = (Topic) obj;
}
return topic;
}

public TopicPublisher getTopicPublisher() throws Exception {
if (topicPublisher == null) {
topicPublisher = getTopicSession(false).createPublisher(
getPublishTopic());
}
return topicPublisher;
}

public void publishText(String message) throws Exception {
TextMessage textMessage = getTopicSession(false).createTextMessage();
textMessage.clearBody();
textMessage.setText(message);
getTopicPublisher().publish(textMessage);
if (isTransacted()) {
getTopicSession(false).commit();
}
}

public void publishObject(Serializable message) throws Exception {
ObjectMessage objectMessage = getTopicSession(false)
.createObjectMessage();
objectMessage.clearBody();
objectMessage.setObject(message);
getTopicPublisher().publish(objectMessage);
if (isTransacted()) {
getTopicSession(false).commit();
}
}

public void publishObject(Serializable message, int type) throws Exception {
publishObject(message, "type", type);

}

protected void publishObject(Serializable message, String propertyName,
int propertyValue) throws Exception {
ObjectMessage objectMessage = getTopicSession(false)
.createObjectMessage();
objectMessage.clearBody();
objectMessage.clearProperties();
objectMessage.setObject(message);
objectMessage.setIntProperty(propertyName, propertyValue);
getTopicPublisher().publish(objectMessage, DeliveryMode.PERSISTENT, 8,
30 * 60 * 1000);
if (isTransacted()) {
getTopicSession(false).commit();
}
}

public void onMessage(Message message) {
}

public void close() throws Exception {
if (topicPublisher != null) {
topicPublisher.close();
topicPublisher = null;
}

if (topicSession != null) {
topicSession.close();
topicSession = null;
}

if (topicConnection != null) {
topicConnection.close();
topicConnection = null;
}
}
} 可以把要发送的信息都放在一个VO类里面,再把VO打成jar加到客户端的项目类里,如TestVO.calss类。使用publishObject方法去发送。TopicName最为关键,因为在jboss里面也是通过TopicName去配置
jboss/server/default/deploy/jms/下jbossmq-destinations-service.xml配置
<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: jbossmq-destinations-service.xml,v 1.4.6.1 2004/11/16 04:32:39 ejort Exp $ -->

<!--
| This file defines the default Queues and Topics that JBossMQ
| ships with. The default Queues and Topics are used by the
| JBoss test suite and by the sample jms programs.
|
| You can add other destinations to this file, or you can create other
| *-service.xml files to contain your application's destinations.
-->

<server>
<!-- Destination without a configured SecurityManager or without a
a SecurityConf will default to role guest with read=true, write=true,
create=false.
-->
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=testTopic">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=OPER_MSG">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=LUNPAN_OPER_MSG">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=testDurableTopic">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>

<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=testQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="MessageCounterHistoryDayLimit">-1</attribute>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="noacc" read="false" write="false" create="false"/>
</security>
</attribute>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=A">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=B">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=C">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=D">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=ex">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Jboss/server/default/conf下jbossmq-state.xml
<?xml version="1.0" encoding="UTF-8"?>
<StateManager>
<Users>
<User>
<Name>u0</Name>
<Password>123456</Password>
<Id>ID:00</Id>
</User>
<User>
<Name>u1</Name>
<Password>123456</Password>
<Id>ID:01</Id>
</User>
<User>
<Name>u2</Name>
<Password>123456</Password>
<Id>ID:02</Id>
</User>
<User>
<Name>u3</Name>
<Password>123456</Password>
<Id>ID:03</Id>
</User>
<User>
<Name>u4</Name>
<Password>123456</Password>
<Id>ID:04</Id>
</User>
<User>
<Name>u5</Name>
<Password>123456</Password>
<Id>ID:05</Id>
</User>
<User>
<Name>u6</Name>
<Password>123456</Password>
<Id>ID:06</Id>
</User>
<User>
<Name>j2ee</Name>
<Password>j2ee</Password>
</User>
<User>
<Name>john</Name>
<Password>needle</Password>
<Id>DurableSubscriberExample</Id>
</User>
<User>
<Name>guest</Name>
<Password>guest</Password>
</User>
<User>
<Name>nobody</Name>
<Password>nobody</Password>
</User>
<User>
<Name>dynsub</Name>
<Password>dynsub</Password>
</User>
</Users>
<Roles>
<Role name="guest">
<UserName>j2ee</UserName>
<UserName>guest</UserName>
<UserName>john</UserName>
</Role>
<Role name="subscriber">
<UserName>john</UserName>
<UserName>u0</UserName>
<UserName>u1</UserName>
<UserName>u2</UserName>
<UserName>u3</UserName>
<UserName>u4</UserName>
<UserName>u5</UserName>
<UserName>u6</UserName>
</Role>
<Role name="publisher">
<UserName>john</UserName>
<UserName>dynsub</UserName>
<UserName>u0</UserName>
<UserName>u1</UserName>
<UserName>u2</UserName>
<UserName>u3</UserName>
<UserName>u4</UserName>
<UserName>u5</UserName>
<UserName>u6</UserName>
<UserName>u7</UserName>
<UserName>u8</UserName>
<UserName>u9</UserName>
<UserName>u10</UserName>
</Role>
<Role name="durpublisher">
<UserName>john</UserName>
<UserName>dynsub</UserName>
<UserName>u0</UserName>
<UserName>u1</UserName>
<UserName>u2</UserName>
<UserName>u3</UserName>
<UserName>u4</UserName>
<UserName>u5</UserName>
<UserName>u6</UserName>
</Role>
<Role name="noacc">
<UserName>nobody</UserName>
</Role>
</Roles>
<DurableSubscriptions>
<DurableSubscription>
<ClientID>ID:00</ClientID>
<Name>u1</Name>
<TopicName>OPER_MSG</TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:01</ClientID>
<Name>topic/OPER_MSG</Name>
<TopicName>OPER_MSG</TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:02</ClientID>
<Name>topic/OPER_MSG </Name>
<TopicName> OPER_MSG </TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:03</ClientID>
<Name>topic/OPER_MSG </Name>
<TopicName> OPER_MSG </TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:04</ClientID>
<Name>topic/OPER_MSG</Name>
<TopicName>OPER_MSG</TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:05</ClientID>
<Name>topic/OPER_MSG</Name>
<TopicName>OPER_MSG</TopicName>
</DurableSubscription>
<DurableSubscription>
<ClientID>ID:06</ClientID>
<Name>topic/OPER_MSG</Name>
<TopicName>OPER_MSG</TopicName>
</DurableSubscription>
</DurableSubscriptions>
</StateManager>
2 JMSR消息接收(导入TestVO.jar)
定义个接口MsgListener
package com.test.common.msg;

import java.io.Serializable;

public interface MsgListener {
public void onMessage(int type, Serializable obj);
} 消息接收类
package com.granddragon.common.msg;

import java.util.Properties;
import javax.jms.Topic;
import javax.naming.NamingException;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.jms.TopicConnection;
import javax.jms.Message;
import javax.jms.TopicSubscriber;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import java.io.Serializable;
import com.granddragon.common.thread.SimpleThreadPool;
import javax.jms.ExceptionListener;

public class MsgReciever {
private String url_;

private class listener implements Runnable, ExceptionListener {

private TopicSubscriber recv = null;

private String name_ = "topic/OPER_MSG";

private TopicConnection conn = null;

private TopicSession session = null;

private Topic topic = null;

private Context context = null;

public listener() {
super();
try {
this.initializeListener();
} catch (Exception e) {
System.out.println("Error creating listener: " + e);
e.printStackTrace();
}

}

public void onException(JMSException jMSException) {
System.out.println("JMS connection disconnection");
}

public void run() {
Serializable obj = null; // sequence
String sid = "";

sid = "u" + String.valueOf(clientNum);
while (true) {
Object tmp = null;
try {
tmp = context.lookup("ConnectionFactory"); // The jboss
// config file
// info
} catch (NamingException ex4) {
ex4.printStackTrace();
try {
Thread.sleep(1000); // 线程等待1秒
} catch (InterruptedException ex2) {
}
continue;
}
//System.out.println("lookup completed, making topic");

TopicConnectionFactory tcf = (TopicConnectionFactory) tmp;

try {

conn = tcf.createTopicConnection(sid, "123456");
conn.setExceptionListener(this);
try {
topic = (Topic) context.lookup(name_);
} catch (NamingException ex5) {
ex5.printStackTrace();
try {
Thread.sleep(1000);
} catch (InterruptedException ex3) {
}
continue;
}

session = conn.createTopicSession(false,
TopicSession.AUTO_ACKNOWLEDGE);
conn.start();

recv = session.createDurableSubscriber(topic,
"topic/OPER_MSG");
Message msg = null;

int type = 0;

ObjectMessage objMsg = null;
while (true) {
msg = recv.receive(2000);

if (msg != null) {
objMsg = (ObjectMessage) msg;
type = objMsg.getIntProperty("type");
obj = (Serializable) objMsg.getObject();
task t = new task(type, obj);
pool.processTask(t);
}
}

} catch (JMSException ex) {
try {
System.out.println("JMS connection disconnection");
if (recv != null)
recv.close();
disconnect();

try {
Thread.sleep(1000);
} catch (InterruptedException ex6) {
}

} catch (JMSException ex1) {
ex1.printStackTrace();
}

}
}

}

private void initializeListener() throws InterruptedException {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs",
"org.jboss.naming");
props.setProperty("java.naming.provider.url", url_);
try {
context = new InitialContext(props);
} catch (NamingException ex3) {
}
System.out.println("performing lookup...");

}

public void disconnect() throws JMSException {

if (session != null) {

session.close();
}

if (conn != null) {

conn.close();
}
}

}

private class task implements Runnable {
private int type = 0;

private Serializable obj = null;

public task(int type, Serializable obj) {
this.type = type;
this.obj = obj;
}

public void run() {
if (obj != null && listen != null) {
listen.onMessage(type, obj);
}
}

}

public MsgReciever(String serverIp) {
url_ = "jnp://" + serverIp + ":1099";
this.initThreads = initThreads;
this.maxThreads = maxThreads;
pool = new SimpleThreadPool(initThreads, maxThreads);
listener lis = new listener();
new Thread(lis).start();
}

public MsgReciever(String serverIp, int clientNum) {
this.clientNum = clientNum;
url_ = "jnp://" + serverIp + ":1099";
this.initThreads = initThreads;
this.maxThreads = maxThreads;
pool = new SimpleThreadPool(initThreads, maxThreads);
listener lis = new listener();
new Thread(lis).start();

}

public MsgReciever(String serverIp, int clientNum, int initThreads,
int maxThreads) {
this.clientNum = clientNum;
url_ = serverIp + ":1099";
this.initThreads = initThreads;
this.maxThreads = maxThreads;
pool = new SimpleThreadPool(initThreads, maxThreads);
listener lis = new listener();
new Thread(lis).start();
}

public MsgReciever(String serverIp, int initThreads, int maxThreads) {
url_ = serverIp + ":1099";
this.initThreads = initThreads;
this.maxThreads = maxThreads;
pool = new SimpleThreadPool(initThreads, maxThreads);
listener lis = new listener();
new Thread(lis).start();
}

public void setMsgListener(MsgListener listen) {
this.listen = listen;
}

private int initThreads = 2;

private int maxThreads = 4;

private MsgListener listen = null;

private SimpleThreadPool pool = null;

private int clientNum = 1;

public void onException(JMSException jMSException) {
System.out.println("JMS connection disconnection");

}
}
MsgReciever方法定义接收服务器的IP,配置连接数去接收服务器发来的消息
初始化类里加载
MsgReciever mes = new MsgReciever(IP,连接数);
mes.setMsgListener(new OperatorInfoCalss());
IP就是你接收消息服务器的IP,刚才发送的JMS在jboss里配置最大到6,就是连接数1到6都可以OperatorInfoCalss里面去接收消息
public class OperatorInfoCalss implements MsgListener {
public void onMessage(int type, Serializable obj) {
MessageGameInfoVo vo = (TestVO) obj;
}
}
收消息的jboss配置和发送的相同。。。。。。。。。。。
JMS(Java Message Service,Java消息服务)是一组Java应用程序接口(Java API),它提供创建、发送、接收、读取消息的服务。由Sun公司和它的合作伙伴设计的JMS API定义了一组公共的应用程序接口和相应语法,使得Java程序能够和其他消息组件进行通信。

JMS是一种与厂商无关的 API,用来访问消息收发系统。它类似于 JDBC (Java Database Connectivity):这里,JDBC 是可以用来访问许多不同关系数据库的 API,而 JMS 则提供同样与厂商无关的访问方法,以访问消息收发服务。许多厂商目前都支持 JMS,包括 IBM 的 MQSeries、BEA的 Weblogic JMS service和 Progress 的 SonicMQ,这只是几个例子。
JMS 使您能够通过消息收发服务(有时称为消息中介程序或路由器)从一个 JMS 客户机向另一个 JML 客户机发送消息。消息是 JMS 中的一种类型对象,由两部分组成:报头和消息主体。报头由路由信息以及有关该消息的元数据组成。消息主体则携带着应用程序的数据或有效负载。根据有效负载的类型来划分,可以将消息分为几种类型,它们分别携带:简单文本 (TextMessage)、可序列化的对象 (ObjectMessage)、属性集合 (MapMessage)、字节流 (BytesMessage)、原始值流 (StreamMessage),还有无有效负载的消息 (Message)。

消息收发系统是异步的,也就是说,JMS 客户机可以发送消息而不必等待回应。比较可知,这完全不同于基于 RPC 的(基于远程过程的)系统,如 EJB 1.1、CORBA 和 Java RMI 的引用实现。在 RPC 中,客户机调用服务器上某个分布式对象的一个方法。在方法调用返回之前,该客户机被阻塞;该客户机在可以执行下一条指令之前,必须等待方法调用结束。在 JMS 中,客户机将消息发送给一个虚拟通道(主题或队列),而其它 JMS 客户机则预订或监听这个虚拟通道。当 JMS 客户机发送消息时,它并不等待回应。它执行发送操作,然后继续执行下一条指令。消息可能最终转发到一个或许多个客户机,这些客户机都不需要作出回应。

  JMS的通用接口集合以异步方式发送或接收消息。异步方式接收消息显然是使用间断网络连接的客户机,诸如移动电话和PDA的最好的选择。另外, JMS采用一种宽松结合方式整合企业系统的方法,其主要的目的就是创建能够使用跨平台数据信息的、可移植的企业级应用程序,而把开发人力解放出来。

  Java消息服务支持两种消息模型:Point-to-Point消息(P2P)和发布订阅消息(Publish Subscribe messaging,简称Pub/Sub)。JMS规范并不要求供应商同时支持这两种消息模型,但开发者应该熟悉这两种消息模型的优势与缺点。

  P2P消息模型是在点对点之间传递消息时使用。如果应用程序开发者希望每一条消息都能够被处理,那么应该使用P2P消息模型。与Pub/Sub消息模型不同,P2P消息总是能够被传送到指定的位置。

  Pub/Sub模型在一到多的消息广播时使用。如果一定程度的消息传递的不可靠性可以被接受的话,那么应用程序开发者也可以使用Pub/Sub消息模型。换句话说,它适用于所有的消息消费程序并不要求能够收到所有的信息或者消息消费程序并不想接收到任何消息的情况。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值