首页
苏兮影视
随笔记
壁纸
更多
直播
时光轴
友联
关于
统计
Search
1
软件添加id功能按钮
760 阅读
2
v2ray节点搭建
727 阅读
3
typecho非常有特色的模块
548 阅读
4
QQxml消息卡片生成源码
501 阅读
5
网易云音乐歌单ID获取教程
471 阅读
谈天说地
建站源码
经验教程
资源分享
动漫美图
登录
Search
标签搜索
java
flutter
springboot
安卓
rust
linux
vue
docker
joe
快捷键
git
fish shell
maven
redis
netty
dart
groovy
js
设计模式
rpc
尽意
累计撰写
101
篇文章
累计收到
39
条评论
首页
栏目
谈天说地
建站源码
经验教程
资源分享
动漫美图
页面
苏兮影视
随笔记
壁纸
直播
时光轴
友联
关于
统计
搜索到
85
篇与
的结果
Flutter 状态管理之 Provider
在 Flutter 开发中,状态管理是一个非常重要的话题。而 Provider 作为 Flutter 社区推荐的状态管理解决方案之一,因其轻量、简单、灵活而备受欢迎。本文将系统地解析 Provider 的基本用法和高级用法,包括 read、watch、consume 和 selector,并通过单个 Model 和多个 Model 的管理案例详细说明。什么是 Provider?Provider 是一个基于 InheritedWidget 的封装,用于高效地管理 Flutter 应用中的状态。它的主要优势包括:简单易用,符合 Dart 语言的惯用写法。支持多层 Widget 树的状态共享。高性能,只会更新需要重建的 Widget。通过 Provider,我们可以方便地实现依赖注入和响应式编程。Provider 的基本用法在使用 Provider 之前,需要先在 pubspec.yaml 文件中添加依赖:dependencies: provider: ^lates以下通过一个简单的计数器示例说明 Provider 的基本用法。单个 Model 的使用创建 Model 类import 'package:flutter/foundation.dart'; class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }在应用中注册 Providerimport 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'counter_model.dart'; void main() { runApp( ChangeNotifierProvider( create: (_) => CounterModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: CounterScreen(), ); } }获取状态和更新 UIclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Provider 示例')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }多个 Model 的管理在大型应用中,可能需要管理多个 Model。在这种情况下,可以使用 MultiProvider。定义多个 Modelclass CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } class ThemeModel with ChangeNotifier { bool _isDark = false; bool get isDark => _isDark; void toggleTheme() { _isDark = !_isDark; notifyListeners(); } }注册多个 Providervoid main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => CounterModel()), ChangeNotifierProvider(create: (_) => ThemeModel()), ], child: MyApp(), ), ); }在不同的 Widget 中使用 Modelclass CounterScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider 示例'), actions: [ IconButton( icon: Icon(Icons.brightness_6), onPressed: () => context.read<ThemeModel>().toggleTheme(), ), ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('当前计数:'), Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), ), ); } }Provider 中的核心方法1. readread 方法用于访问状态,但不会订阅状态的变化。这意味着调用 read 的 Widget 在状态更新时不会重建。适用场景:需要触发一次性的操作,例如调用方法或事件处理器。FloatingActionButton( onPressed: () => context.read<CounterModel>().increment(), child: Icon(Icons.add), )2. watchwatch 方法会订阅状态的变化。当状态发生变化时,使用 watch 的 Widget 会重新构建。适用场景:需要根据状态动态更新 UI。Text( context.watch<CounterModel>().count.toString(), style: Theme.of(context).textTheme.headline4, )3. consumeConsumer 是 Provider 提供的一个 Widget,能够订阅状态并重建自身及其子树。适用场景:需要精确控制重建的范围,避免不必要的 Widget 重建。Consumer<CounterModel>( builder: (context, counter, child) { return Text( counter.count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )4. selectorSelector 提供了更高效的订阅方式,可以从状态中选择特定字段进行订阅,避免因其他字段变化导致的无效重建。适用场景:状态对象较大且只需要监听其中部分字段时。Selector<CounterModel, int>( selector: (_, counter) => counter.count, builder: (context, count, child) { return Text( count.toString(), style: Theme.of(context).textTheme.headline4, ); }, )性能优化建议使用 Consumer 或 Selector 控制重建范围:避免不必要的父级 Widget 重建。分离逻辑和 UI:将业务逻辑放在模型中,UI 层只负责展示。尽量减少依赖注入的深度:如果可能,使用多层 Provider。
2024年12月06日
74 阅读
0 评论
1 点赞
Spring Boot 整合 Swagger3
Swagger3 基于 OpenAPI 3 标准,支持自动生成直观的交互式 API 文档页面。快速集成1. 引入依赖在 pom.xml 中添加以下依赖:<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>2. 配置 Swagger创建配置类 SwaggerConfig,定义基本的 Swagger 配置:package com.example.swaggerdemo.config; 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; @Configuration public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.swaggerdemo")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger3 API 文档") .description("Spring Boot 整合 Swagger3 示例") .version("1.0.0") .build(); } }3. 创建测试接口新增 HelloController 用于测试:package com.example.swaggerdemo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/v1") public class HelloController { @GetMapping("/hello") public String sayHello() { return "Hello, Swagger3!"; } }4. 启动并访问启动项目后,在浏览器中访问以下地址:http://localhost:8080/swagger-ui/您将看到一个交互式的 API 文档页面。常见问题1. 无法访问 Swagger UI确保依赖和配置无误。检查 basePackage 是否正确。2. 修改访问路径在 application.yml 中自定义路径:spring: web: path-mapping: swagger-ui: "/custom/swagger-ui"重新访问:http://localhost:8080/custom/swagger-ui/
2024年12月05日
102 阅读
0 评论
2 点赞
2024-12-04
Spring Boot 集成 JWT 简单实现
一、JWT 简介JSON Web Token (JWT) 是一种用于客户端与服务端之间安全传递信息的轻量级协议。它通常用于:用户认证:登录成功后颁发 Token,后续请求中携带该 Token。授权管理:通过 Token 判断用户是否有权限。JWT 的组成部分:Header:描述令牌的类型和算法。Payload:包含用户信息及其他声明。Signature:由 Header、Payload 和密钥生成,用于验证 Token 的完整性。二、项目依赖在项目的 pom.xml 中引入以下依赖:<dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.5</version> </dependency> </dependencies>三、创建 JWT 配置类1. 定义 JwtProperties通过 @ConfigurationProperties 注解加载外部配置:package com.example.jwt.config; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "jwt") public class JwtProperties { private String secret; // 秘钥 private long expiration; // 过期时间(秒) public String getSecret() { return secret; } public void setSecret(String secret) { this.secret = secret; } public long getExpiration() { return expiration; } public void setExpiration(long expiration) { this.expiration = expiration; } }2. 激活配置类package com.example.jwt.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(JwtProperties.class) public class JwtConfig { }3. 在 application.yml 中添加配置jwt: secret: my-secret-key expiration: 3600 # 单位:秒四、编写 JWT 工具类创建 JwtUtils,用于生成和验证 Token:package com.example.jwt.utils; import com.example.jwt.config.JwtProperties; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.stereotype.Component; import java.util.Date; @Component public class JwtUtils { private final JwtProperties jwtProperties; public JwtUtils(JwtProperties jwtProperties) { this.jwtProperties = jwtProperties; } // 生成 JWT public String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getExpiration() * 1000)) .signWith(SignatureAlgorithm.HS256, jwtProperties.getSecret()) .compact(); } // 验证 JWT public Claims validateToken(String token) { try { return Jwts.parser() .setSigningKey(jwtProperties.getSecret()) .parseClaimsJws(token) .getBody(); } catch (Exception e) { return null; // Token 无效 } } }五、实现登录接口1. 控制器 AuthControllerpackage com.example.jwt.controller; import com.example.jwt.utils.JwtUtils; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/auth") public class AuthController { private final JwtUtils jwtUtils; public AuthController(JwtUtils jwtUtils) { this.jwtUtils = jwtUtils; } // 登录接口 @PostMapping("/login") public Map<String, String> login(@RequestBody Map<String, String> request) { String username = request.get("username"); // 简单验证用户(实际中应使用数据库或其他认证机制) if ("admin".equals(username)) { String token = jwtUtils.generateToken(username); Map<String, String> response = new HashMap<>(); response.put("token", token); return response; } else { throw new RuntimeException("Invalid username or password"); } } }2. 测试接口使用 curl 测试登录接口:curl -X POST http://localhost:8080/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "admin"}'返回结果:{ "token": "eyJhbGciOiJIUzI1NiIsInR..." }六、实现简单的认证拦截器为了验证 Token 是否有效,我们可以使用拦截器来处理请求。1. 创建拦截器 JwtInterceptorpackage com.example.jwt.interceptor; import com.example.jwt.utils.JwtUtils; import io.jsonwebtoken.Claims; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class JwtInterceptor implements HandlerInterceptor { private final JwtUtils jwtUtils; public JwtInterceptor(JwtUtils jwtUtils) { this.jwtUtils = jwtUtils; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); // 去掉 "Bearer " Claims claims = jwtUtils.validateToken(token); if (claims != null) { // 将用户名放入请求属性中 request.setAttribute("username", claims.getSubject()); return true; } } response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write("Unauthorized"); return false; } }2. 注册拦截器package com.example.jwt.config; import com.example.jwt.interceptor.JwtInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final JwtInterceptor jwtInterceptor; public WebConfig(JwtInterceptor jwtInterceptor) { this.jwtInterceptor = jwtInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") .excludePathPatterns("/auth/login"); // 登录接口不拦截 } }七、验证拦截功能添加受保护接口package com.example.jwt.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/user/info") public String getUserInfo(@RequestAttribute("username") String username) { return "Hello, " + username; } }测试接口访问受保护接口(无 Token):curl http://localhost:8080/user/info返回结果:Unauthorized携带 Token 访问:curl http://localhost:8080/user/info \ -H "Authorization: Bearer <your-jwt-token>"返回结果:Hello, admin
2024年12月04日
62 阅读
0 评论
1 点赞
基于 Maven 多模块的 SpringCloud 微服务架构实战
随着微服务架构的普及,越来越多的项目开始采用分布式服务模式。在本文中,我们基于 SpringCloud Alibaba 构建一套简单但功能齐全的微服务架构。技术栈包括 Nacos、OpenFeign、SpringCloud Gateway、OkHttp 等,架构基于 Maven 的多模块项目管理方式。目标架构本项目采用多模块 Maven 项目管理,结构如下:springcloud-demo ├── pom.xml # 父 POM ├── gateway-service # 网关服务模块 ├── service-a # 服务 A 模块 ├── service-b # 服务 B 模块 └── nacos-server # Nacos 配置说明功能概览服务注册与发现:Nacos 作为服务注册中心,实现动态服务注册与发现。服务通信:使用 OpenFeign 实现跨服务的 HTTP 调用,支持负载均衡。统一网关:通过 SpringCloud Gateway 实现统一入口和路由管理。连接池优化:结合 OkHttp 提高 OpenFeign 的网络连接效率。配置管理:通过 Nacos 实现动态的集中配置管理。技术栈解析1. Nacos作用:作为服务注册与配置中心,支持动态服务发现和配置热更新。使用场景:服务注册发现、集中化配置管理。2. OpenFeign作用:基于声明式的 REST 客户端,简化服务间调用。优势:自动负载均衡,支持多种序列化方式和超时配置。3. SpringCloud Gateway作用:提供统一网关入口,支持路由转发、限流、熔断等功能。优势:对微服务访问统一管理,提升扩展性与安全性。4. OkHttp作用:为 OpenFeign 提供底层连接池支持,提高网络通信效率。优势:轻量高效,支持连接复用。父项目 POM 配置在父项目的 pom.xml 中,定义公共依赖和子模块:<modules> <module>gateway-service</module> <module>service-a</module> <module>service-b</module> </modules> <dependencyManagement> <dependencies> <!-- SpringCloud Alibaba 依赖管理 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2021.0.5.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- Spring Boot 基础依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- Nacos 服务发现 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- OpenFeign 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- SpringCloud Gateway 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> </dependencies>各子模块实现1. Nacos 配置从 Nacos 官方 下载,启动命令:# 单机模式 sh startup.sh -m standaloneNacos 默认端口为 8848,访问 http://localhost:8848/nacos 查看管理界面,默认用户名和密码均为 nacos。2. Service A功能:提供简单的 REST 接口。依赖:Nacos 服务注册。application.ymlserver: port: 8081 spring: application: name: service-a cloud: nacos: discovery: server-addr: 127.0.0.1:8848Controller 示例@RestController @RequestMapping("/service-a") public class ServiceAController { @GetMapping("/hello") public String hello() { return "Hello from Service A"; } }3. Service B功能:调用 Service A 的接口。依赖:OpenFeign,Nacos 服务注册。application.ymlserver: port: 8082 spring: application: name: service-b cloud: nacos: discovery: server-addr: 127.0.0.1:8848Feign Client@FeignClient(name = "service-a") public interface ServiceAFeignClient { @GetMapping("/service-a/hello") String callServiceA(); }Controller 示例@RestController @RequestMapping("/service-b") public class ServiceBController { @Autowired private ServiceAFeignClient serviceAFeignClient; @GetMapping("/call") public String call() { return serviceAFeignClient.callServiceA(); } }4. Gateway 服务功能:通过网关统一路由到服务 A 和服务 B。依赖:SpringCloud Gateway,Nacos 服务注册。application.ymlserver: port: 8080 spring: application: name: gateway-service cloud: gateway: routes: - id: service-a-route uri: lb://service-a predicates: - Path=/service-a/** - id: service-b-route uri: lb://service-b predicates: - Path=/service-b/** nacos: discovery: server-addr: 127.0.0.1:8848配置 OkHttp 连接池为 OpenFeign 配置 OkHttp 优化性能: FeignConfig@Configuration public class FeignConfig { @Bean public OkHttpClient okHttpClient() { return new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .build(); } @Bean public OkHttpFeignClient feignClient(OkHttpClient okHttpClient) { return new OkHttpFeignClient(okHttpClient); } }在 service-b 的 Feign Client 中即可使用配置的 OkHttp 连接池。测试流程启动 Nacos:确保 Nacos 服务运行在 8848 端口。启动各服务:按照顺序启动 gateway-service、service-a、service-b。访问接口:通过 Gateway 访问服务:http://localhost:8080/service-a/hello 返回 Hello from Service A。http://localhost:8080/service-b/call 通过 Feign 调用 Service A。
2024年12月04日
77 阅读
0 评论
2 点赞
RabbitMQ 消息队列详解及 Spring Boot 实战教程
2024年11月26日
106 阅读
0 评论
3 点赞
2024-11-26
RabbitMQ 是一个高效、可靠的消息代理中间件,广泛应用于分布式系统中,用于实现微服务之间的异步通信和解耦。一、RabbitMQ 基本概念1.1 核心概念队列(Queue):存储消息的容器,消息由生产者发送到队列,消费者从队列中取出进行处理。支持点对点(P2P)模式。交换机(Exchange):负责根据路由规则将消息分发到队列。常见交换机类型:Direct、Fanout、Topic。绑定(Binding):连接交换机和队列的规则,结合路由键(Routing Key)定义消息的路由方式。消息模型:点对点模式(P2P): 一条消息只能被一个消费者消费。发布订阅模式(Pub/Sub): 一条消息可以被多个消费者消费。二、三种交换机详解2.1 Direct 交换机路由方式: 消息根据路由键(Routing Key)精准匹配到指定队列。优点: 简单、高效,适用于明确路由需求的场景。缺点: 需要为每个队列绑定具体的路由键,维护成本较高。应用场景: 点对点通知,如订单支付成功通知。2.2 Fanout 交换机路由方式: 广播消息到所有绑定队列,无需路由键。优点: 适合广播场景,无需复杂路由配置。缺点: 不支持消息过滤,容易造成资源浪费。应用场景: 全网公告或系统事件通知。2.3 Topic 交换机路由方式: 根据通配符模糊匹配路由键。* 匹配一个单词,# 匹配零个或多个单词。优点: 灵活的路由规则,支持复杂消息分发需求。缺点: 配置复杂,性能略低于其他类型交换机。应用场景: 新闻分类推送或订阅系统。三、Spring Boot 与 RabbitMQ 整合3.1 项目依赖在 pom.xml 文件中添加 RabbitMQ 依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>3.2 RabbitMQ 配置两种方式方法一:使用 application.yml 配置在 application.yml 文件中配置 RabbitMQ:spring: rabbitmq: host: localhost port: 5672 username: guest password: guest方法二:通过配置类创建连接工厂import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQFactoryConfig { @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory factory = new CachingConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); factory.setUsername("guest"); factory.setPassword("guest"); return factory; } }3.3 交换机、队列及绑定的两种创建方式方法一:直接使用 new 创建import org.springframework.amqp.core.*; @Configuration public class RabbitMQDirectConfig { @Bean public Queue directQueue() { return new Queue("direct.queue"); } @Bean public DirectExchange directExchange() { return new DirectExchange("direct.exchange"); } @Bean public Binding bindingDirect(Queue directQueue, DirectExchange directExchange) { return BindingBuilder.bind(directQueue).to(directExchange).with("direct.key"); } }方法二:通过工厂类创建import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQFactoryConfig { @Bean public Queue fanoutQueue() { return QueueBuilder.durable("fanout.queue").build(); } @Bean public FanoutExchange fanoutExchange() { return ExchangeBuilder.fanoutExchange("fanout.exchange").durable(true).build(); } @Bean public Binding bindingFanout(Queue fanoutQueue, FanoutExchange fanoutExchange) { return BindingBuilder.bind(fanoutQueue).to(fanoutExchange); } }3.4 消息生产者与消费者消息生产者import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Component; @Component public class MessageProducer { private final RabbitTemplate rabbitTemplate; public MessageProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void sendDirectMessage(String message) { rabbitTemplate.convertAndSend("direct.exchange", "direct.key", message); } public void sendFanoutMessage(String message) { rabbitTemplate.convertAndSend("fanout.exchange", "", message); } public void sendTopicMessage(String message) { rabbitTemplate.convertAndSend("topic.exchange", "topic.test", message); } }消息消费者import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class MessageConsumer { @RabbitListener(queues = "direct.queue") public void receiveDirectMessage(String message) { System.out.println("Received Direct Message: " + message); } @RabbitListener(queues = "fanout.queue") public void receiveFanoutMessage(String message) { System.out.println("Received Fanout Message: " + message); } }3.5 单元测试使用 JUnit 测试消息发送功能:import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class RabbitMQTest { @Autowired private MessageProducer messageProducer; @Test public void testDirectMessage() { messageProducer.sendDirectMessage("Test Direct Exchange"); } @Test public void testFanoutMessage() { messageProducer.sendFanoutMessage("Test Fanout Exchange"); } }四、总结本文通过介绍 RabbitMQ 的核心概念,分析了三种交换机的优缺点及适用场景,并通过 Spring Boot 实现了 MQ 的完整配置与消息生产、消费功能。提供的两种实现方式(application.yml 配置和配置类方式,以及直接 new 和工厂创建方式)为不同项目需求提供了灵活选择。
1
2
3
4
...
17