RabbitMQ

直连模型

项目整体视图

在这里插入图片描述

导入依赖

       <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.14.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

创建生产者Producer

package a_direct;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;

//消息的生产者
public class Producer {
    @Test
    public void sendMessage() throws Exception{
        //1、创建一个连接工厂
        ConnectionFactory connectionFactory=new ConnectionFactory();
        //2、设置相关的参数
        connectionFactory.setHost("39.105.127.232");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("sxt");//设置用户密码
        connectionFactory.setPassword("123456");
        connectionFactory.setVirtualHost("/v-sxt");//虚拟主机
        //3、从链接工厂里面创建一个链接
        Connection connection = connectionFactory.newConnection();
        //4、创建一个通道
        Channel channel = connection.createChannel();
        /*****
         * 5、绑定队列
         * 参数1、队列名、如果发送消息时、队列mq里面不存在、他会创建一个新的队列
         * 参数2、是否持久化、如果为false,当mq重启时、消息会丢失
         * 参数3、是否独享、true代表只有当前的connection可以访问到这个队列
         * 参数4、是否自动删除、是否用完之后就删除这个队列
         * 参数5、其他参数
         */
        channel.queueDeclare("hello",true,false,false,null);
        /****
         * 6、发消息
         * 参数1、交换机
         * 参数2、队列名
         * 参数3、相关属性
         * 参数4、消息体
         */
        channel.basicPublish("","hello",null,"hello rabbitmq".getBytes());
        //7、关闭通道和连接
        channel.close();
        connection.close();
        System.out.println("消息发送成功");
    }
}

创建消费者Consumer

package a_direct;

import com.rabbitmq.client.*;
import org.junit.Test;

import java.io.IOException;

//消息的生产者
public class Consumer {
    @Test
    public void sendMessage() throws Exception{
        //1、创建一个连接工厂
        ConnectionFactory connectionFactory=new ConnectionFactory();
        //2、设置相关的参数
        connectionFactory.setHost("39.105.127.232");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("sxt");//设置用户密码
        connectionFactory.setPassword("123456");
        connectionFactory.setVirtualHost("/v-sxt");//虚拟主机
        //3、从链接工厂里面创建一个链接
        Connection connection = connectionFactory.newConnection();
        //4、创建一个通道
        Channel channel = connection.createChannel();
        /*****
         * 5、绑定队列
         * 参数1、队列名、如果发送消息时、队列mq里面不存在、他会创建一个新的队列
         * 参数2、是否持久化、如果为false,当mq重启时、消息会丢失
         * 参数3、是否独享、true代表只有当前的connection可以访问到这个队列
         * 参数4、是否自动删除、是否用完之后就删除这个队列
         * 参数5、其他参数
         */
        channel.queueDeclare("hello",true,false,false,null);

        channel.basicConsume("hello",true,new DefaultConsumer(channel){
            /***
             * @param consumerTag
             * @param envelope
             * @param properties
             * @param body 消息体
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者接收到消息:"+new String(body));
                //super.handleDelivery(consumerTag, envelope, properties, body);
            }
        });
        //不能让程序结束
        System.in.read();


//        //7、关闭通道和连接
//        channel.close();
//        connection.close();
//        System.out.println("消息发送成功");
    }
}

编写工具类优化代码

项目整体视图
在这里插入图片描述

生产者Producer

package a_direct;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
import utils.RabbitMQUtils;

//消息的生产者
public class Producer {
    @Test
    public void sendMessage() throws Exception{
//        //1、创建一个连接工厂
//        ConnectionFactory connectionFactory=new ConnectionFactory();
//        //2、设置相关的参数
//        connectionFactory.setHost("39.105.127.232");
//        connectionFactory.setPort(5672);
//        connectionFactory.setUsername("sxt");//设置用户密码
//        connectionFactory.setPassword("123456");
//        connectionFactory.setVirtualHost("/v-sxt");//虚拟主机
//        //3、从链接工厂里面创建一个链接
//        Connection connection = connectionFactory.newConnection();
        Connection connection = RabbitMQUtils.getConnection();
        //4、创建一个通道
        Channel channel = connection.createChannel();
        /*****
         * 5、绑定队列
         * 参数1、队列名、如果发送消息时、队列mq里面不存在、他会创建一个新的队列
         * 参数2、是否持久化、如果为false,当mq重启时、消息会丢失
         * 参数3、是否独享、true代表只有当前的connection可以访问到这个队列
         * 参数4、是否自动删除、是否用完之后就删除这个队列
         * 参数5、其他参数
         */
         
        channel.queueDeclare("hello",true,false,false,null);要想消息持久化就要设置上面那行的参数
        /****
         * 6、发消息
         * 参数1、交换机
         * 参数2、队列名
         * 参数3、相关属性
         * 参数4、消息体
         */
          channel.basicPublish("","hello", MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());
        //channel.basicPublish("","hello",null,"hello rabbitmq".getBytes());要想消息持久化就要设置上面那行的参数
        //7、关闭通道和连接
//        channel.close();
//        connection.close();
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
        System.out.println("消息发送成功");
    }
}

消费者Consumer

package a_direct;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消息的生产者
public class Consumer {
    @Test
    public void sendMessage() throws Exception{
//        //1、创建一个连接工厂
//        ConnectionFactory connectionFactory=new ConnectionFactory();
//        //2、设置相关的参数
//        connectionFactory.setHost("39.105.127.232");
//        connectionFactory.setPort(5672);
//        connectionFactory.setUsername("sxt");//设置用户密码
//        connectionFactory.setPassword("123456");
//        connectionFactory.setVirtualHost("/v-sxt");//虚拟主机
//        //3、从链接工厂里面创建一个链接
//       
        Connection connection = RabbitMQUtils.getConnection();
        //4、创建一个通道
        Channel channel = connection.createChannel();
        /*****
         * 5、绑定队列
         * 参数1、队列名、如果发送消息时、队列mq里面不存在、他会创建一个新的队列
         * 参数2、是否持久化、如果为false,当mq重启时、消息会丢失
         * 参数3、是否独享、true代表只有当前的connection可以访问到这个队列
         * 参数4、是否自动删除、是否用完之后就删除这个队列
         * 参数5、其他参数
         */
        channel.queueDeclare("hello",true,false,false,null);

        channel.basicConsume("hello",true,new DefaultConsumer(channel){
            /***
             * @param consumerTag
             * @param envelope
             * @param properties
             * @param body 消息体
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者接收到消息:"+new String(body));
                //super.handleDelivery(consumerTag, envelope, properties, body);
            }
        });
        //不能让程序结束
        System.in.read();


//        //7、关闭通道和连接
//        channel.close();
//        connection.close();
//        System.out.println("消息发送成功");
    }
}

工具类RabbitMQUtils

package utils;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

//工具类
public class RabbitMQUtils {
    private static ConnectionFactory connectionFactory;
    static {
        connectionFactory=new ConnectionFactory();
        //2、设置相关的参数
        connectionFactory.setHost("39.105.127.232");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("sxt");//设置用户密码
        connectionFactory.setPassword("123456");
        connectionFactory.setVirtualHost("/v-sxt");//虚拟主机
    }
    /**
     * 得到连接的方法
     */
    public static Connection getConnection(){
        try {
            //从链接工厂里面创建一个链接
            Connection connection = connectionFactory.newConnection();
            return connection;
        }catch (Exception e){
            System.out.println(e);
        }
        return null;
    }
    /**
     * 关闭连接的方法
     */
    public static void closeChannelAndConnection(Channel channel,Connection connection){
        try {
            if(null!=channel) channel.close();
            if (null!=connection) connection.close();
        }catch (Exception e){
            System.out.println(e);
        }
    }
}

work queue

整体视图

在这里插入图片描述
注意:这里的RabbitMQUtils工具类为上种模型所编写

创建生产者

package b_workqueue;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
import utils.RabbitMQUtils;

//生产者
public class Producer {
    @Test
    public void sendMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建信道
        Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare("hello",false,false,false,null);
        //发送消息
        for (int i=1;i<=100;i++){
            channel.basicPublish("","hello",null,("hello rabbitmq-----workqueue"+i).getBytes());
        }
        //关闭
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
        System.out.println("消息发送成功");
    }
}

创建消费者1

package b_workqueue;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者
public class Consumer1 {
    @Test
    public void receiveMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建信道
        Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare("hello",false,false,false,null);
        //接收消息
        channel.basicConsume("hello",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【1】接收消息:"+new String(body));
            }
        });
        System.in.read();
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
    }
}

创建消费者2

package b_workqueue;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者
public class Consumer2 {
    @Test
    public void receiveMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建信道
        Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare("hello",false,false,false,null);
        //接收消息
        channel.basicConsume("hello",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【2】接收消息:"+new String(body));
            }
        });
        System.in.read();
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
    }
}

测试

注意测试的时候要先运行消费者然后再运行生产者,消费者平均消费
在这里插入图片描述

在这里插入图片描述

消息的自动确认机制

在这里插入图片描述
当消费者1的消费能力有限时,此时消费者就不是平均消费,消费者1消费不完的,可由消费者2消费
在这里插入图片描述
在这里插入图片描述

fanout

广播

创建生产者

package c_fanout;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
import utils.RabbitMQUtils;

//生产者
public class Proudcer {
    @Test
    public void senMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.FANOUT);
        //向交换机发消息
        channel.basicPublish("logs","",null,"我是一个fanout类型的消息".getBytes());
        //关闭
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
        System.out.println("消息发送成功");
    }
}

创建消费者1

package c_fanout;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者1
public class Consumer1 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.FANOUT);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"logs","");
        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【1】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【1】启动成功");
        System.in.read();
    }
}

创建消费者2

package c_fanout;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者2
public class Consumer2 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.FANOUT);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"logs","");
        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【2】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【2】启动成功");
        System.in.read();
    }
}

测试

在这里插入图片描述
在这里插入图片描述

Routing-Direct

路由-直连

创建生产者

package d_routing_direct;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
import utils.RabbitMQUtils;

//生产者
public class Proudcer {
    @Test
    public void senMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.DIRECT);
        //向交换机发消息 发送了四条消息,分别指定了路由key
        channel.basicPublish("logs","info",null,"我是一个routingkey-Direct类型的消息-info".getBytes());
        channel.basicPublish("logs","warn",null,"我是一个routingkey-Direct类型的消息-warn".getBytes());
        channel.basicPublish("logs","debug",null,"我是一个routingkey-Direct类型的消息-debug".getBytes());
        channel.basicPublish("logs","error",null,"我是一个routingkey-Direct类型的消息-error".getBytes());

        //关闭
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
        System.out.println("消息发送成功");
    }
}

创建消费者1

package d_routing_direct;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者1
public class Consumer1 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.DIRECT);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"logs","info");
        channel.queueBind(queue,"logs","warn");
        channel.queueBind(queue,"logs","debug");
        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【info】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【info】启动成功");
        System.in.read();
    }
}

创建消费者2

package d_routing_direct;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者2
public class Consumer2 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("logs", BuiltinExchangeType.DIRECT);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"logs","error");
        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【error】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【error】启动成功");
        System.in.read();
    }
}

测试

在这里插入图片描述
在这里插入图片描述

Routing-Topic

.*匹配一个
.#匹配0个或多个

生产者

package e_routing_topic;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import org.junit.Test;
import utils.RabbitMQUtils;

//生产者
public class Proudcer {
    @Test
    public void senMessage() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("topic", BuiltinExchangeType.TOPIC);
        //向交换机发消息 发送了四条消息,分别指定了路由key
        channel.basicPublish("topic","user.insert",null,"我是一个routingkey-Topic类型的消息-user.insert".getBytes());
        channel.basicPublish("topic","user.insert.a",null,"我是一个routingkey-Topic类型的消息-user.insert.a".getBytes());
        //关闭
        RabbitMQUtils.closeChannelAndConnection(channel,connection);
        System.out.println("消息发送成功");
    }
}

消费者1

package e_routing_topic;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者1
public class Consumer1 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("topic", BuiltinExchangeType.TOPIC);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"topic","user.*");

        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【*】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【*】启动成功");
        System.in.read();
    }
}

消费者2

package e_routing_topic;

import com.rabbitmq.client.*;
import org.junit.Test;
import utils.RabbitMQUtils;

import java.io.IOException;

//消费者1
public class Consumer2 {
    @Test
    public void Message() throws Exception{
        Connection connection = RabbitMQUtils.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        //设置交换机
        channel.exchangeDeclare("topic", BuiltinExchangeType.TOPIC);
       //从通道里面得到一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //把临时队列和交换机进行绑定
        channel.queueBind(queue,"topic","user.#");

        //接受消息
        channel.basicConsume(queue,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者【#】接收到消息是:"+new String(body));
            }
        });
        System.out.println("消费者【#】启动成功");
        System.in.read();
    }
}

测试

在这里插入图片描述
在这里插入图片描述

集成spring boot-直连

两个spring boot项目

生产者测试类

package com.sxt;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class RabbitmqSpringbootProducerApplicationTests {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
        System.out.println(rabbitTemplate);
    }
    /**
     *第一种模式的消息发送
     */
    @Test
    void testHello(){
        rabbitTemplate.convertAndSend("hello","hello world");
        System.out.println("消息发送成功");
    }

}

yml配置文件

server:
  port: 8001
spring:
  application:
    name: producer
  rabbitmq:
    host: 39.105.127.232
    port: 5672
    username: user
    password: 123456
    virtual-host: /v-sxt

编写生产者HelloConfig配置

package com.sxt.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HelloConfig {
    //创建一个队列
    @Bean
    public Queue hello(){//ctrl + p 显示其他参数   这里可以和hello项目一样设置五个参数
        Queue hello = new Queue("hello");
        return hello;
    }
}

消费者HelloConsumer

package com.sxt.consumer;

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queuesToDeclare = {@Queue("hello")})
public class HelloConsumer {
    @RabbitHandler
    public void receive(String body){
        System.out.println("消费者收到消息,内容为:"+body);
    }
}

消费者与生产者的yml配置文件一样,先启动生产者再启动消费者

测试

在这里插入图片描述

在这里插入图片描述

集成spring boot-work

生产者测试类

    @Test
    void testWork(){
        for (int i=1;i<=10;i++){
            rabbitTemplate.convertAndSend("work","hello work--"+i);
        }
        System.out.println("消息全部发送成功");
    }

生产者配置类WorkConfig

package com.sxt.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WorkConfig {
    //创建一个队列
    @Bean
    public Queue work(){//ctrl + p 显示其他参数   这里可以和hello项目一样设置五个参数
        Queue work = new Queue("work");
        return work;
    }
}

消费者配置类WorkConsumer

package com.sxt.consumer;

import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component

public class WorkConsumer {
    @RabbitListener(queuesToDeclare = {@Queue("work")})
    public void receive1(String body){
        System.out.println("消费者[1]收到消息,内容为:"+body);
    }

    @RabbitListener(queuesToDeclare = {@Queue("work")})
    public void receive2(String body){
        System.out.println("消费者[2]收到消息,内容为:"+body);
    }
}

测试

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值