SpringBoot+ActiveMQ-发布订阅模式(生产端)

news2024/9/22 21:33:36

SpringBoot+ActiveMQ-发布订阅模式(生产端)

Topic 主题

* 消息消费者(订阅方式)消费该消息

* 消费生产者将发布到topic中,同时有多个消息消费者(订阅)消费该消息

* 这种方式和点对点方式不同,发布到topic的消息会被所有订阅者消费

* 当生产者发布消息,不管是否有消费者,都不会保存消息,如果对订阅消息提前做了持久化操作,还是可以收到的

ActiveMQ版本:apache-activemq-5.16.5

案例源码:SpringBoot+ActiveMQ-发布订阅Demo

SpringBoot集成ActiveMQ topic生产端的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>boot.example.topic.provider</groupId>
    <artifactId>boot-example-topic-demo-provider-2.0.5</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>boot-example-topic-demo-provider-2.0.5</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>boot.example.demo.entity</groupId>
            <artifactId>boot-example-demo-entity-2.0.5</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- activeMQ依赖组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- spring.activemq.pool.enabled=true -->
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
            <version>5.16.5</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- 打包成一个可执行jar -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

 
server.port=8043
 
 
spring.activemq.broker-url=tcp://127.0.0.1:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.in-memory=false
spring.activemq.packages.trust-all=true
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=6
spring.activemq.pool.idle-timeout=30000
spring.activemq.pool.expire-timeout=0
spring.jms.pub-sub-domain=false

启动类AppTopicProvider

package boot.example.topic.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;

/**
 *蚂蚁舞
 */
@SpringBootApplication
@EnableJms
public class AppTopicProvider
{
    public static void main( String[] args )
    {
        SpringApplication.run(AppTopicProvider.class, args);
        System.out.println( "Hello World!" );
    }
}

ActiveMqConfig

package boot.example.topic.provider.config;

import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

import javax.jms.ConnectionFactory;
import javax.jms.Topic;

/**
 * 蚂蚁舞
 */

@Configuration
public class ActiveMqConfig {

    public static final String defaultTopic = "myw_topic";

    @Bean
    public Topic topic() {
        return new ActiveMQTopic(defaultTopic);
    }


//    // topic模式的ListenerContainer
//    @Bean
//    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
//        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
//        bean.setPubSubDomain(true);
//        bean.setConnectionFactory(activeMQConnectionFactory);
//        return bean;
//    }

}

ProviderDefaultTopicService

package boot.example.topic.provider.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import javax.jms.Topic;


@Service
public class ProviderDefaultTopicService {

    @Autowired
    private Topic topic;

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    /**
     *  使用默认bean配置的名称发送数据
     */
    public void sendStringDefaultTopic(String message) {
        this.jmsMessagingTemplate.convertAndSend(topic, message);
    }


    
}

ProviderTopicService

package boot.example.topic.provider.service;

import boot.example.queue.entity.BootProvider;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 *  蚂蚁舞
 */
@Service
public class ProviderTopicService {


    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    /**
     * 发送字符串消息主题
     *
     * @param topicName 主题名称
     * @param message   字符串
     */
    public void sendStringTopic(String topicName, String message) {
        this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), message);
    }

    /**
     * 发送字符串集合消息主题
     *
     * @param topicName 主题名称
     * @param list      字符串集合
     */
    public void sendStringListTopic(String topicName, List<String> list) {
        this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), list);
    }

    /**
     * 发送对象消息主题
     *
     * @param topicName 主题名称
     * @param obj       对象
     */
    public void sendObjTopic(String topicName, BootProvider obj) {
        this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), obj);
    }

    /**
     * 发送对象集合消息主题
     *
     * @param topicName 主题名称
     * @param objList   对象集合
     */
    public void sendObjListTopic(String topicName, List<BootProvider> objList) {
        this.jmsMessagingTemplate.convertAndSend(new ActiveMQTopic(topicName), objList);
    }

}

BootDefaultTopicProviderController

package boot.example.topic.provider.controller;

import boot.example.topic.provider.service.ProviderDefaultTopicService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 *     蚂蚁舞
 */
@RestController
@RequestMapping(value="/provider")
public class BootDefaultTopicProviderController {


    @Resource
    private ProviderDefaultTopicService providerDefaultTopicService;

    @PostMapping(value = "/sendStringDefaultTopic")
    @ResponseBody
    public String sendStringDefaultTopic(@RequestParam(name="message",required = true) String message) throws Exception {
        providerDefaultTopicService.sendStringDefaultTopic(message);
        return "success";
    }





}

BootTopicProviderController

package boot.example.topic.provider.controller;

import boot.example.queue.entity.BootProvider;
import boot.example.topic.provider.service.ProviderTopicService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 *     蚂蚁舞
 */
@RestController
@RequestMapping(value="/provider")
public class BootTopicProviderController {

    //  指定Topic
    public static final String stringTopic = "stringTopic";

    //  指定list<String>
    public static final String stringListTopic = "stringListTopic";

    //  指定Object
    public static final String objTopic = "objTopic";

    //  指定List<Object>
    public static final String objListTopic = "objListTopic";


    @Resource
    private ProviderTopicService providerTopicService;

    @PostMapping(value = "/sendStringTopic")
    @ResponseBody
    public String sendStringTopic(@RequestParam(name="message",required = true) String message) throws Exception {
        providerTopicService.sendStringTopic(stringTopic, message);
        return "success";
    }

    @PostMapping(value = "/sendStringListTopic")
    @ResponseBody
    public String sendStringListTopic(@RequestBody List<String> list) throws Exception {
        if(list.isEmpty()){return "fail";}
        providerTopicService.sendStringListTopic(stringListTopic, list);
        return "success";
    }

    @PostMapping(value = "/sendObjTopic")
    @ResponseBody
    public String sendObjTopic(@RequestBody BootProvider bootProvider) throws Exception {
        if(bootProvider == null){return "fail";}
        providerTopicService.sendObjTopic(objTopic, bootProvider);
        return "success";
    }

    @PostMapping(value = "/sendObjListTopic")
    @ResponseBody
    public String sendObjListTopic(@RequestBody  List<BootProvider> list) throws Exception {
        if(list.isEmpty()){return "fail";}
        providerTopicService.sendObjListTopic(objListTopic, list);
        return "success";
    }





}

SwaggerConfig UI界面测试用

package boot.example.topic.provider.config;

import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 *  蚂蚁舞
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi(){
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .paths(PathSelectors.regex("/.*"))
                .build().apiInfo(apiInfo());
    }

    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("demo")
                .description("demo接口")
                .version("0.01")
                .build();
    }

    /**
     * http://localhost:XXXX/doc.html  地址和端口根据实际项目查看
     */


}

BootProvider用来测试的类

package boot.example.queue.entity;

import java.io.Serializable;
import java.util.Date;

/**
 *  用在activeMq消息,必须保证package一致,不然序列化后反序列化要出错
 *  蚂蚁舞
 */
public class BootProvider implements Serializable {

    private int id;

    private String name;

    private Date date = new Date();

    public BootProvider() {
    }

    public BootProvider(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "BootProvider{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", date=" + date +
                '}';
    }
}

代码结构

├─boot-example-demo-entity-2.0.5
│  │  pom.xml
│  │  
│  ├─src
│  │  └─main
│  │      └─java
│  │          └─boot
│  │              └─example
│  │                  └─queue
│  │                      └─entity
│  │                              BootProvider.java
│  │                              
├─boot-example-topic-demo-provider-2.0.5
│  │  pom.xml
│  ├─src
│  │  ├─main
│  │  │  ├─java
│  │  │  │  └─boot
│  │  │  │      └─example
│  │  │  │          └─topic
│  │  │  │              └─provider
│  │  │  │                  │  AppTopicProvider.java
│  │  │  │                  │  
│  │  │  │                  ├─config
│  │  │  │                  │      ActiveMqConfig.java
│  │  │  │                  │      SwaggerConfig.java
│  │  │  │                  │      
│  │  │  │                  ├─controller
│  │  │  │                  │      BootDefaultTopicProviderController.java
│  │  │  │                  │      BootTopicProviderController.java
│  │  │  │                  │      
│  │  │  │                  └─service
│  │  │  │                          ProviderDefaultTopicService.java
│  │  │  │                          ProviderTopicService.java
│  │  │  │                          
│  │  │  └─resources
│  │  │          application.properties
│  │  │          
│  │  └─test
│  │      └─java
│  │          └─boot
│  │              └─example
│  │                  └─topic
│  │                      └─provider
│  │                              AppTopicProviderTest.java

ActiveMQ在SpringBoot里的Topic代码demo集成完成,(ActiveMQ已启动后)启动程序访问

http://localhost:8043/doc.html

SpringBoot集成activeMQ对于队列(queue)来说是持久化的事物模式,因此拿来即用,但是发布订阅(topic主题)模式不是持久化的,发送端把消息发出后,如果没有消费者,消息不会被消费,即使消费者端启动了,也不会消费之前的消息(除非对发布订阅也做持久化)

典型的案例topic demo测试(支持持久化订阅)

ActiveMQTopicProvider(Topic生产端)

package boot.example.topic.provider;


import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 *  蚂蚁舞
 */
public class ActiveMQTopicProvider {

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

        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
        Connection connection = connectionFactory.createConnection();
        connection.start();
        //创建会话
        //第一个参数:是否开启事务 transacted true开启 false不开启
        //第二个参数:消息是否自动确认  acknowledgeMode
        //当transacted为true时,acknowledgeMode会默认Session.SESSION_TRANSACTED
        Session session = connection.createSession(true, Session.DUPS_OK_ACKNOWLEDGE);
        //创建Topic
        Topic topic = session.createTopic("myw_topic_test");
        MessageProducer producer = session.createProducer(topic);
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);//持久化设置 默认就是这个
        Message message = session.createTextMessage("myyhtw蚂蚁也会跳舞");
        producer.send(message);

        session.commit();  // 开启事务必须提交这个
        producer.close();
        session.close();
        connection.close();
    }
}

ActiveMQTopicConsumer(Topic消费端)

package boot.example.topic.provider;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 蚂蚁舞
 */
public class ActiveMQTopicConsumer {
    public static void main(String[] args) throws Exception {

        String clientId = "myw_topic_test_wijwe";
        //创建连接工厂
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
        //  持久订阅的Client端标识(多个端持久订阅需要保证唯一性,否则可能会出现问题)
        connectionFactory.setClientID(clientId);

        //创建连接
        Connection connection = connectionFactory.createConnection();
        //开启连接
        connection.start();
        // 创建会话
        // transacted 如果设置true,操作消息队列后,必须使用 session.commit() 如果设置false,操作消息队列后,不使用session.commit();
        // acknowledgeMode
        // 1-Session.AUTO_ACKNOWLEDGE 自动应答
        // 2-Session.CLIENT_ACKNOWLEDGE 手动应答
        // 3-Session.DUPS_OK_ACKNOWLEDGE 延迟应答
        // 0-Session.SESSION_TRANSACTED 事务
        // 当transacted为true时,acknowledgeMode会默认Session.SESSION_TRANSACTED
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        //创建topic
        Topic topic = session.createTopic("myw_topic_test");
        //持久订阅

        //创建消费者
//        // 普通订阅 topic不是持久化的
//        MessageConsumer consumer = session.createConsumer(topic);
        // 持久订阅
        MessageConsumer consumer = session.createDurableSubscriber(topic,clientId);

        while(true){
            //失效时间,如果10秒内没有收到新的消息,说明没有消息存在,此时可以退出当前循环
            TextMessage message = (TextMessage) consumer.receive(60000);
            if(message!=null){
                System.out.println(message.getText());
                //message.acknowledge();
            } else {
                break;
            }
        }

        //关闭连接
        session.commit();
        session.close();
        connection.close();
    }
}

ActiveMQTopicConsumerListener(Topic消费端监听)

package boot.example.topic.provider;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * 蚂蚁舞
 */
public class ActiveMQTopicConsumerListener {


    public static void main(String[] args) throws Exception {
        String clientId = "myw_topic_test_www2";
        //创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");
        //创建连接
        Connection connection = connectionFactory.createConnection();
        //  持久订阅的Client端标识(多个端持久订阅需要保证唯一性,否则可能会出现问题)
        connection.setClientID(clientId);
        //开启连接
        connection.start();
        // 创建会话
        // transacted 如果设置true,操作消息队列后,必须使用 session.commit() 如果设置false,操作消息队列后,不使用session.commit();
        // acknowledgeMode
        // 1-Session.AUTO_ACKNOWLEDGE 自动应答
        // 2-Session.CLIENT_ACKNOWLEDGE 手动应答
        // 3-Session.DUPS_OK_ACKNOWLEDGE 延迟应答
        // 0-Session.SESSION_TRANSACTED 事务
        // 当transacted为true时,acknowledgeMode会默认Session.SESSION_TRANSACTED
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        //创建topic
        Topic topic = session.createTopic("myw_topic_test");
        //创建消费者
//        // 普通订阅 topic不是持久化的
//        MessageConsumer consumer = session.createConsumer(topic);
        // 持久订阅
        MessageConsumer consumer = session.createDurableSubscriber(topic,clientId);

        //注册消息监听器
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try {
                    TextMessage msg = (TextMessage)message;
                    System.out.println(msg.getText());
                    message.acknowledge();
                } catch (JMSException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        while (true){}
//        consumer.close();
//        session.close();
//        connection.close();
    }

}

topic持久化需要发布端设置持久化

producer.setDeliveryMode(DeliveryMode.PERSISTENT);//持久化设置 默认就是这个

topic消费订阅端在代码里有这几个设置

String clientId = "myw_topic_test_www2";

//  持久订阅的Client端标识(多个端持久订阅需要保证唯一性,否则可能会出现问题)
connection.setClientID(clientId);

// 持久订阅
MessageConsumer consumer = session.createDurableSubscriber(topic,clientId);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/357287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NETCore下CI/CD之自动化测试 (详解篇)

NETCore下CI/CD之自动化测试 &#xff08;详解篇&#xff09; 目录&#xff1a;导读 前言 安装JDK 安装 Tomcat 首先&#xff0c;我们需要指定 Tomcat.PID 进程文件&#xff0c;进入 /usr/local/tomcat/bin&#xff0c;编辑文件 增加 tomcat 账户并赋予权限 防止Jeknins…

JSP脚本指令及标记学习笔记

好久没更新文章了&#xff0c;上次更新的文章还是一个学习笔记。本篇博文介绍的是JSP基本概念 1.JSP开发方法 一个jsp网页只需要加上<%%>就行了。 2.JSP运行机制 3.JSP脚本元素 3.1 JSP脚本代码 <% 脚本代码 %>实例 <% SimpleDateFormat df new SimpleDa…

MathType公式编辑器过期(禁止联网)的解决方案

MathType公式编辑器过期&#xff08;禁止联网&#xff09;的解决方案 Mathtype公式编辑器无法使用解决方案 MathType联网后显示证书失效&#xff0c;需要重新认证或者购买。或者是MathType成了精简版&#xff0c;只剩两行了。 1. 打开控制面板 方法1 首先大家在电脑中打开W…

解析从Linux零拷贝深入了解Linux-I/O(下)

接上文解析从Linux零拷贝深入了解Linux-I/O&#xff08;上&#xff09; 大文件传输场景 零拷贝还是最优选吗 在大文件传输的场景下&#xff0c;零拷贝技术并不是最优选择&#xff1b;因为在零拷贝的任何一种实现中&#xff0c;都会有「DMA 将数据从磁盘拷贝到内核缓存区——P…

加油站会员管理小程序实战开发教程11

我们已经用了10篇的篇幅讲解了首页的功能,首页主要是用来展示信息的。那么接下来就要进入我们的功能页面了,会员管理一个比较重要的功能是充值的功能。 要想实现充值功能,首先需要办一张会员卡,那什么时候办理会员卡呢?需要先注册成为会员,然后进行开卡的动作。这里要注…

c/c++开发,无可避免的模板编程实践(篇五)

一、关联容器简述 容器containers是用来管理某对象数据的集合&#xff0c;每种容器都有其优缺点&#xff0c;为了应对不同应用需求&#xff0c;标准库准备了不同的容器类型&#xff0c;容器可以是数组、链表或者是每个元素有一个特别的键值&#xff08;KEY&#xff09;组织起来…

gocd部署应用

产品需要在多个环境部署测试&#xff0c;为了提高部署测试效率&#xff0c;故计划使用CD工具&#xff0c;jenkins确实足够强大&#xff0c;但是使用部署功能是需要安装插件的&#xff0c;再说自己本身只用部署功能&#xff0c;故决定找一个小巧的CD工具&#xff0c;经过一番查找…

CUDA线程块的分配

为了确保能够真正地了解线程块的分配&#xff0c;接下来我们写一个简短的内核程序来输出线程块、线程、线程束和线程全局标号到屏幕上。现在&#xff0c;除非你使用的是 3.2 版本以上的 SDK否则内核中是不支持 printf的。因此&#xff0c;我们可以将数据传送回 CPU 端然后输出到…

微内核和零拷贝

文章目录1.操作系统的特性并发共享虚拟异步2. 微内核(1) 支撑功能中断管理时钟管理原语操作(2)资源管理功能进程管理存储器管理设备管理3.零拷贝什么是零拷贝传统拷贝方式零拷贝方式GatherCopy零拷贝mmap零拷贝1.操作系统的特性 并发 并发&#xff1a;在宏观上&#xff0c;多个…

TryHackMe-Wreath [网络杀伤链](windows网络)渗透测试

Wreath 复习了几天&#xff0c;把自己写的辣鸡wp都看了看&#xff0c;ad也复了复&#xff0c;顺便还将之前一些不懂和遗漏的一些问题都解决了&#xff0c;所谓温故而知新 在继续红队路径之前&#xff0c;先来玩一玩期待已久的Wreath 了解如何通过破坏面向公众的 Web 计算机并…

分布式缓存的问题

1,Redis缓存穿透问题 Redis缓存穿透问题是指查询一个一定不存在的数据&#xff0c;由于这样的数据缓存一定不命中&#xff0c;所以这样的请求一定会打到数据库上。但是由于数据库里面也没有这样数据&#xff0c;且也没有将这样的null值缓存到数据库&#xff0c;从而造成这样的…

软件设计(十三)-原码、反码、补码、移码

软件设计&#xff08;十二&#xff09;数据结构(下)https://blog.csdn.net/ke1ying/article/details/129035300 下面把一个数转成二进制表达形式 原码&#xff1a; 数值1 &#xff1a; 0000 0001 数值-1 &#xff1a; 1000 0001 1 (- 1) &#xff1a; 1000 0010 这是8个…

【安卓逆向】APK修改与反编译回编译

【安卓逆向】反编译修改APK回编译使用工具流程步骤Apktool相关安装与使用常用命令备查APK签名命令备查实战练习反编译查看修改的地方使用Apktool反编译得到产物文件夹并进行修改回编APK实用场景在日常开发我们可能需要替换某些资源或者修改某些代码&#xff0c;但是我们没有源码…

Java基础语法练习题

2023.2.18刷题1、java的4类流程控制语句解析&#xff1a;java的4类流程控制语句循环语句&#xff1a;while&#xff0c;for&#xff0c;do while选择语句&#xff08;分支语句&#xff09;&#xff1a;if,switch跳转语句&#xff1a;break,continue,break,label异常处理语句&am…

Markdown及其语法详细介绍(全面)

文章目录一、基本语法1.标题2.段落和换行3.强调4.列表5.链接6.图片7.引用8.代码9.分割线10表格二、扩展语法1.标题锚点标题 {#anchor}2.脚注3.自动链接4.任务列表5.删除线6.表情符号7.数学公式三、Markdown 应用1.文档编辑2.博客写作3.代码笔记四、常见的工具和平台支持 Markdo…

加油站会员管理小程序实战开发教程12

我们上一篇介绍了会员数据源的开发,本节我们介绍一下会员注册功能。 首先呢梳理一下会员注册的业务逻辑,如果用户是首次登录,那他肯定还没有给我们的小程序提交任何的信息。那么我们就在我的页面给他显示一个注册的按钮,如果他已经注册过了,那么就正常显示会员的信息,他…

spring cloud 集成 seata 分布式事务

spring cloud 集成 seata 分布式事务 基于 seata-server 1.6.x 序言 下载 seata-server 准备一个数据库 seata 专门为 seata-server 做存储&#xff0c;如, 可以指定 branch_tabledistributed_lockglobal_tablelock_table 准备一个业务库&#xff0c;比如存放定单&#xff…

【学习笔记2.19】动态规划、MySQL、Linux、Redis(框架)

动态规划 343整数拆分 class Solution {public int integerBreak(int n) {int dp [] new int [n 1];//dp[i]:正整数i拆分后的最大乘积dp[2] 1;for(int i 2;i < n ;i ){for(int j 1;j < i;j ){dp[i] Math.max(dp[i],Math.max(j * (i - j),j * dp[i - j]));} …

Ubuntu安装opencv库3.4.10,并在cmake工程中引入opencv库

Windows下安装不同&#xff0c;Ubuntu安装OpenCV库时&#xff0c;需要事先安装依赖&#xff0c;而且不同OpenCV库所需的依赖可能会有所不同&#xff0c;下面的依赖亲测 3.4.10 和 4.5.5版本的有效&#xff0c;但是4.6以上版本安装可能会报错。 参考链接&#xff1a;https://bl…

【Python】以邮件的方式定时发送一天的股票分析报告

【Python】以邮件的方式定时发送一天的股票分析报告 文章目录【Python】以邮件的方式定时发送一天的股票分析报告1、Python发送邮件1&#xff09;EmailSender封装2&#xff09;可能存在的问题2、jinja2动态渲染html页面3、阿里云OSS搭建图床1&#xff09;Python上传图片到OSS中…