首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >rabbitmq系列(二)五种常见模式

rabbitmq系列(二)五种常见模式

原创
作者头像
Java旅途
修改于 2020-06-28 02:21:33
修改于 2020-06-28 02:21:33
8510
举报
文章被收录于专栏:Java旅途Java旅途

一、简单模式

原理:生产者将消息交给默认的交换机,交换机获取消息后交给绑定这个生产者的队列(投递规则为队列名称和routing key 相同的队列),监听当前队列的消费者获取信息并执行消费逻辑。

简单模式.png
简单模式.png

场景:有一个oa系统,用户通过接收手机验证码进行注册,页面上点击获取验证码后,将验证码放到消息队列,然后短信服务从队列中获取到验证码,并发送给用户。

实现

生产者:

代码语言:txt
AI代码解释
复制
public class Producter {

    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();
        // 4. 通过channel发布消息
        /**
         * 四个参数:
         * 第一个参数是交换机的名称
         * 第二个参数是路由键
         * 第三个参数标识消息的一些额外的属性
         * 第四个是消息的具体的内容
         */
        String message = "字节";
        for(int i = 0;i < 5;i   ){

            channel.basicPublish("","byte001",null,message.getBytes());
        }
        // 5. 释放资源,释放channel 和 链接对象

        channel.close();
        connection.close();
    }
}

消费者:

代码语言:txt
AI代码解释
复制
public class Consumer {

    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        // 4. 创建出消息队列
        /**
         * 第一个参数是消息队列的名称
         * 第二个参数表示消息是否持久化
         * 第三个参数标识消息队列是否被channel独占
         * 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
         * 第五个是消息队列扩展参数
         */
        String queueName = "byte001";
        channel.queueDeclare(queueName, true, false, false, null);

        // 5. 创建消费者,对消息进行处理
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("获取到的消息:" s);
            }
        };
        // 6. 通过channel消费者和消息队列关联
        /**
         * 第一个参数是消息队列的名字
         * 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
         * 第三个参数是消费者
         */
        channel.basicConsume(queueName, true, consumer);
    }
}

二、工作模式

原理:生产者将消息交给交换机,交换机交给绑定的队列,队列有多个消费者监听,一条消息只能由一个消费者消费,这样就形成了资源竞争,谁的资源空闲大,争抢到的可能性就大。

工作模式.png
工作模式.png

场景:有一个电商平台,有两个订单服务,用户下单的时候,任意一个订单服务消费用户的下单请求生成订单即可。不用两个订单服务同时消费用户的下单请求。

实现

生产者:

代码语言:txt
AI代码解释
复制
public class Producter {

    public static final String QUEUE_NAME = "byte002";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        // 申明队列
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        // 4. 通过channel发布消息
        /**
         * 四个参数:
         * 第一个参数是交换机的名称
         * 第二个参数是路由键
         * 第三个参数标识消息的一些额外的属性
         * 第四个是消息的具体的内容
         */
        String message = "字节";
        for(int i = 0;i < 100;i   ){

            channel.basicPublish("",QUEUE_NAME,null,(message i).getBytes());
        }
        // 5. 释放资源,释放channel 和 链接对象

        channel.close();
        connection.close();
    }
}

消费者1:

代码语言:txt
AI代码解释
复制
public class Consumer {

    public static final String QUEUE_NAME = "byte002";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        // 4. 创建出消息队列
        /**
         * 第一个参数是消息队列的名称
         * 第二个参数表示消息是否持久化
         * 第三个参数标识消息队列是否被channel独占
         * 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
         * 第五个是消息队列扩展参数
         */
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.basicQos(1); // 告诉服务器,在我们没有确认当前消息时不要给我们发送新的消息
        // 5. 创建消费者,对消息进行处理
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者1收到的内容:" s);
                try {
                    Thread.sleep(10); // 模拟消费耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag(),false); // 参数2false为确认收到消息,true为拒绝收到消息
            }
        };
        // 6. 通过channel消费者和消息队列关联
        /**
         * 第一个参数是消息队列的名字
         * 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
         * 第三个参数是消费者
         */
        channel.basicConsume(QUEUE_NAME, false, consumer);
    }
}

消费者2:

代码语言:txt
AI代码解释
复制
public class Consumer2 {

    public static final String QUEUE_NAME = "byte002";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        // 4. 创建出消息队列
        /**
         * 第一个参数是消息队列的名称
         * 第二个参数表示消息是否持久化
         * 第三个参数标识消息队列是否被channel独占
         * 第四个参数标识是否自动删除消息队列,当消息队列没有绑定交换机后是否自动删除
         * 第五个是消息队列扩展参数
         */
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.basicQos(1); // 告诉服务器,在我们没有确认当前消息时不要给我们发送新的消息
        // 5. 创建消费者,对消息进行处理
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者2收到的内容:" s);
                try {
                    Thread.sleep(500); // 模拟消费耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag(),false); // 参数2false为确认收到消息,true为拒绝收到消息
            }
        };
        // 6. 通过channel消费者和消息队列关联
        /**
         * 第一个参数是消息队列的名字
         * 第二个参数是否自动签收(即消费消息后告知服务器已被消费)
         * 第三个参数是消费者
         */
        channel.basicConsume(QUEUE_NAME, false, consumer);
    }
}

保证资源竞争的代码就是这一行channel.basicQos(1);如果不加这一行,我们会发现两个消费者是轮询消费消息的。

三、发布订阅模式

原理:生产者将消息扔给交换机,交换机类型是fanout,不同的队列注册到交换机上,不同的消费注册在不同的队列上。所有消费者都会收到消息。

发布订阅模式.png
发布订阅模式.png

场景:有一个商城,我们新添加一个商品后,可能同时需要去更新缓存和数据库

实现:

生产者:

代码语言:txt
AI代码解释
复制
public class Producter {

    // 定义交换机的名字
    public static final String EXCHANGE_NAME="byte003";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();
        // 定义一个交换机,类型是fanout
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");

        // 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
        channel.basicPublish(EXCHANGE_NAME,"",null,"发布订阅模式的消息".getBytes());

        channel.close();
        connection.close();
    }
}

消费者1:

代码语言:txt
AI代码解释
复制
public class Consumer1 {
    public static final String EXCHANGE_NAME="byte003";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue003";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者1:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

消费者2:

代码语言:txt
AI代码解释
复制
public class Consumer2 {
    public static final String EXCHANGE_NAME="byte003";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue004";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者2:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

需要注意的一点就是交换机没有保存功能,如果没有消费者,则消息会丢失。

四、路由模式

原理:生产者将消息发送给交换机,消息携带具体的routingkey。交换机类型是direct,接收到消息中的routingkey,比对与之绑定的队列的routingkey,分发到不同的队列上。

路由模式.png
路由模式.png

场景:还是一样,有一个商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,不用刷新缓存。

实现

生产者:

代码语言:txt
AI代码解释
复制
public class Producter {

    // 定义交换机的名字
    public static final String EXCHANGE_NAME="byte004";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();
        // 定义一个交换机,类型是direct
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");

        // 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
        channel.basicPublish(EXCHANGE_NAME,"key1",null,"发布路由模式的消息".getBytes());

        channel.close();
        connection.close();
    }
}

消费者1:

代码语言:txt
AI代码解释
复制
public class Consumer1 {
    public static final String EXCHANGE_NAME="byte004";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue005";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        /**
         * 参数3是routingkey,只有和它一样的routingkey的消息才会被当前消费者收到
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"key1");
        // 如果要接收多个routingkey的消息,在执行一次上面的代码即可,如下
        channel.queueBind(queueName,EXCHANGE_NAME,"key2");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者1:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

消费者2:

代码语言:txt
AI代码解释
复制
public class Consumer2 {
    public static final String EXCHANGE_NAME="byte004";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue006";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"key2");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者2:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

五、主题模式

原理路由模式的一种,路由功能添加了模糊匹配。星号(*)代表1个单词,#号(#)代表一个或多个单词。具体可参考路由模式。

主题模式.png
主题模式.png

场景:还是一样,有一个商城,新添加了一个商品,实时性不是很高,只需要添加到数据库即可,数据库包含了主数据库mysql1和从数据库mysql2的内容,不用刷新缓存。

实现

生产者:

代码语言:txt
AI代码解释
复制
public class Producter {

    // 定义交换机的名字
    public static final String EXCHANGE_NAME="byte004";
    public static void main(String[] args) throws Exception {

        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();
        // 定义一个交换机,类型是topic
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");

        // 因为消息先发到交换机,交换机没有保存功能,所以如果没有消费者,消息会丢失
        channel.basicPublish(EXCHANGE_NAME,"key.1.2",null,"发布路由模式的消息".getBytes());

        channel.close();
        connection.close();
    }
}

消费者1:

代码语言:txt
AI代码解释
复制
public class Consumer1 {
    public static final String EXCHANGE_NAME="byte004";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue005";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        /**
         * 参数3是routingkey,只有和它一样的routingkey的消息才会被当前消费者收到
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"key.*");
        // 如果要接收多个routingkey的消息,在执行一次上面的代码即可,如下
        channel.queueBind(queueName,EXCHANGE_NAME,"abc.#");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者1:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

消费者2:

代码语言:txt
AI代码解释
复制
public class Consumer2 {
    public static final String EXCHANGE_NAME="byte004";

    public static void main(String[] args) throws Exception {


        // 1. 创建出链接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");

        // 2. 通过链接工厂创建链接对象
        Connection connection = factory.newConnection();

        // 3. 通过链接对象创建出channel
        Channel channel = connection.createChannel();

        String queueName = "queue006";
        channel.queueDeclare(queueName,false,false,false,null);

        // 绑定队列到交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"key.#");
        channel.basicQos(1);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            /**
             * consumerTag 用来标识.可以再监听队列时候设置
             * envelope 信封,通过envelope可以通过这个获取到很多东西
             * properties 额外的消息属性
             * body:消息体
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                String s = new String(body, "UTF-8");
                System.out.println("消费者2:" s);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        };
        channel.basicConsume(queueName,false,consumer);
    }
}

<!-- wp:paragraph -->

<p>代码已上传:</p>

<!-- /wp:paragraph -->

<!-- wp:paragraph -->

<p>github地址: <a href="https://github.com/binzh303/zhixie-code-example">https://github.com/binzh303/zhixie-code-example</a> </p>

<!-- /wp:paragraph -->

<!-- wp:paragraph -->

<p>gitee地址: <a href="https://gitee.com/javaXiaoCaiJi/zhixie-code-example">https://gitee.com/javaXiaoCaiJi/zhixie-code-example</a> </p>

<!-- /wp:paragraph -->

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
来来来,手把手教你做大白!
这个东西也是经常被拿来玩的一个小东西,就是通过border-radius 去自己切一个图形。
疯狂的技术宅
2019/03/28
4360
CSS3实现冰墩墩自由
CSS3代码: body { background: rgba(72, 167, 255, 0.733); overflow: hidden; width: 100%; height: 100%; } .main { width: 100px; margin: 10% auto; perspective: 300px; position: absolute; top: 20%; left: 50%; transfor
用户5997198
2022/03/28
4110
CSS3实现冰墩墩自由
冰墩墩太火了,一墩难求?Bloger用css方式呈现一人一墩
近日来,围绕冬奥的热点层出不穷。观众们眼前不断闪过一个接一个既陌生又新鲜好玩的项目,话题更迭的速度比钢架雪车还快。自然也会衍生出诸多分歧:围绕谷爱凌的国籍、苏翊鸣的分数、短道速滑赛场上几乎每一次的摔倒和判罚……这是每一届体育大赛中,都少不了的争论甚至争吵,只有冰墩墩成为了例外。
李洋博客
2022/02/18
4470
冰墩墩太火了,一墩难求?Bloger用css方式呈现一人一墩
CSS+HTML绘制2022年北京冬奥会吉祥物冰墩墩
既然买不到冰墩墩,就自己做个专属冰墩墩吧!以上代码都是本人原创,转载的话请注明出处
用户9999906
2022/09/26
3220
【Html.js——CSS布局】618 活动(蓝桥杯真题-2325)【合集】
Rossy Yan
2025/02/02
810
【Html.js——CSS布局】618 活动(蓝桥杯真题-2325)【合集】
【Html.js——页面布局】个人博客(蓝桥杯真题-1766)【合集】
通过以上步骤,HTML 和 CSS 代码协同工作,实现了一个具有导航栏、首页 banner、文章列表和右侧栏的个人博客页面布局。
Rossy Yan
2025/01/24
1470
【Html.js——页面布局】个人博客(蓝桥杯真题-1766)【合集】
【Html.js——Bug修复】找回连接的奇幻之旅(蓝桥杯真题-18555)【合集】
请在 js/index.js 文件中补充 resetableOnce 函数,实现在接收相同的函数时只执行一次。
Rossy Yan
2025/02/26
1090
【Html.js——Bug修复】找回连接的奇幻之旅(蓝桥杯真题-18555)【合集】
【Html.js——页面布局】水果摆盘(蓝桥杯真题-1767)【合集】
在需要修改部分的代码有相关提示,请仔细阅读之后,使用 flex 布局中的 align-self 和 order 完善 index.css 中的代码, 把对应的水果放在对应的盘子里面,最终效果如下:
Rossy Yan
2025/01/24
2450
【Html.js——页面布局】水果摆盘(蓝桥杯真题-1767)【合集】
HTML+CSS+JS 实现登录注册界面[通俗易懂]
鉴于小伙伴们没有csdn积分,我把代码压缩成了一个压缩包,放在了gitee上面,需要的请点击下载 点击下载
全栈程序员站长
2022/09/13
26.3K0
HTML+CSS+JS 实现登录注册界面[通俗易懂]
CSS3 Loading加载效果合集
效果1 CSS <style> .loading { width: 300px; height: 300px; position: relative; border: 1px solid gray; } .loading .line { width: 200px; height: 8px; /* margin: 50% 20px; */ position:
无道
2019/11/13
1.3K0
CSS3 Loading加载效果合集
CSS3实现雪容融自由
前几天写了一篇CSS3实现冰墩墩自由的技术文章,很多人问有没有雪容融的,今天就来啦!
用户5997198
2022/03/28
2690
CSS3实现雪容融自由
【Html.js——功能实现】布局切换(蓝桥杯真题-18556)【合集】
Rossy Yan
2025/02/21
2660
【Html.js——功能实现】布局切换(蓝桥杯真题-18556)【合集】
【CSS——功能实现】用户名片(蓝桥杯真题-2321)【合集】
选中 index.html 右键启动 Web Server 服务(Open with Live Server),让项目运行起来。
Rossy Yan
2025/02/02
1590
【CSS——功能实现】用户名片(蓝桥杯真题-2321)【合集】
700行无用 纯 CSS 祝考生 金榜高粽《1_bit 的无用 CSS 代码 》
今天才想起来这回事,没办法就急急忙忙的赶工一下,接下来我就画一下这个海报试试手了:
1_bit
2022/06/06
6440
700行无用 纯 CSS 祝考生 金榜高粽《1_bit 的无用 CSS 代码 》
【Html.js——标签导航栏】卡片化标签页(蓝桥杯真题-1765)【合集】
选中 index.html 右键启动 Web Server 服务(Open with Live Server),让项目运行起来。接着,打开环境右侧的【Web 服务】,就可以在浏览器中看到如下效果,当前显示仅有静态布局,并未实现选项卡切换功能。
Rossy Yan
2025/01/24
3210
【Html.js——标签导航栏】卡片化标签页(蓝桥杯真题-1765)【合集】
【Html.js——功能实现】蓝桥校园一卡通(蓝桥杯真题-2421)【合集】
HTML 部分主要负责构建页面的结构,创建了一个校园一卡通制卡的表单界面,包含了卡片展示区域和用户输入信息的表单区域。
Rossy Yan
2025/02/10
1930
【Html.js——功能实现】蓝桥校园一卡通(蓝桥杯真题-2421)【合集】
【CSS3——页面布局】画一只考拉(蓝桥杯真题-2341)【合集】
这段 HTML 代码构建了页面的基本结构,为绘制考拉提供了元素容器。主要通过嵌套的 <div> 元素来划分不同的部分,每个部分都有对应的类名,方便在 CSS 中进行样式设置。
Rossy Yan
2025/02/06
1850
【CSS3——页面布局】画一只考拉(蓝桥杯真题-2341)【合集】
归档 | 原生JS实现会动代码之哆啦A梦
TL;DR 项目官网:https://doraemon.jirengu.maylove.pub 源码地址:https://github.com/zkeq/Doraemon 实现原理 textDom.innerHTML = cssString.substring(0, textStartIndex); styleDom.innerHTML = cssString.substring(0, textStartIndex); 没啥好说的 完整 js 放一下 const cssString
Zkeq
2022/09/07
6680
HTML简单音乐播放器「建议收藏」
通过JS部分的代码,动态给歌曲信息模块(id为player-content1)的DOM元素添加/移除active类名。 设置CSS3动画过渡属性: transition:top 0.3s ease;来生成过渡时间0.3s,速度逐渐变慢的: 上移动画效果:top:0px; ——>top:-85px; 下移动画效果: top:-85px; ——>top:0px;
全栈程序员站长
2022/09/07
4.6K0
乐高个性化小人生成器(源代码一键复制即可运行 )
大家好,今天我要给大家介绍一个超级有趣的网页项目——乐高个性化小人生成器!这个项目可以让你随心所欲地定制属于自己的乐高小人,让它们拥有独一无二的表情和配色。
前端达人
2024/11/25
1260
乐高个性化小人生成器(源代码一键复制即可运行 )
推荐阅读
相关推荐
来来来,手把手教你做大白!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档