首页 > 其他分享 >RabbitMQ如何保证发送的消息可靠(RabbitMQ的Confirm模式和2.Return模式)

RabbitMQ如何保证发送的消息可靠(RabbitMQ的Confirm模式和2.Return模式)

时间:2024-11-06 22:16:05浏览次数:3  
标签:RabbitTemplate Return amqp springframework 模式 org import RabbitMQ public

RabbitMQ如何保证发送的消息可靠(RabbitMQ的Confirm模式和2.Return模式)

1、RabbitMQ消息Confirm模式(保证从生产者到交换机的消息可靠)

1.1、Confirm模式简介

消息的confirm确认机制,是指生产者投递消息后,到达了消息服务器Broker里面的exchange交换机,exchange交换机会给生产者一个应答,生产者接收到应答,用来确定这条消息是否正常的发送到Broker的exchange中,这也是消息可靠性投递的重要保障。
在这里插入图片描述

1.2、具体代码实现

1 配置文件application.yml 开启确认模式:spring.rabbitmq.publisher-confirm-type=correlated
2 写一个类实现RabbitTemplate.ConfirmCallback,判断成功和失败的ack结果,可以根据具体的结果,如果ack为false,对消息进行重新发送或记录日志等处理;
设置rabbitTemplate的确认回调方法
3 rabbitTemplate.setConfirmCallback(messageConfirmCallBack);

在这里插入图片描述

1.2.1、application.yml 开启确认模式

server:
  port: 8080
spring:
  application:
    name: confirm-test01

  rabbitmq:
    host: 你的服务器IP
    port: 5672
    username: 你的账号
    password: 你的密码
    virtual-host: power
    publisher-confirm-type: correlated #开启生产者的确认模式,设置关联模式

my:
  exchangeName: exchange.confirm.01
  queueName: queue.confirm.01

1.2.2、生产者

方式1:实现RabbitTemplate.ConfirmCallback

单独写一个类,实现RabbitTemplate.ConfirmCallback

package com.power.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class MyConfirmCallback implements RabbitTemplate.ConfirmCallback {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            log.info("消息正确到达交换机");
            return;
        }
        //ack为false,消息没有到达交换机
        log.error("消息没有到达交换机,原因是:{}",cause);
    }
}
生产者发送消息
package com.power.service;

import com.power.config.MyConfirmCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private MyConfirmCallback confirmCallback;

    @PostConstruct//构造方法后执行,相当于初始化作用
    public void init(){
        rabbitTemplate.setConfirmCallback(confirmCallback);
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        CorrelationData correlationData = new CorrelationData();//关联数据
        correlationData.setId("order_123456");//发送订单信息
        rabbitTemplate.convertAndSend("exchange.confirm.01","info",message,correlationData);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }
}
方式2:直接写在生产者发送消息类,实现RabbitTemplate.ConfirmCallback
package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService implements RabbitTemplate.ConfirmCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct//构造方法后执行,相当于初始化作用
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        CorrelationData correlationData = new CorrelationData();//关联数据
        correlationData.setId("order_123456");//发送订单信息
        rabbitTemplate.convertAndSend("exchange.confirm.01","info",message,correlationData);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            log.info("消息正确到达交换机");
            return;
        }
        //ack为false,消息没有到达交换机
        log.error("消息没有到达交换机,原因是:{}",cause);
    }
}
方式3:匿名内部类写法

在这里插入图片描述

package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct//构造方法后执行,相当于初始化作用
    public void init(){
        rabbitTemplate.setConfirmCallback(
            new RabbitTemplate.ConfirmCallback() {
                @Override
                public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                    if(ack){
                        log.info("消息正确到达交换机");
                        return;
                    }
                    //ack为false,消息没有到达交换机
                    log.error("消息没有到达交换机,原因是:{}",cause);
                }
            }
        );
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        CorrelationData correlationData = new CorrelationData();//关联数据
        correlationData.setId("order_123456");//发送订单信息
        rabbitTemplate.convertAndSend("exchange.confirm.01","info",message,correlationData);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }
   
}
方式4:lambda表达式写法

在这里插入图片描述

package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct//构造方法后执行,相当于初始化作用
    public void init(){
        rabbitTemplate.setConfirmCallback(
             //lambda表达式写法
            (correlationData, ack, cause)->{
                log.info("关联id:{}",correlationData.getId());
                if(ack){
                    log.info("消息正确到达交换机");
                    return;
                }
                //ack为false,消息没有到达交换机
                log.error("消息没有到达交换机,原因是:{}",cause);
            }
        );
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        CorrelationData correlationData = new CorrelationData();//关联数据
        correlationData.setId("order_123456");//发送订单信息
        rabbitTemplate.convertAndSend("exchange.confirm.03","info",message,correlationData);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }

}

1.2.3、RabbitConfig做交换机和队列的绑定

package com.power.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    @Value("${my.exchangeName}")
    private String exchangeName;

    @Value("${my.queueName}")
    private String queueName;

    //创建直连交换机
    @Bean
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange(exchangeName).build();
    }

    //创建队列
    @Bean
    public Queue queue(){
        return QueueBuilder.durable(queueName).build();
    }

    //交换机绑定队列
    @Bean
    public Binding binding(DirectExchange exchangeName,Queue queueName){
        return BindingBuilder.bind(queueName).to(exchangeName).with("info");
    }
}

1.2.4、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>

  <groupId>com.power</groupId>
  <artifactId>rabbit_08_confirm01</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>rabbit_08_confirm01</name>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.13</version>
    <relativePath/>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

1.2.5、测试

如果没有任何异常,消息会正常发送到交换机

在这里插入图片描述
如果程序存在异常,消息不会正常发送到交换机,如果当交换机的名字不对时,消息不会正常到底交换机的。

在这里插入图片描述

2、RabbitMQ消息Return模式(保证从交换机的到队列的消息可靠)

rabbitmq 整个消息投递的路径为:
producer —> exchange —> queue —> consumer

  • 消息从 producer 到 exchange 则会返回一个 confirmCallback;
  • 消息从 exchange –> queue 投递失败则会返回一个 returnCallback

我们可以利用这两个callback控制消息的可靠性投递;

开启 确认模式;
使用rabbitTemplate.setConfirmCallback设置回调函数,当消息发送到exchange后回调confirm方法。在方法中判断ack,如果为true,则发送成功,如果为false,则发送失败,需要处理;

注意配置文件中,开启 退回模式;

spring.rabbitmq.publisher-returns: true

在这里插入图片描述
使用rabbitTemplate.setReturnCallback设置退回函数,当消息从exchange路由到queue失败后,则会将消息退回给producer,并执行回调函数returnedMessage;

2.1、具体代码实现

在这里插入图片描述

2.1.1、applicaton.yml

server:
  port: 8080
spring:
  application:
    name: return-test01

  rabbitmq:
    host: 你的服务器IP
    port: 5672
    username: 你的账号
    password: 你的密码
    virtual-host: power
    publisher-returns: true #开启return模式

my:
  exchangeName: exchange.return.01
  queueName: queue.return.01

2.1.2、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>

  <groupId>com.power</groupId>
  <artifactId>rabbit_09_return01</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>rabbit_09_return01</name>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.13</version>
    <relativePath/>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

2.1.3、启动类

package com.power;

import com.power.service.MessageService;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;

@SpringBootApplication
public class Application implements ApplicationRunner {

    @Resource
    private MessageService messageService;

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        messageService.sendMsg();
    }
}

2.1.4、业务层

方式1:实现RabbitTemplate.ReturnsCallback

回调类MyReturnCallback
package com.power.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

/**
 * 外部类
 * 写一个类实现一个接口
 */
@Component
@Slf4j
public class MyReturnCallback implements RabbitTemplate.ReturnsCallback {

    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.error("消息从交换机没有正确的投递到队列,原因是:{}",returnedMessage.getReplyText());
    }
}
配置类
package com.power.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {

    @Value("${my.exchangeName}")
    private String exchangeName;

    @Value("${my.queueName}")
    private String queueName;

    //创建直连交换机
    @Bean
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange(exchangeName).build();
    }

    //创建队列
    @Bean
    public Queue queue(){
        return QueueBuilder.durable(queueName).build();
    }

    //交换机绑定队列
    @Bean
    public Binding binding(DirectExchange directExchange,Queue queue){
        return BindingBuilder.bind(queue).to(directExchange).with("info");
    }
}
service业务层
package com.power.service;

import com.power.config.MyReturnCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private MyReturnCallback myReturnCallback;

    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnsCallback(myReturnCallback);//设置回调
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        rabbitTemplate.convertAndSend("exchange.return.01","info111",message);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }
}

方式2:MessageService类实现RabbitTemplate.ReturnsCallback

package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService  implements RabbitTemplate.ReturnsCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnsCallback(this);//设置回调
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        rabbitTemplate.convertAndSend("exchange.return.01","info111",message);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }

    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.error("消息从交换机没有正确的投递到队列,原因是:{}",returnedMessage.getReplyText());
    }
}

方式3:匿名内部类实现RabbitTemplate.ReturnsCallback

package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnsCallback(
                new RabbitTemplate.ReturnsCallback() {
                    @Override
                    public void returnedMessage(ReturnedMessage returned) {
                        log.error("消息从交换机没有正确的投递到队列,原因是:{}",returned.getReplyText());
                    }
                }
        );
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        rabbitTemplate.convertAndSend("exchange.return.01","info111",message);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }

}

核心代码:
在这里插入图片描述

方式4:lambda表达式实现RabbitTemplate.ReturnsCallback

package com.power.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

@Service
@Slf4j
public class MessageService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnsCallback(
            returned-> {
                log.error("消息从交换机没有正确的投递到队列,原因是:{}",returned.getReplyText());
            }
        );
    }

    @Bean
    public void sendMsg(){
        Message message = MessageBuilder.withBody("hello world".getBytes()).build();
        rabbitTemplate.convertAndSend("exchange.return.04","info111",message);
        log.info("消息发送完毕,发送时间是:{}",new Date());
    }

}

核心

在这里插入图片描述

2.1.5、测试

启动程序,当消息从交换机 没有正确地 到达队列,则会触发该方法。

在这里插入图片描述
启动程序,如果消息从交换机 正确地 到达队列了,那么就不会触发该方法。
在这里插入图片描述

标签:RabbitTemplate,Return,amqp,springframework,模式,org,import,RabbitMQ,public
From: https://blog.csdn.net/qq_46112274/article/details/143571201

相关文章

  • PHP常见设计模式应用:单例、工厂、观察者等
    在PHP的开发过程中,设计模式作为一种解决方案,能够帮助开发者简化代码结构、提高系统的可维护性和扩展性。常见的设计模式如单例模式、工厂模式和观察者模式,它们在不同的业务场景下各有其独特的应用价值。单例模式(SingletonPattern)是PHP开发中常用的设计模式之一。它确保一个类只......
  • Spark on YARN:Spark集群模式之Yarn模式的原理、搭建与实践
    Spark的介绍与搭建:从理论到实践-CSDN博客Spark的Standalone集群环境安装与测试-CSDN博客PySpark本地开发环境搭建与实践-CSDN博客Spark程序开发与提交:本地与集群模式全解析-CSDN博客目录一、SparkonYARN的优势(一)统一化资源管理(二)YARN调度机制的优势二、Spark......
  • 10.桥接模式设计思想
    10.桥接模式设计思想目录介绍01.桥接模式基础1.1桥接模式由来1.2桥接模式定义1.3桥接模式场景1.4桥接模式思考1.5解决的问题02.桥接模式实现2.1罗列一个场景2.2桥接结构2.3桥接基本实现2.4有哪些注意点03.桥接实例演示3.1需求分析3.2代码案例实......
  • 0基础学Python——类的单例模式、反射函数、记录类的创建个数、迭代器、生成器及生成
    0基础学Python——类的单例模式、反射函数、记录类的创建个数、迭代器、生成器及生成器练习类的单例模式定义代码演示反射函数代码演示记录类的创建个数迭代器定义特点生成器定义特点写法生成器练习生成器生成1-无穷的数字生成器生成无穷个素数类的单例模式定义......
  • 《大话设计模式》读后感
    大多数初学者都会有这样的问题,就是碰到问题就直觉地用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程。这其实是用计算机的方式去思考,但这样的思维却使得我们的程序只为满足实现当前的需求,不容易维护,不容易扩展,更不容易复用,从而达不到高质量代码的要求。面向对象......
  • 商密学习-分组密码加密模式笔记
    利于并行:ECB(加解密均利于并行)、CTR(加解密均并行)不利于并行:CBC(加密串行,解密可并行)、CFB(加密串行,解密可并行)、OFB(不可并行,每个密钥流块的生成依赖于前一个块的结果)需要填充:ECB、CBC不需要填充:CFB、OFB、CTR错误有扩散:CBC(加密过程错误影响随后所有,解密过程长度不改变最多影响两个......
  • 23设计模式详解
    参考博客https://baijiahao.baidu.com/s?id=1758410771062793648&wfr=spider&for=pc设计模式(Designpattern)"""对软件开发中【普遍存在(反复出现)的问题】,而提出的【解决方案】。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要和重复出现的设计通过设计......
  • C++工厂模式全解析:从简单工厂到抽象工厂的进阶之路
    在软件设计中,工厂模式(FactoryPattern)是一类创建型设计模式,用于将对象的创建过程和使用过程解耦。这种设计模式在面向对象编程中非常常见,特别是在构建复杂系统时,工厂模式可以使代码更加灵活、模块化、易于扩展。工厂模式的主要类型包括:简单工厂模式(SimpleFactory)工厂方法模......
  • EF Core 仓储模式
    数据库:SqlServer为例安装包: 数据库连接DbContextpublicclassTestDbContext:DbContext{publicTestDbContext(DbContextOptions<TestDbContext>options):base(options){}publicDbSet<User>Users{get;set;}}注册数据库上下文builder.S......
  • 《图解设计模式》 读后笔记
    设计模式很早前看过,那时候囫囵吞枣,从来没有系统的总结过,因为对于面试而言问的问题总是答的不精确。这次又借助《图解设计模式》复习了一遍,自己写了一篇总结。23种设计模式看起来很多其实大多数在开发中都见到过。甚至有的设计模式对于一个初学者而言即使不知道设计模式也会应......