「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程
文章目录
- 0.序言
- 我的成长历程
- 遇到挫折,陷入低谷
- 重拾信心,迎接未来
- 开源与分享
- 我为何如此看重这次评选
- 最后的心声
- 1.概述
- 1.主要功能
- 2.相关链接
- 2.系统要求
- 构建工具
- 框架和语言
- 数据库与缓存
- 消息队列与对象存储
- 3.快速入门
- 0.配置Maven中央仓库
- 1.打开settings.xml
- 2.不要配置阿里云,切换为Maven中央仓库,否则下不了依赖
- 1.创建项目 combinations-quickstart-starter-demo
- 2.基本目录结构
- 3.代码
- 1.pom.xml 引入quickstart依赖
- 2.application.yml 配置日志存储根目录
- 3.QuickStartController.java 测试的Controller
- 4.QuickStartApplication.java 启动类
- 5.测试运行
- 6.请求测试
- 1.Controller的返回结果是String,默认自动被包装了
- 2.自带链路追踪以及全链路的日志输出
- 4.基础知识(必读)
- 1.项目架构
- 1.图示
- 2.说明
- 1. `sunrays-dependencies`
- 2. `sunrays-framework`
- 3. `sunrays-common`
- 4. `sunrays-common-cloud`
- 5. `sunrays-common-demo`
- 6. `sunrays-combinations`
- 7. `sunrays-combinations-demo`
- 2.common-log4j2-starter说明
- 1.这个模块是必须被引入的!
- 2.对于sunrays-combinations
- 3.对于sunrays-common或者sunrays-common-cloud
- 3.隐私数据保护的问题
- 1.引入common-env-starter
- 2.不引入common-env-starter
- 5.核心模块介绍
- 1.common-log4j2-starter
- 1.功能介绍
- 2.配置示例
- 3.案例演示
- 1.创建模块
- 2.目录结构
- 3.pom.xml
- 1.基本配置
- 2.引入依赖
- 4.application.yml 配置日志输出根目录
- 5.Log4j2Controller.java 测试Controller
- 6.Log4j2Application.java 启动类
- 7.测试
- 1.启动
- 2.请求
- 2.common-web-starter
- 1.功能介绍
- 1.JacksonConfig提供对日期类型的序列化支持
- 2.修饰SpringMVC 中的请求处理适配器
- 3.将前台传进的多种日期格式自动反序列化为 Date 类型
- 2.配置示例
- 3.案例演示
- 1.创建模块
- 2.目录结构
- 3.pom.xml
- 1.基本配置
- 2.引入依赖
- 3.打包配置
- 4.application.yml 配置日志根目录
- 5.WebController.java 测试三种Web响应方式
- 6.WebApplication.java 启动类
- 7.测试
- 1.第一种方式:直接使用自动包装成功结果
- 2.第二种方式:使用 @IgnoredResultWrapper注解忽略掉自动包装
- 3.第三种方式:直接使用ResultWrapper来自己封装结果
- 4.测试打包功能 clean install
- 3.common-mybatis-plus-starter
- 1.功能介绍
- 1.自定义分页封装
- 2.对 MyBatis-Plus 框架进行二次封装
- 3.定义 MyBatis 拦截器
- 2.配置示例
- 1.开启 SQL 美化 配置是否启用 SQL 美化功能,使 SQL 更加可读。
- 2.配置数据源 配置数据库连接信息,使用 Spring 的数据源配置项。
- 3.配置 EasyCode 的宏定义
- 4.配置 `common-mybatis-plus-starter` 模块的 `BaseEntity` 与通用字段一致
- 5.最佳实践(无需任何配置)
- 3.案例演示
- 1.EasyCode插件配置
- 1.下载 EasyCodeConfig.json
- 2.在插件设置中选择从本地导入配置
- 3.在设置的Global Config中创建sunrays-framework.vm并粘贴配置
- 2.IDEA连接数据库
- 1.点击右上角的数据库标志,然后点击加号,选择要连接的数据库
- 2.填写数据库信息进行连接
- 3.创建并使用数据库 sunrays_framework
- 4.创建示例表
- 5.让IDEA连接刚才创建的数据库
- 3.项目环境搭建
- 1.创建模块 common-mybatis-plus-starter-demo
- 2.目录结构
- 3.pom.xml
- 4.application.yml 配置日志根目录、.env文件的绝对路径、数据源
- 5..env文件配置数据库信息
- 6.MyBatisPlusController.java 测试Controller
- 7.MyBatisPlusApplication.java 启动类
- 8.启动测试
- 4.使用EasyCode生成代码
- 1.选中指定的表,右键生成代码
- 2.选择Module和Package以及之前导入的模板,点击OK
- 3.生成的代码
- 5.测试分页查询
- 1.不加任何条件查询第一页,页面大小为三的数据
- 2.响应结果
- 6.全链路日志展示
- 1.controller和service方法的入参格式化打印
- 2.统计数量的sql格式化打印
- 3.查询数据的sql格式化打印
- 4.controller和service方法的出参格式化打印
- 4.部分生成代码说明
- 1.ExampleTableController.java
- 1.展示
- 2.介绍
- 2.ExampleTableService.java
- 1.展示
- 2.介绍
- 3.ExampleTableServiceImpl.java
- 1.展示
- 2.介绍
- 4.ExampleTableMapper.java
- 1.展示
- 2.介绍
- 5.ExampleTableMapper.xml
- 1.展示
- 2.介绍
- 5.示例:使用框架编写一个需求
- 1.需求
- 2.目录结构
- 3.ExampleTableMapper.java 新增求数量和求数据的方法
- 4.ExampleTableMapper.xml 实现方法
- 5.ExampleTableService.java 新增分页查询的方法
- 6.ExampleTableServiceImpl.java 实现方法
- 7.ExampleTableController.java 新增req和分页查询方法
- 8.查询结果
- 4.common-minio-starter
- 1.功能介绍
- 1.快捷上传文件
- 2.文件名不重复
- 3.便捷管理
- 2.配置示例
- 3.案例演示
- 1.创建模块
- 2.目录结构
- 3.pom.xml
- 1.基本配置
- 2.引入依赖
- 4.application.yml 配置日志根目录、.env文件的绝对路径以及minio
- 5..env 配置minio的信息
- 6.MinioController.java Minio测试Controller
- 7.MinioApplication.java 启动类
- 4.测试
- 1.创建一个存储桶
- 2.检查刚才创建的桶是否存在
- 3.上传文件并返回预览和下载链接
- 1.上传到test桶(已经使用mc开放了读权限)
- 2.预览和下载
- 3.如果没有开放读权限预览就是下面的报错
- 5.common-redis-starter
- 1.功能介绍
- 1. 快捷操作:
- 2. 灵活性:
- 3. 数据安全性:
- 4. 高效的管理:
- 6.丰富的操作功能:
- String 类型:
- Hash 类型:
- List 类型:
- Set 类型:
- SortedSet 类型:
- 2.配置示例
- 3.案例演示
- 1.创建模块
- 2.目录结构
- 3.pom.xml
- 1.基本配置
- 2.引入依赖
- 4.application.yml 配置日志根目录、.env文件的绝对路径以及Redis
- 5..env 配置Redis的信息
- 6.测试的Controller
- 1.RHashController.java
- 2.RSetController.java
- 3.RSortedSetController.java
- 4.RStringController.java
- 5.RListController.java
- 7.RedisApplication.java 启动类
- 8.测试RString
- 1.设置缓存值
- 2.获取缓存值
- 6.common-rabbitmq-starter
- 1. 功能介绍
- 1.自定义消息转换器
- 2.增强的可扩展性
- 3.与 Spring Boot 高度集成
- 2. 配置示例
- 3.案例演示
- 1.创建模块
- 1.父模块
- 2.生产者 publisher
- 3.消费者 consumer
- 2.目录结构
- 3.父pom.xml
- 1.统一管理子模块
- 2.基本配置
- 3.引入依赖
- 4.publisher
- 1.application.yml 配置日志根目录、.env文件的绝对路径以及RabbitMQ
- 2..env 填写RabbitMQ的配置
- 3.TestConfig.java 创建fanout类型的交换机和队列
- 4.TestConfigPublisher.java 发布对象类型的消息
- 5.PublisherApplication.java 启动类
- 5.consumer
- 1.application.yml 配置日志根目录、.env文件的绝对路径以及RabbitMQ
- 2..env 填写RabbitMQ的配置
- 3.TestConfigConsumer.java 监听队列中的消息
- 4.ConsumerApplication.java 启动类
- 6.测试
- 1.发送消息
- 2.接受消息
- 7.总结
0.序言
很荣幸能够参与到 2024年博客之星评选活动。在此,请允许我简单地介绍一下自己:
我的成长历程
我是 2025届 的一名计算机专业学生,从小学到高中,我一直是那个努力学习、听话的孩子。周围的人都在埋头苦读,似乎学习和考试就是我们人生的全部意义。
进入大学后,我依然保持着高中的学习状态。即使室友们在深夜 12:30 熄灯,我也坚持早起学习,坐在课堂的第一排,每一堂课都全神贯注。大一时,我的专业成绩排名 第四,连续两年获得 奖学金。虽然在外人眼中,我是一个“出类拔萃”的学生,但内心深处的迷茫和压力始终伴随着我。
某一天,我开始思考:人生的意义究竟是什么? 难道就是不停地学习和考试吗?于是,我开始阅读各类哲学书籍,试图从中找到人生的答案。《幸福之路》、 《苏菲的世界》、《苏格拉底的申辩》…… 这些书让我渐渐意识到,人生并不只是学习和考试,更重要的是找到属于自己的方向和热爱。那时,加入了鱼皮的知识星球,看到许多伙伴分享 Java学习心得,心中悄然燃起了对编程的渴望。从那一刻起,成为 Java后端工程师成为了我的第一个梦想。
于是,我开始了漫长的自学之旅。从 韩顺平老师的600小时Java课程 到手写 Tomcat、Servlet 和 Spring、SpringMVC 、 MyBatis 的底层实现,我每天学习 8到11小时,甚至连春节都只休息了一天。用八个月时间,完成了正常一年才能学完的内容。通过这段时间的努力,我掌握了完整的 Java体系,并且反复研究 设计模式,通过视频、书籍和总结的方式学了四遍。这一年的时间,我的语雀文档笔记已经到达了一百万字。
不仅如此,我还跟随鸡翅老哥的 Club项目,完成了 八万行后端代码,完成了五期的全部内容,并独自将项目部署到 8台服务器 上。看着群里连做这个项目到处问问题的人都进了字节,而我却能独自解决所有问题,我就更有信心了,也让我无比坚定了自己的选择。
为了秋招,我根据简历整理出了 八万字的面试题,每天按计划背诵,虽然枯燥无味,但我依然坚持了下来。
遇到挫折,陷入低谷
然而,秋招的经历让我第一次真正体会到现实的压力。第一次大厂面试,我因为算法准备的不充分而被刷掉,面试官的一句话更让我深受打击:“你们这些应届生项目我看不上,很多人连项目都没有,你基础太差了。”这一刻,我感受到前所未有的打击,难道只有算法才算基础?我辛辛苦苦做的 Java底层 和 项目经验 就不值一提吗?
在秋招的最后,我获得了一个小厂自研的工作。然后因为正在等待中厂的意向,我选择去小厂试一试,在 10月末,中厂发了意向,考虑到这个公司在网上风评不错,并且在这个小厂感觉每天技术都在退步,只是做一些业务的处理,完全用不到我学的那么多技术,并且小厂在一个月试用期后离职就要付公司一个月的培训费用,就先离职了。
然而,11月末,中厂的意向突然被毁掉,那一刻的巨大落差让我瞬间陷入了迷茫。那些曾经不眠不休、全力以赴的日子,似乎在一瞬间都变得毫无意义。这种挫败感让我深陷痛苦,彻夜难眠,反复思考:我究竟错在哪里?
从小到大,我几乎没有真正休息过。大三时,我更是将全部的精力都投入到 Java 学习中。别人在午休时,我在埋头钻研;别人在享受娱乐、玩游戏时,我却依然坚持学习。我几乎舍弃了生活中的一切,只为了让自己在未来能够更加出色。那段时间,我用辛勤的努力为自己构筑了一座信念之塔,然而却在这一刻轰然倒塌。
重拾信心,迎接未来
失意的阴影笼罩着我,质疑与痛苦一度让我无法自拔。过去的每一份坚持与牺牲,都像是一场徒劳的幻梦,让人怀疑努力的意义。然而,也正是在这一刻,我开始意识到——或许,这只是前行路上的一块绊脚石,而不是终点。我必须学会站起来,重新出发。
经历了这段低谷期,我重新审视自己,发现其实我并没有尽全力。如果每天 8到11小时 不够,那就努力把时间延长到 12小时;如果算法不行,那就每天刷 10道算法题;如果我的项目不够好,那就自研框架并反复优化。
虽然在小厂没有待多久,而且离职资料完全被删除,但是因为当时用小厂自研的框架写过几个接口,即使没有看过具体框架的代码,我也凭借着扎实的 Java基础,以及 设计模式 的基础,用了几天时间经过逐步的思考、优化,最终的实现效果竟然与原框架不谋而合。
通过参与企业项目,我了解了一些企业开发中的痛点,并不断优化和增加框架功能,这些经验不仅丰富了我的技术积累,也让我更加坚定了继续前行的决心。
开源与分享
加入 CSDN 后,我秉承 开源精神,并专注于技术分享与输出。在半年多的时间里,发布275篇高质量文章,平均质量分90分,得到了12000多粉丝的关注,铁粉数量900多。
此次,我决定将自己半年多来精心编写的框架 Sunrays-Framework 开源到 GitCode,并在CSDN附上详细的文档和教程,希望能帮助更多正在学习的朋友,也希望我的经验能够激励更多人相信,只要 坚持不懈,终将迎来希望。
我为何如此看重这次评选
这次评选不仅仅是对我过去半年努力的肯定,更是我 春招路上最后的底气。作为一名即将毕业的学生,在 Java行业竞争异常激烈的现状 下,这可能是我最后一次证明自己实力的机会。对于我而言,这不仅仅是一次比赛,而是关乎未来职业发展的一次重大转折点。
但我的目标并不仅仅是为自己争取一次机会,更希望借此评选让更多人关注 Sunrays-Framework。这个框架凝聚了我半年多的心血,它不仅是我技术能力的体现,更是我对开源精神的理解与实践。我希望它能帮助更多开发者,无论是用来 学习 还是作为 毕业设计,都能成为大家提升技能和效率的得力助手。
我并不奢求任何回报,只希望在这次评选中,能够获得你们宝贵的一票!每一票,都是对我努力的认可,对开源精神的支持。这不仅是对过去半年辛苦付出的最好褒奖,更是帮助我在 春招最后关头 再拼一次的机会。
最后的心声
我深知 Java行业 的竞争有多么激烈,尤其是对应届毕业生而言。每一份工作机会都来之不易,而这次评选,可能是我 改变命运的最后机会。无论最终成绩如何,我都会继续完善框架,不断优化,只为帮助更多像我一样热爱技术、追求成长的年轻人!
如果你也曾在学习编程时迷茫过,曾在技术深坑中挣扎过,我真诚希望我的经历和这个框架,能够为你带来一丝启发和帮助。你的每一票,都是对我的最大支持和鼓励!
衷心感谢每一位愿意投票的朋友。你们的支持,不仅仅是对我努力的肯定,更是推动我不断前行的动力!让我们共同期待 Sunrays-Framework 帮助更多开发者取得进步,焕发更大的光彩!
1.概述
Sunrays-Framework 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件,涵盖了以下关键功能:
- MyBatis-Plus:简化数据访问层的开发。
- Minio:提供稳定、高效的分布式文件存储支持。
- Redis:实现缓存、分布式锁等高性能存储功能。
- RabbitMQ:可靠的消息队列支持,适用于异步任务和消息通知。
- Log4j2:提供灵活、性能卓越的日志管理。
- Nacos:负责服务发现与配置管理,确保系统动态可扩展。
- Spring Cloud Gateway:高性能的 API 网关,支持路由与负载均衡。
- OpenFeign:声明式 HTTP 客户端,简化服务间通信。
- OpenAI:为智能化应用提供接入支持。
- Mail:内置邮件服务功能,支持多场景通知需求。
- 微信支付与登录:完整集成微信支付功能和微信授权登录,提升用户体验。
框架注重 高效性、可扩展性和易维护性,为开发者提供开箱即用的解决方案,极大地简化了微服务架构的搭建过程。无论是构建企业级分布式系统还是完成毕设项目,Sunrays-Framework 都能以其强大的模块化设计与全面的技术支持,帮助开发者快速实现目标、专注于业务逻辑的创新与优化。
1.主要功能
本人在此承诺:只要我做Java一天,框架就会不断的升级!
永久开源,永久免费!
2.相关链接
- CSDN:Sunrays-Framework 开发笔记
- GitCode:Sunrays-Framework 开源地址
- 官方文档:Sunrays-Framework 官方文档 必读部分提供了七万字的完整语雀开发文档
2.系统要求
为确保系统正常运行,以下是本项目所需的技术栈及版本要求。
构建工具
工具 | 版本 |
---|---|
Maven | 3.6.3 或更高版本 |
框架和语言
技术 | 版本 |
---|---|
Spring Boot | 2.4.2 |
Spring Cloud | 2020.0.1 |
Spring Cloud Alibaba | 2021.1 |
JDK | 1.8 |
数据库与缓存
技术 | 版本 |
---|---|
MySQL | 5.7 |
Redis | 6.2.6 |
消息队列与对象存储
技术 | 版本 |
---|---|
RabbitMQ | 3.8.8 |
MinIO | 2024-12-19 |
3.快速入门
0.配置Maven中央仓库
1.打开settings.xml
2.不要配置阿里云,切换为Maven中央仓库,否则下不了依赖
<mirrors><mirror><id>central</id><mirrorOf>central</mirrorOf> <!-- 直接指定中央仓库 --><name>Maven Central</name><url>https://repo.maven.apache.org/maven2</url></mirror></mirrors>
1.创建项目 combinations-quickstart-starter-demo
2.基本目录结构
3.代码
1.pom.xml 引入quickstart依赖
<?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>cn.sunxiansheng</groupId><artifactId>sunrays-framework-demo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>combinations-quickstart-starter-demo</artifactId><!-- 通过properties来指定版本号 --><properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version></properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- 快速入门的一个starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>combinations-quickstart-starter</artifactId><!-- 无需指定版本 --></dependency></dependencies>
</project>
2.application.yml 配置日志存储根目录
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/combinations-quickstart-starter-demo/logs # 日志存储的根目录
3.QuickStartController.java 测试的Controller
package cn.sunxiansheng.quickstart.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description: QuickStartController** @Author sun* @Create 2025/1/18 19:17* @Version 1.0*/
@RestController
public class QuickStartController {/*** A test endpoint.** @return A sample response.*/@RequestMapping("/test")public String test() {return "This is a test response from QuickStartController";}
}
4.QuickStartApplication.java 启动类
package cn.sunxiansheng.quickstart;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: QuickStartApplication** @Author sun* @Create 2025/1/18 18:52* @Version 1.0*/
@SpringBootApplication
public class QuickStartApplication {public static void main(String[] args) {SpringApplication.run(QuickStartApplication.class, args);}
}
5.测试运行
6.请求测试
1.Controller的返回结果是String,默认自动被包装了
2.自带链路追踪以及全链路的日志输出
4.基础知识(必读)
1.项目架构
1.图示
2.说明
1. sunrays-dependencies
- 职责:管理项目的依赖版本及配置。
- 描述:独立模块,不继承其他模块。
2. sunrays-framework
- 职责:统一管理整个项目,继承
sunrays-dependencies
。 - 描述:作为项目的核心框架模块,负责整体项目的基础配置和管理。
3. sunrays-common
- 职责:封装通用组件,继承
sunrays-framework
。 - 描述:包括一些通用的工具类、公共模块等。
4. sunrays-common-cloud
- 职责:封装 Cloud 相关的通用组件,继承
sunrays-framework
。 - 描述:包括 Cloud 相关的基础设施和服务封装。
5. sunrays-common-demo
- 职责:提供
sunrays-common
和sunrays-common-cloud
的测试 demo,继承sunrays-framework
。 - 描述:用于验证
sunrays-common
和sunrays-common-cloud
子模块的功能和集成。
6. sunrays-combinations
- 职责:管理业务依赖,或者作为中台,继承
sunrays-framework
。 - 描述:通过组合
sunrays-common
和sunrays-common-cloud
完成具体的业务依赖管理。
7. sunrays-combinations-demo
- 职责:提供
sunrays-combinations
模块的测试 demo,继承sunrays-framework
。 - 描述:用于验证
sunrays-combinations
模块的功能和集成。
2.common-log4j2-starter说明
1.这个模块是必须被引入的!
2.对于sunrays-combinations
如果引入了sunrays-combinations模块的依赖,就不需要额外引入common-log4j2-starter,因为已经默认包含了。
3.对于sunrays-common或者sunrays-common-cloud
如果引入的是sunrays-common或者sunrays-common-cloud,那么就需要额外引入common-log4j2-starter。
3.隐私数据保护的问题
1.引入common-env-starter
这个依赖一旦引入,就可以在application.yml配置文件中配置.env文件的路径,然后通过$占位符来从.env文件中读取隐私数据,我在后面的介绍中都会采用这种方式。
2.不引入common-env-starter
在实际开发中,如果不需要进行隐私数据的保护,就可以不引入这个依赖:
- 不需要在application.yml配置文件中配置.env文件的路径,也不需要创建.env文件了
- 将我示例中的${xxx}的部分直接替换为真实的数据即可,比如:
5.核心模块介绍
1.common-log4j2-starter
1.功能介绍
ApplicationReadyListener
- 程序启动时,动态获取并打印以下信息:
- 日志存储的根目录的绝对路径
- 应用的访问地址(包括端口)
- 前端请求时可用的日期格式
- 程序启动时,动态获取并打印以下信息:
ApplicationEnvironmentPreparedListener
- 获取日志根目录及模块名,并将其设置为环境变量供
log4j2-spring.xml
使用。
- 获取日志根目录及模块名,并将其设置为环境变量供
TraceIdLoggingAspect
- 每次请求开始时打印一行日志,包含请求的
traceId
,以便于日志追踪。
- 每次请求开始时打印一行日志,包含请求的
LogAspect
- 日志切面(AOP),匹配所有
controller
和service
包中的方法,记录以下信息:- 方法的执行时间
- 请求参数
- 返回结果
- 日志切面(AOP),匹配所有
- 使用自定义的
banner.txt
- 读取项目的版本号,并在启动时展示自定义的 Banner。
2.配置示例
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-demo/common-log4j2-starter-demo/logs # 日志根目录 (默认: ./logs)log-aspect-enable: true # 是否启用日志切面 (默认开启)
3.案例演示
1.创建模块
2.目录结构
3.pom.xml
1.基本配置
<!-- 通过properties来指定版本号 --><properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version></properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
2.引入依赖
<dependencies><!-- common-log4j2-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency><!-- 引入web模块作为测试! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency></dependencies>
4.application.yml 配置日志输出根目录
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-log4j2-starter-demo/logs # 日志根目录 (默认: ./logs)
5.Log4j2Controller.java 测试Controller
package cn.sunxiansheng.log4j2.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description: Log4j2Controller** @Author sun* @Create 2025/1/19 13:07* @Version 1.0*/
@RestController
public class Log4j2Controller {/*** A test endpoint.** @return A sample response.*/@RequestMapping("/test")public String test() {return "This is a test response from Log4j2Controller";}
}
6.Log4j2Application.java 启动类
package cn.sunxiansheng.log4j2;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: Log4j2Application** @Author sun* @Create 2025/1/19 13:07* @Version 1.0*/
@SpringBootApplication
public class Log4j2Application {public static void main(String[] args) {SpringApplication.run(Log4j2Application.class, args);}
}
7.测试
1.启动
2.请求
2.common-web-starter
1.功能介绍
1.JacksonConfig提供对日期类型的序列化支持
- 配置 Jackson 的 ObjectMapper 来为 Date 类型指定自定义的序列化和反序列化格式。这样,前后端可以统一日期格式。
2.修饰SpringMVC 中的请求处理适配器
- 通过自定义注解 IgnoredResultWrapper 和装饰器模式对 SpringMVC 中的请求处理适配器进行扩展,控制响应结果的包装及处理方式。
3.将前台传进的多种日期格式自动反序列化为 Date 类型
- 使用
@InitBinder
来解析来自前端的多种日期格式,确保它们能正确反序列化为 Date 类型。
2.配置示例
配置 Maven 来打包项目时,指定 .jar
文件的名称为项目的 artifactId
和 version
,并使用 spring-boot-maven-plugin
插件来打包所有依赖。
<!-- Maven 打包常规配置 -->
<build><!-- 打包成 jar 包时的名字为项目的 artifactId + version --><finalName>${project.artifactId}-${project.version}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.2</version><executions><execution><goals><!-- 将所有的依赖包都打到这个模块中 --><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>
3.案例演示
1.创建模块
2.目录结构
3.pom.xml
1.基本配置
<!-- 通过properties来指定版本号 -->
<properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version>
</properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
2.引入依赖
<dependencies><!-- common-web-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency><!-- common-log4j2-starter 是必须引入的!!! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency></dependencies>
3.打包配置
<!-- maven 打包常规配置 --><build><!-- 打包成 jar 包时的名字为项目的artifactId + version --><finalName>${project.artifactId}-${project.version}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.2</version><executions><execution><goals><!-- 将所有的依赖包都打到这个模块中 --><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
4.application.yml 配置日志根目录
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-web-starter-demo/logs # 日志根目录(默认./logs)
5.WebController.java 测试三种Web响应方式
package cn.sunxiansheng.web.controller;import cn.sunxiansheng.tool.response.ResultWrapper;
import cn.sunxiansheng.web.annotation.IgnoredResultWrapper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description: WebController** @Author sun* @Create 2025/1/19 13:39* @Version 1.0*/
@RestController
public class WebController {/*** 第一种方式:直接使用自动包装成功结果** @return*/@RequestMapping("/method1")public String method1() {return "method1";}/*** 第二种方式:使用 @IgnoredResultWrapper注解忽略掉自动包装** @return*/@IgnoredResultWrapper@RequestMapping("/method2")public String method2() {return "method2";}/*** 第三种方式:直接使用ResultWrapper来自己封装结果** @return*/@RequestMapping("/method3")public ResultWrapper<String> method3() {return ResultWrapper.fail("method3");}
}
6.WebApplication.java 启动类
package cn.sunxiansheng.web;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: WebApplication** @Author sun* @Create 2025/1/19 13:39* @Version 1.0*/
@SpringBootApplication
public class WebApplication {public static void main(String[] args) {SpringApplication.run(WebApplication.class, args);}
}
7.测试
1.第一种方式:直接使用自动包装成功结果
2.第二种方式:使用 @IgnoredResultWrapper注解忽略掉自动包装
3.第三种方式:直接使用ResultWrapper来自己封装结果
4.测试打包功能 clean install
3.common-mybatis-plus-starter
1.功能介绍
1.自定义分页封装
- 只需传递
pageNum
,pageSize
,total
,data
即可自动完成分页封装,简化分页逻辑。
2.对 MyBatis-Plus 框架进行二次封装
- 隐藏
QueryWrapper
等复杂实现细节,保留动态生成 CRUD 特性。 - 结合 EasyCode 自定义模板优化代码生成,实现无感封装,统一数据访问规范,大幅提升开发效率和规范性,打造高可用、高扩展性、低入门成本的企业级数据访问层解决方案。
3.定义 MyBatis 拦截器
- 对 SQL 进行格式话输出,提高 SQL 可读性,便于排查问题。
2.配置示例
1.开启 SQL 美化 配置是否启用 SQL 美化功能,使 SQL 更加可读。
sun-rays:mybatis-plus:sql-beauty-enabled: true # 是否开启 SQL 美化(默认 true)
2.配置数据源 配置数据库连接信息,使用 Spring 的数据源配置项。
spring:datasource:username: ${MYSQL_USERNAME} # 用户名password: ${MYSQL_PASSWORD} # 密码url: jdbc:mysql://${MYSQL_IP}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false # 数据库连接 URL
3.配置 EasyCode 的宏定义
# 定义配置宏
# 指定逻辑删除字段名(驼峰命名)
set($logicDeleteField = "isDeleted")# 指定逻辑删除字段名(下划线命名)
set($logicDeleteFieldUnder = "is_deleted")# 定义全局逻辑删除字段的删除值和未删除值
set($deleteColumnValue = 1)
set($notDeletedColumnValue = 0)# 配置排除的字段列表(驼峰命名)
set($excludedFields = ["createBy", "createTime", "updateBy", "updateTime"])
4.配置 common-mybatis-plus-starter
模块的 BaseEntity
与通用字段一致
5.最佳实践(无需任何配置)
通用字段为:
create_by
create_time
update_by
update_time
is_deleted
3.案例演示
1.EasyCode插件配置
1.下载 EasyCodeConfig.json
点击下载 EasyCodeConfig.json
2.在插件设置中选择从本地导入配置
3.在设置的Global Config中创建sunrays-framework.vm并粘贴配置
# 定义配置宏# 指定逻辑删除字段名(驼峰命名)set($logicDeleteField = "isDeleted")# 指定逻辑删除字段名(下划线命名)set($logicDeleteFieldUnder = "is_deleted")#定义全局逻辑删除字段的删除值和未删除值set($deleteColumnValue = 1)set($notDeletedColumnValue = 0)# 配置排除的字段列表(驼峰命名)set($excludedFields = ["createBy", "createTime", "updateBy", "updateTime"])# 最佳实践(必要字段):create_by,create_time,update_by,update_time,is_deleted
2.IDEA连接数据库
1.点击右上角的数据库标志,然后点击加号,选择要连接的数据库
2.填写数据库信息进行连接
3.创建并使用数据库 sunrays_framework
create database sunrays_framework;
use sunrays_framework;
4.创建示例表
CREATE TABLE example_table
(id INT PRIMARY KEY COMMENT '主键ID',user_name VARCHAR(255) NULL COMMENT '用户名称',user_email VARCHAR(255) NULL COMMENT '用户邮箱',phone_number VARCHAR(20) DEFAULT NULL COMMENT '联系电话',home_address VARCHAR(255) DEFAULT NULL COMMENT '家庭住址',account_status TINYINT(1) DEFAULT 0 COMMENT '账户状态(0-禁用,1-启用)',create_by VARCHAR(50) DEFAULT NULL COMMENT '创建人',create_time DATETIME COMMENT '创建时间',update_by VARCHAR(50) DEFAULT NULL COMMENT '更新人',update_time DATETIME COMMENT '更新时间',is_deleted TINYINT(1) DEFAULT 0 COMMENT '逻辑删除标记(0-未删除,1-已删除)'
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4 COMMENT ='示例表';INSERT INTO example_table (id, user_name, user_email, phone_number, home_address, account_status, create_by)
VALUES (1, '张三', 'zhangsan@example.com', '13800138000', '北京市朝阳区', 1, 'admin'),(2, '李四', 'lisi@example.com', '13800138001', '上海市浦东新区', 1, 'admin'),(3, '王五', 'wangwu@example.com', '13800138002', '广州市天河区', 0, 'admin'),(4, '赵六', 'zhaoliu@example.com', '13800138003', '深圳市福田区', 1, 'admin'),(5, '孙七', 'sunqi@example.com', '13800138004', '成都市武侯区', 0, 'admin'),(6, '周八', 'zhouba@example.com', '13800138005', '杭州市西湖区', 1, 'admin'),(7, '吴九', 'wujia@example.com', '13800138006', '重庆市渝中区', 0, 'admin'),(8, '郑十', 'zhengshi@example.com', '13800138007', '南京市鼓楼区', 1, 'admin'),(9, '冯十一', 'fengshiyi@example.com', '13800138008', '武汉市武昌区', 1, 'admin'),(10, '褚十二', 'chushier@example.com', '13800138009', '长沙市岳麓区', 0, 'admin');
5.让IDEA连接刚才创建的数据库
3.项目环境搭建
1.创建模块 common-mybatis-plus-starter-demo
2.目录结构
3.pom.xml
-
基本配置
<!-- 通过properties来指定版本号 --><properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version></properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
-
引入依赖
-
<dependencies><!-- common-mybatis-plus-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-mybatis-plus-starter</artifactId></dependency><!-- common-log4j2-starter 是必须引入的!!! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency><!-- EasyCode 生成的代码依赖Web模块--><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency><!-- env模块确保数据安全,可以不引入 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-env-starter</artifactId></dependency></dependencies>
4.application.yml 配置日志根目录、.env文件的绝对路径、数据源
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-common-demo/common-mybatis-plus-starter-demo/logs # 日志根目录(默认./logs)env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework/sunrays-common-demo/common-mybatis-plus-starter-demo # .env文件的绝对路径
spring:datasource:username: ${MYSQL_USERNAME} # 用户名password: ${MYSQL_PASSWORD} # 密码url: jdbc:mysql://${MYSQL_IP}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false # url
5…env文件配置数据库信息
MYSQL_USERNAME= 用户名
MYSQL_PASSWORD= 密码
MYSQL_IP= ip
MYSQL_PORT= 端口
MYSQL_DATABASE= 数据库名字
6.MyBatisPlusController.java 测试Controller
package cn.sunxiansheng.mybatis.plus.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description: MyBatisPlusController** @Author sun* @Create 2025/1/19 15:01* @Version 1.0*/
@RestController
public class MyBatisPlusController {/*** A test endpoint.** @return A sample response.*/@RequestMapping("/test")public String test() {return "This is a test response from MyBatisPlusController";}
}
7.MyBatisPlusApplication.java 启动类
package cn.sunxiansheng.mybatis.plus;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: MyBatisPlusApplication** @Author sun* @Create 2025/1/19 15:00* @Version 1.0*/
@SpringBootApplication
public class MyBatisPlusApplication {public static void main(String[] args) {SpringApplication.run(MyBatisPlusApplication.class, args);}
}
8.启动测试
4.使用EasyCode生成代码
1.选中指定的表,右键生成代码
2.选择Module和Package以及之前导入的模板,点击OK
3.生成的代码
5.测试分页查询
1.不加任何条件查询第一页,页面大小为三的数据
2.响应结果
{"success": true,"code": 200,"message": "操作成功","data": {"pageNo": 1,"pageSize": 3,"total": 10,"totalPages": 4,"result": [{"id": 1,"userName": "张三","userEmail": "zhangsan@example.com","phoneNumber": "13800138000","homeAddress": "北京市朝阳区","accountStatus": 1,"isDeleted": 0},{"id": 2,"userName": "李四","userEmail": "lisi@example.com","phoneNumber": "13800138001","homeAddress": "上海市浦东新区","accountStatus": 1,"isDeleted": 0},{"id": 3,"userName": "王五","userEmail": "wangwu@example.com","phoneNumber": "13800138002","homeAddress": "广州市天河区","accountStatus": 0,"isDeleted": 0}],"start": 1,"end": 3,"hasNextPage": true,"hasPreviousPage": false}
}
6.全链路日志展示
1.controller和service方法的入参格式化打印
2.统计数量的sql格式化打印
3.查询数据的sql格式化打印
4.controller和service方法的出参格式化打印
4.部分生成代码说明
1.ExampleTableController.java
1.展示
2.介绍
- 该文件是Controller
- 继承了BaseController,提供了Date类型的自动转换,和一些快捷的响应方法
- 提供了一些基础的接口实现
- 如果想要自定义接口,直接在下面调用Service即可,跟平常的使用方式是一样的
2.ExampleTableService.java
1.展示
2.介绍
- 该文件是Service接口
- 两个泛型分别是与数据库对应的entity的类型以及id类型
- 使用的时候也是跟平常一样,在接口内加一个方法
3.ExampleTableServiceImpl.java
1.展示
2.介绍
- 该文件是Service的实现类
- 三个泛型分别是调用MyBatis Plus方法的Mapper类型,与数据库对应的entity的类型以及id类型
- 构造器是为了在运行时动态给父类设置具体的操作Mybatis Plus的Mapper
- 调用框架自动生成的方法使用super.xxx,调用自己实现的方法用注入的Mapper
- 使用的时候,就不需要管那么多,直接实现Service方法即可
4.ExampleTableMapper.java
1.展示
2.介绍
- 该文件是Mapper接口
- 提供了三个基础的方法
- 使用起来也是跟平常一样,加方法
5.ExampleTableMapper.xml
1.展示
2.介绍
- 该文件是Mapper的实现类
- 提供了三个基础方法的实现
- 使用起来就直接实现Mapper接口的方法去写sql就行
5.示例:使用框架编写一个需求
1.需求
分页查询id大于5的用户
2.目录结构
3.ExampleTableMapper.java 新增求数量和求数据的方法
/*** 查询出id大于5的用户数量** @return*/Long countById();/*** 分页查询出id大于5的所有用户** @param offset* @param limit* @return*/List<ExampleTable> queryByPageAboutId(@Param("offset") Long offset,@Param("limit") Long limit);
4.ExampleTableMapper.xml 实现方法
<select id="countById" resultType="java.lang.Long">select count(*)from example_tablewhere id > 5
</select><select id="queryByPageAboutId" resultMap="ExampleTableMap">select id, user_name, user_email, phone_number, home_address, account_status, create_by, create_time, update_by,update_time, is_deletedfrom example_tablewhere id > 5and is_deleted = 0limit #{offset}, #{limit}
</select>
5.ExampleTableService.java 新增分页查询的方法
/*** 分页查询id大于5的用户** @return*/
PageResult<ExampleTableVo> queryByPageAboutId(ExampleTableController.QueryByPageAboutIdReq req);
6.ExampleTableServiceImpl.java 实现方法
@Override
@Transactional(rollbackFor = Exception.class) // 开启事务
public PageResult<ExampleTableVo> queryByPageAboutId(ExampleTableController.QueryByPageAboutIdReq req) {// 分页查询PageResult<ExampleTableVo> paginate = SunPageHelper.paginate(req.getPageNo(),req.getPageSize(),() -> exampleTableMapper.countById(),(offset, limit) -> {// 查询数据,并转换为voList<ExampleTable> exampleTableList =exampleTableMapper.queryByPageAboutId(offset, limit);List<ExampleTableVo> exampleTableVos = ExampleTableConverter.INSTANCE.convertPoList2VoList(exampleTableList);return exampleTableVos;});return paginate;
}
7.ExampleTableController.java 新增req和分页查询方法
@Datapublic static class QueryByPageAboutIdReq {private Long pageNo;private Long pageSize;}/*** 分页查询id大于5的用户** @return*/@GetMapping("/queryByPageAboutId")public ResultWrapper<PageResult<ExampleTableVo>> queryByPageAboutId(QueryByPageAboutIdReq req) {// ============================== Preconditions 参数校验 ==============================// ============================== 调用Service层 ==============================// 调用service查询id大于5的用户PageResult<ExampleTableVo> pageResult = exampleTableService.queryByPageAboutId(req);return ResultWrapper.ok(pageResult);}
8.查询结果
4.common-minio-starter
1.功能介绍
1.快捷上传文件
- 使用
putObject(MultipartFile file, String bucketName)
一步完成文件上传,并返回预览链接和下载链接。 - 文件自动归类到按日期生成的文件夹中,方便管理。
2.文件名不重复
- 上传文件时,结合日期路径和
UUID
自动生成唯一文件名,避免命名冲突。
3.便捷管理
- 支持文件上传、下载、删除及存储桶管理,满足日常文件操作需求。
- 此工具类极大简化了文件操作流程,让上传和链接生成更加高效可靠。
此工具类极大简化了文件操作流程,让上传和链接生成更加高效可靠!
2.配置示例
sun-rays:minio:endpoint: ${MINIO_ENDPOINT} # minio服务地址 http://ip:端口accessKey: ${MINIO_ACCESS_KEY} # minio服务的accessKeysecretKey: ${MINIO_SECRET_KEY} # minio服务的secretKey
3.案例演示
1.创建模块
2.目录结构
3.pom.xml
1.基本配置
<!-- 通过properties来指定版本号 --><properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version></properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
2.引入依赖
<dependencies><!-- common-minio-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-minio-starter</artifactId></dependency><!-- common-log4j2-starter 是必须引入的!!! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency><!-- 引入web模块作为测试! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency><!-- env模块确保数据安全,可以不引入 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-env-starter</artifactId></dependency>
</dependencies>
4.application.yml 配置日志根目录、.env文件的绝对路径以及minio
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-minio-starter-demo/logs # 日志根目录(默认./logs)env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-minio-starter-demo # .env文件的绝对路径minio:endpoint: ${MINIO_ENDPOINT} # minio服务地址 http://ip:端口accessKey: ${MINIO_ACCESS_KEY} # minio服务的accessKeysecretKey: ${MINIO_SECRET_KEY} # minio服务的secretKey
5…env 配置minio的信息
MINIO_ENDPOINT= minio服务地址 http://ip:端口
MINIO_ACCESS_KEY= minio服务的accessKey
MINIO_SECRET_KEY= minio服务的secretKey
6.MinioController.java Minio测试Controller
package cn.sunxiansheng.minio.controller;import cn.sunxiansheng.minio.utils.MinioUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.util.List;/*** Description: MinioController** @Author sun* @Create 2025/1/19 17:11* @Version 1.0*/
@RestController
public class MinioController {/*** A test endpoint.** @return A sample response.*/@RequestMapping("/test")public String test() {return "This is a test response from MinioController";}@Resourceprivate MinioUtil minioUtil;/*** 检查存储桶是否存在*/@GetMapping("/bucketExists")public boolean bucketExists(@RequestParam String bucketName) {return minioUtil.bucketExists(bucketName);}/*** 列出所有存储桶的名字*/@GetMapping("/listBucketNames")public List<String> listBucketNames() {return minioUtil.listBucketNames();}/*** 创建存储桶*/@PostMapping("/makeBucket")public String makeBucket(@RequestParam String bucketName) {minioUtil.makeBucket(bucketName);return "Bucket " + bucketName + " created successfully!";}/*** 删除空的存储桶*/@DeleteMapping("/removeBucket")public String removeBucket(@RequestParam String bucketName) {minioUtil.removeBucket(bucketName);return "Bucket " + bucketName + " removed successfully!";}/*** 上传文件并返回预览和下载链接*/@PostMapping("/upload")public List<String> uploadFile(@RequestParam MultipartFile file, @RequestParam String bucketName) {return minioUtil.putObject(file, bucketName);}/*** 下载文件到指定路径*/@GetMapping("/download")public String downloadFile(@RequestParam String bucketName,@RequestParam String objectName,@RequestParam String fileName) {minioUtil.downloadObject(bucketName, objectName, fileName);return "File " + objectName + " downloaded to " + fileName;}/*** 删除文件或文件夹*/@DeleteMapping("/removeObject")public String removeObjectOrFolder(@RequestParam String bucketName, @RequestParam String prefix) {return minioUtil.removeObjectOrFolder(bucketName, prefix);}
}
7.MinioApplication.java 启动类
package cn.sunxiansheng.minio;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: MinioApplication** @Author sun* @Create 2025/1/19 17:09* @Version 1.0*/
@SpringBootApplication
public class MinioApplication {public static void main(String[] args) {SpringApplication.run(MinioApplication.class, args);}
}
4.测试
1.创建一个存储桶
2.检查刚才创建的桶是否存在
3.上传文件并返回预览和下载链接
1.上传到test桶(已经使用mc开放了读权限)
2.预览和下载
3.如果没有开放读权限预览就是下面的报错
5.common-redis-starter
1.功能介绍
1. 快捷操作:
- 支持五大基础数据类型(String、Hash、List、Set、SortedSet)的全面操作。
- 常用功能包括新增、删除、修改、查询及批量操作,使用便捷。
2. 灵活性:
- 提供自定义缓存键名生成方法,支持默认分隔符(
:)
及自定义分隔符的拼接。 - 通过 Lua 脚本支持原子操作,提升操作性能。
3. 数据安全性:
- 缓存数据采用 JSON 序列化存储,自动保留类型信息,确保数据在反序列化时的准确性。
- 完善的类型转换支持,提供类型安全的 Redis 操作。
4. 高效的管理:
- 支持对键设置过期时间、延长有效期、批量删除等操作。
- 针对不同场景,提供丰富的类型专用方法,如:批量获取、排序操作、分数范围查询等。
6.丰富的操作功能:
String 类型:
- 快速设置键值。
- 设置带过期时间的缓存。
- 支持条件操作(如键不存在时才设置值)。
Hash 类型:
- 单值、多值的添加与删除。
- 获取单个值、多个值及完整键值对。
- 支持键值对的批量操作。
List 类型:
- 左/右添加与弹出。
- 根据索引操作列表元素。
- 支持获取指定范围及完整列表内容。
Set 类型:
- 元素的添加、删除及批量操作。
- 集合长度查询及随机元素获取。
- 检查集合是否包含某个元素。
SortedSet 类型:
- 添加元素及分数更新。
- 获取指定分数范围的元素及排序结果。
- 支持获取元素排名及分数。
2.配置示例
spring:redis:host: ${REDIS_HOST} # Redis服务器地址 ipport: ${REDIS_PORT} # Redis服务器端口password: ${REDIS_PASSWORD} # Redis服务器密码
3.案例演示
1.创建模块
2.目录结构
3.pom.xml
1.基本配置
<!-- 通过properties来指定版本号 -->
<properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version>
</properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
2.引入依赖
<dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-redis-starter</artifactId></dependency><!-- common-log4j2-starter 是必须引入的!!! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency><!-- 用来测试的Web模块 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency><!-- env模块确保数据安全,可以不引入 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-env-starter</artifactId></dependency></dependencies>
4.application.yml 配置日志根目录、.env文件的绝对路径以及Redis
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-redis-starter-demo/logs # 日志根目录(默认./logs)env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-redis-starter-demo # .env文件的绝对路径
spring:redis:host: ${REDIS_HOST} # Redis服务器地址 ipport: ${REDIS_PORT} # Redis服务器端口password: ${REDIS_PASSWORD} # Redis服务器密码
5…env 配置Redis的信息
REDIS_HOST= Redis服务器地址 ip
REDIS_PORT= Redis服务器端口
REDIS_PASSWORD= Redis服务器密码
6.测试的Controller
1.RHashController.java
package cn.sunxiansheng.redis.controller;import cn.sunxiansheng.redis.utils.RHash;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/rhash")
public class RHashController {private final RHash rHash;public RHashController(RHash rHash) {this.rHash = rHash;}@NoArgsConstructor@AllArgsConstructor@Datapublic static class User {private Long id;private String name;private Integer age;}/*** 设置单个hash值*/@PostMapping("/put")public void put(@RequestParam String key, @RequestParam String hashKey, @RequestBody User user) {rHash.put(key, hashKey, user);}/*** 设置多个hash值*/@PostMapping("/putAll")public void putAll(@RequestParam String key, @RequestBody Map<String, User> userMap) {rHash.putAll(key, userMap);}/*** 删除hash中的多个值*/@DeleteMapping("/deleteMultiple")public Long deleteMultiple(@RequestParam String key, @RequestBody List<String> hashKeys) {return rHash.delete(key, hashKeys);}/*** 删除hash中的单个值*/@DeleteMapping("/deleteSingle")public Long deleteSingle(@RequestParam String key, @RequestParam String hashKey) {return rHash.delete(key, hashKey);}/*** 获取单个hash值并转换为指定类型*/@GetMapping("/getOne")public User getOneMapValue(@RequestParam String key, @RequestParam String hashKey) {return rHash.getOneMapValue(key, hashKey, User.class);}/*** 获取多个hash值并转换为指定类型*/@GetMapping("/getMulti")public List<User> getMultiMapValue(@RequestParam String key, @RequestBody List<String> hashKeys) {return rHash.getMultiMapValue(key, hashKeys, User.class);}/*** 获取所有键值对并转换为指定类型*/@GetMapping("/getAll")public Map<String, User> getAll(@RequestParam String key) {return rHash.getAll(key, User.class);}/*** 判断hash中是否存在某个键*/@GetMapping("/hasHashKey")public Boolean hasHashKey(@RequestParam String key, @RequestParam String hashKey) {return rHash.hasHashKey(key, hashKey);}
}
2.RSetController.java
package cn.sunxiansheng.redis.controller;import cn.sunxiansheng.redis.utils.RSet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.io.Serializable;
import java.util.Set;/*** Description: RSet的测试Controller** @Author sun* @Create 2024/11/15* @Version 1.0*/
@RestController
@RequestMapping("/rset")
public class RSetController {@Autowiredprivate RSet rSet;/*** 静态内部类表示简单的自定义对象*/@Data@NoArgsConstructor@AllArgsConstructorpublic static class Element implements Serializable {private Long id;private String name;}/*** 添加一个元素*/@PostMapping("/add")public Long add(@RequestParam String key, @RequestBody Element element) {return rSet.add(key, element);}/*** 批量添加元素*/@PostMapping("/addBatch")public Long addBatch(@RequestParam String key, @RequestBody Set<Element> elements) {return rSet.addBatch(key, elements);}/*** 移除元素*/@PostMapping("/remove")public Long remove(@RequestParam String key, @RequestBody Set<Element> elements) {return rSet.remove(key, elements);}/*** 获取集合*/@GetMapping("/members")public Set<Element> members(@RequestParam String key) {return rSet.members(key, Element.class);}/*** 判断是否包含某元素*/@GetMapping("/isMember")public Boolean isMember(@RequestParam String key, @RequestBody Element element) {return rSet.isMember(key, element);}/*** 获取集合大小*/@GetMapping("/size")public Long size(@RequestParam String key) {return rSet.size(key);}
}
3.RSortedSetController.java
package cn.sunxiansheng.redis.controller;import cn.sunxiansheng.redis.utils.RSortedSet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;import java.util.Set;/*** Description: 测试 RSortedSet 工具类** @Author sun* @Create 2024/11/16* @Version 1.0*/
@RestController
@RequestMapping("/rsortedset")
public class RSortedSetController {@Autowiredprivate RSortedSet rSortedSet;// 自定义类型@Data@NoArgsConstructor@AllArgsConstructorpublic static class CustomValue {private Long id;private String name;}@PostMapping("/add")public Boolean add(@RequestParam String key, @RequestBody CustomValue value, @RequestParam double score) {return rSortedSet.add(key, value, score);}@PostMapping("/addBatch")public Long addBatch(@RequestParam String key, @RequestBody Set<RSortedSet.DataScore<CustomValue>> dataScores) {return rSortedSet.addBatch(key, dataScores);}@PostMapping("/remove")public Long remove(@RequestParam String key, @RequestBody Set<CustomValue> values) {return rSortedSet.remove(key, values);}@PostMapping("/removeRangeByScore")public Long removeRangeByScore(@RequestParam String key, @RequestParam double min, @RequestParam double max) {return rSortedSet.removeRangeByScore(key, min, max);}@PostMapping("/changeByDelta")public Double changeByDelta(@RequestParam String key, @RequestBody CustomValue value, @RequestParam double delta) {return rSortedSet.changeByDelta(key, value, delta);}@GetMapping("/reverseRangeWithScores")public Set<ZSetOperations.TypedTuple<CustomValue>> reverseRangeWithScores(@RequestParam String key) {return rSortedSet.reverseRangeWithScores(key, CustomValue.class);}@GetMapping("/score")public Double score(@RequestParam String key, @RequestBody CustomValue value) {return rSortedSet.score(key, value);}@GetMapping("/reverseRank")public Long reverseRank(@RequestParam String key, @RequestBody CustomValue value) {return rSortedSet.reverseRank(key, value);}@GetMapping("/zCard")public Long zCard(@RequestParam String key) {return rSortedSet.zCard(key);}@GetMapping("/count")public Long count(@RequestParam String key, @RequestParam double min, @RequestParam double max) {return rSortedSet.count(key, min, max);}
}
4.RStringController.java
package cn.sunxiansheng.redis.controller;import cn.sunxiansheng.redis.utils.RString;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** Description: 测试 RString 工具类的 Controller** @Author sun* @Create 2024/11/14 15:20* @Version 1.0*/
@RestController
@RequestMapping("/rstring")
public class RStringController {@Resourceprivate RString rString;/*** 设置缓存值*/@PostMapping("/set")public String set(@RequestParam String key, @RequestParam Long value) {rString.set(key, value);return "Value set successfully!";}/*** 设置缓存值并设置过期时间*/@PostMapping("/setWithExpire")public String setWithExpire(@RequestParam String key,@RequestParam Long value,@RequestParam long timeout) {rString.setWithExpire(key, value, timeout);return "Value set with expiration successfully!";}/*** 设置缓存值并设置过期时间(自定义时间单位)*/@PostMapping("/setWithExpireUnit")public String setWithExpireUnit(@RequestParam String key,@RequestParam Long value,@RequestParam long timeout) {rString.setWithExpire(key, value, timeout, TimeUnit.DAYS);return "Value set with custom expiration successfully!";}/*** 设置缓存值,如果key不存在,则设置成功*/@PostMapping("/setIfAbsent")public String setIfAbsent(@RequestParam String key,@RequestParam Long value,@RequestParam long timeout) {boolean result = rString.setIfAbsent(key, value, timeout);return result ? "Value set successfully!" : "Key already exists!";}/*** 获取缓存值*/@GetMapping("/get")public Long get(@RequestParam String key) {return rString.get(key, Long.class);}/*** 获取缓存值并设置新值*/@PostMapping("/getAndSet")public Long getAndSet(@RequestParam String key, @RequestParam Long value) {return rString.getAndSet(key, value, Long.class);}/*** 根据 delta 值调整缓存中的数值*/@PostMapping("/changeByDelta")public Long changeByDelta(@RequestParam String key, @RequestParam long delta) {return rString.changeByDelta(key, delta);}
}
5.RListController.java
package cn.sunxiansheng.redis.controller;import cn.sunxiansheng.redis.utils.RList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** 测试 RList 工具类的 Controller** @Author sun* @Create 2024/11/14 16:00* @Version 1.0*/
@RestController
@RequestMapping("/rlist")
public class RListController {@Autowiredprivate RList rList;/*** 左侧添加单个值*/@PostMapping("/leftPush")public String leftPush(@RequestParam String key, @RequestBody User user) {rList.leftPush(key, user);return "User added to the left of the list.";}/*** 左侧批量添加多个值*/@PostMapping("/leftPushAll")public String leftPushAll(@RequestParam String key, @RequestBody List<User> users) {rList.leftPushAll(key, users);return "Users added to the left of the list.";}/*** 右侧添加单个值*/@PostMapping("/rightPush")public String rightPush(@RequestParam String key, @RequestBody User user) {rList.rightPush(key, user);return "User added to the right of the list.";}/*** 右侧批量添加多个值*/@PostMapping("/rightPushAll")public String rightPushAll(@RequestParam String key, @RequestBody List<User> users) {rList.rightPushAll(key, users);return "Users added to the right of the list.";}/*** 根据索引设置List中的值*/@PutMapping("/set")public String set(@RequestParam String key, @RequestParam int index, @RequestBody User user) {rList.set(key, index, user);return "User updated at index " + index;}/*** 获取List中的所有数据*/@GetMapping("/rangeAll")public List<User> rangeAll(@RequestParam String key) {return rList.rangeAll(key, User.class);}/*** 根据索引获取List中的元素*/@GetMapping("/getElementByIndex")public User getElementByIndex(@RequestParam String key, @RequestParam int index) {return rList.getElementByIndex(key, index, User.class);}/*** 获取List的长度*/@GetMapping("/size")public Long size(@RequestParam String key) {return rList.size(key);}/*** 从右侧弹出元素*/@DeleteMapping("/popRight")public User popRight(@RequestParam String key) {return rList.popRight(key, User.class);}/*** 从左侧弹出元素*/@DeleteMapping("/popLeft")public User popLeft(@RequestParam String key) {return rList.popLeft(key, User.class);}/*** 根据值移除指定数量的匹配元素*/@DeleteMapping("/removeByValue")public String removeByValue(@RequestParam String key, @RequestParam int count, @RequestBody User user) {Long removedCount = rList.removeByValue(key, count, user);return removedCount + " matching users removed.";}
}/*** 简单的自定义类型 User** @Author sun* @Create 2024/11/14 15:50* @Version 1.0*/
@NoArgsConstructor
@Data
@AllArgsConstructor
class User implements java.io.Serializable {private String id;private String name;
}
7.RedisApplication.java 启动类
package cn.sunxiansheng.redis;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: RedisApplication** @Author sun* @Create 2025/1/19 19:33* @Version 1.0*/
@SpringBootApplication
public class RedisApplication {public static void main(String[] args) {SpringApplication.run(RedisApplication.class, args);}
}
8.测试RString
1.设置缓存值
2.获取缓存值
6.common-rabbitmq-starter
1. 功能介绍
1.自定义消息转换器
- 发送消息时根据数据类型动态设置
Content-Type
(application/json
或text/plain
)。 - 接收消息时根据
Content-Type
自动反序列化为 Java 对象或字符串。
2.增强的可扩展性
- 自定义消息转换器覆盖了默认的 RabbitMQ 消息转换器,实现了更加灵活的消息处理逻辑。
- 自动处理不支持的消息类型,抛出清晰的异常提示。
3.与 Spring Boot 高度集成
- 在
RabbitAutoConfiguration
之前加载配置,确保自定义逻辑优先生效。 - 将自定义消息转换器应用到
RabbitTemplate
,方便开发者直接使用。
2. 配置示例
spring:rabbitmq:host: ${RABBITMQ_HOST} # RabbitMQ 服务地址username: ${RABBITMQ_USERNAME} # 登录用户名password: ${RABBITMQ_PASSWORD} # 登录密码virtual-host: / # 虚拟主机路径port: ${RABBITMQ_PORT} # RabbitMQ 服务端口
3.案例演示
1.创建模块
1.父模块
2.生产者 publisher
3.消费者 consumer
2.目录结构
3.父pom.xml
1.统一管理子模块
<!-- 统一管理子模块 --><packaging>pom</packaging><modules><module>publisher</module><module>consumer</module></modules>
2.基本配置
<!-- 通过properties来指定版本号 -->
<properties><!-- 指定编译版本 --><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- 指定Sunrays-Framework的版本 --><sunrays.version>1.0.0</sunrays.version>
</properties><dependencyManagement><!-- 使用sunrays-dependencies来管理依赖,则依赖无需加版本号 --><dependencies><dependency><groupId>cn.sunxiansheng</groupId><artifactId>sunrays-dependencies</artifactId><version>${sunrays.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
3.引入依赖
<dependencies><!-- common-rabbitmq-starter --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-rabbitmq-starter</artifactId></dependency><!-- common-log4j2-starter 是必须引入的!!! --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-log4j2-starter</artifactId></dependency><!-- 用来测试的Web模块 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-web-starter</artifactId></dependency><!-- env模块确保数据安全,可以不引入 --><dependency><groupId>cn.sunxiansheng</groupId><artifactId>common-env-starter</artifactId></dependency>
</dependencies>
4.publisher
1.application.yml 配置日志根目录、.env文件的绝对路径以及RabbitMQ
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-rabbitmq-starter-demo/publisher/logs # 日志根目录(默认./logs)env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-rabbitmq-starter-demo/publisher # .env文件的绝对路径
spring:# RabbitMQ 配置rabbitmq:# 服务器地址 iphost: ${RABBITMQ_HOST}# 用户名username: ${RABBITMQ_USERNAME}# 密码password: ${RABBITMQ_PASSWORD}# 虚拟主机virtual-host: /# 端口port: ${RABBITMQ_PORT}
server:port: 8081
2…env 填写RabbitMQ的配置
RABBITMQ_HOST=host
RABBITMQ_USERNAME=用户名
RABBITMQ_PASSWORD=密码
RABBITMQ_PORT=端口
3.TestConfig.java 创建fanout类型的交换机和队列
package cn.sunxiansheng.publisher.config;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Description: 测试配置类** @Author sun* @Create 2024/12/31 19:00* @Version 1.0*/
@Configuration
public class TestConfig {/*** 创建一个fanout类型的交换机** @return*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("fanout.exchange.testExchange");}/*** 创建一个队列** @return*/@Beanpublic Queue fanoutQueue() {return QueueBuilder.durable("testQueue") // 持久化队列.lazy() // 惰性队列.build();}/*** 交换机和队列绑定*/@Beanpublic Binding binding() {return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());}
}
4.TestConfigPublisher.java 发布对象类型的消息
package cn.sunxiansheng.publisher.pub;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** Description: 测试发布者** @Author sun* @Create 2024/12/31 19:05* @Version 1.0*/
@RestController
@Slf4j
public class TestConfigPublisher {@Resourceprivate RabbitTemplate rabbitTemplate;/*** bean对象*/@Datastatic class Person {private String name;private int age;}/*** 发布对象类型的消息*/@RequestMapping("/send")public void send() {log.info("发送消息");Person person = new Person();person.setName("sun");person.setAge(18);rabbitTemplate.convertAndSend("fanout.exchange.testExchange", "", person);}
}
5.PublisherApplication.java 启动类
package cn.sunxiansheng.publisher;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: PublisherApplication** @Author sun* @Create 2025/1/20 14:55* @Version 1.0*/
@SpringBootApplication
public class PublisherApplication {public static void main(String[] args) {SpringApplication.run(PublisherApplication.class, args);}
}
5.consumer
1.application.yml 配置日志根目录、.env文件的绝对路径以及RabbitMQ
sun-rays:log4j2:home: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-rabbitmq-starter-demo/consumer/logs # 日志根目录(默认./logs)env:path: /Users/sunxiansheng/IdeaProjects/sunrays-framework-demo/common-rabbitmq-starter-demo/consumer # .env文件的绝对路径
spring:# RabbitMQ 配置rabbitmq:# 主机host: ${RABBITMQ_HOST}# 用户名username: ${RABBITMQ_USERNAME}# 密码password: ${RABBITMQ_PASSWORD}# 虚拟主机virtual-host: /# 端口port: ${RABBITMQ_PORT}
server:port: 8082
2…env 填写RabbitMQ的配置
RABBITMQ_HOST=host
RABBITMQ_USERNAME=用户名
RABBITMQ_PASSWORD=密码
RABBITMQ_PORT=端口
3.TestConfigConsumer.java 监听队列中的消息
package cn.sunxiansheng.consumer.con;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;/*** Description: 测试消费者** @Author sun* @Create 2024/12/31 19:03* @Version 1.0*/
@Component
@Slf4j
public class TestConfigConsumer {/*** bean对象*/@Datastatic class Person {private String name;private int age;}@RabbitListener(queues = "testQueue")public void receive(Person person) {String name = person.getName();int age = person.getAge();log.info("name:{}, age:{}", name, age);}
}
4.ConsumerApplication.java 启动类
package cn.sunxiansheng.consumer;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Description: ConsumerApplication** @Author sun* @Create 2025/1/20 14:55* @Version 1.0*/
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}
}
6.测试
1.发送消息
2.接受消息
7.总结
半年多的创作历程,每一行代码、每一个功能模块,都凝结了我无数个日日夜夜的努力与付出。从最初的构想到如今逐步完善的框架,我经历了无数的挑战,攻克了一个又一个技术难题,每一步都让我更加坚定要为开发者们带来更好、更高效的开发工具。
Sunrays-Framework 是我心血的结晶,它不仅包含了我对技术的探索,更承载了我对开发者的责任与承诺。在过去的半年里,我深入研究、精心打磨,将 MyBatis-Plus、Redis、RabbitMQ、Minio 等技术组件集成在其中,力求让框架既强大又易用,帮助开发者节省时间、提升效率,快速构建高质量的分布式系统。
尽管教程展示了框架的一个小部分,但框架的功能远远不止这些。它提供了 丰富的模块化设计、优雅的日志处理、高效的配置管理 等一系列功能,能在不同场景下满足开发者的需求。想要深入了解更多功能和最佳实践,官方文档是你必不可少的学习资源,它将带领你全面掌握框架的各个方面。
而这一切的实现离不开你们的支持与鼓励!我知道,每一个投票背后都是你们对我创作的认可和对开源精神的支持。你们的每一票,都是我继续前行的动力,是我不断优化、改进框架的不竭源泉。我会继续不断努力,让 Sunrays-Framework 成为每位开发者不可或缺的工具,为更多的开发者带来便利和提升。
最后,衷心感谢各位在百忙之中抽出宝贵时间阅读这篇文章,支持我,投票给我!你们的支持对我意义非凡,它不仅是对我过去半年来努力的肯定,更将成为我继续坚持下去的动力源泉。我相信,在大家的支持下,未来的 Sunrays-Framework会更加完善和强大,帮助更多的开发者走得更远,做得更好。
每一份支持,都是我前进的动力,每一次反馈,都是我成长的机会。谢谢大家,真的感谢你们的每一票!
相关文章:
「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程
文章目录 0.序言我的成长历程遇到挫折,陷入低谷重拾信心,迎接未来开源与分享我为何如此看重这次评选最后的心声 1.概述1.主要功能2.相关链接 2.系统要求构建工具框架和语言数据库与缓存消息队列与对象存储 3.快速入门0.配置Maven中央仓库1.打开settings.…...
【Elasticsearch】Springboot编写Elasticsearch的RestAPI
RestAPI 初始化RestClient创建索引库Mapping映射 判断索引库是否存在删除索引库总结 ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。 官方文档地址 由于ES目前最新版本是8.8,提供了全…...
Swift语言的学习路线
Swift语言的学习路线 引言 在现代程序开发中,Swift语言逐渐成为了移动应用程序开发的重要工具,尤其是在iOS和macOS平台上。自2014年发布以来,Swift以其易读性和强大的功能,受到越来越多开发者的青睐。对于初学者而言,…...
63,【3】buuctf web Upload-Labs-Linux 1
进入靶场 点击pass1 查看提示 既然是上传文件,先构造一句话木马,便于用蚁剑连接 <?php eval($_POST[123])?> 将这两处的检查函数删掉 再上传木马 文件后缀写为.php 右键复制图片地址 打开蚁剑连接 先点击测试连接,显示成功后&…...
Leetcode:2239
1,题目 2,思路 循环遍历满足条件就记录,最后返回结果值 3,代码 public class Leetcode2239 {public static void main(String[] args) {System.out.println(new Solution2239().findClosestNumber(new int[]{-4, -2, 1, 4, 8})…...
自然语言处理与NLTK环境配置
自然语言处理(Natural Language Processing, NLP)是人工智能的重要分支,专注于计算机如何理解、分析和生成自然语言。自然语言是人类用于交流的语言,如中文、英文等,这使得自然语言处理成为沟通人与计算机的桥梁。近年来,NLP在诸多领域得到广泛应用,包括文本分析、语言翻…...
分布式搜索引擎02
1. DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1. DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据,…...
使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法
在开发 Spring Boot 项目时,日志是调试和监控的重要工具。Spring Boot 默认支持 Logback 作为日志系统,并提供了 logback.xml 和 logback-spring.xml 两种配置方式。这篇文章将详细介绍这两者的区别、各自的优缺点以及最佳实践。 目录 一、什么是 Logbac…...
【爬虫开发】爬虫开发从0到1全知识教程第12篇:scrapy爬虫框架,介绍【附代码文档】
本教程的知识点为:爬虫概要 爬虫基础 爬虫概述 知识点: 1. 爬虫的概念 requests模块 requests模块 知识点: 1. requests模块介绍 1.1 requests模块的作用: 数据提取概要 数据提取概述 知识点 1. 响应内容的分类 知识点:…...
鸿蒙UI(ArkUI-方舟UI框架)-开发布局
文章目录 开发布局1、布局概述1)布局结构2)布局元素组成3)如何选择布局4)布局位置5)对子元素的约束 2、构建布局1)线性布局 (Row/Column)概述布局子元素在排列方向上的间距布局子元素在交叉轴上的对齐方式(…...
代码随想录_字符串
字符串 344.反转字符串 344. 反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。 思路: 双指针 代…...
2025年1月17日(点亮三色LED)
系统信息: Raspberry Pi Zero 2W 系统版本: 2024-10-22-raspios-bullseye-armhf Python 版本:Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习目标:…...
Spring Boot自动配置原理:如何实现零配置启动
引言 在现代软件开发中,Spring 框架已经成为 Java 开发领域不可或缺的一部分。而 Spring Boot 的出现,更是为 Spring 应用的开发带来了革命性的变化。Spring Boot 的核心优势之一就是它的“自动配置”能力,它极大地简化了 Spring 应用的配置…...
React技术栈搭配(全栈)(MERN栈、PERN栈)
文章目录 1. MERN 栈2. PERN 栈3. React Next.js Node.js4. JAMstack (JavaScript, APIs, Markup)5. React GraphQL Node.js6. React Native Node.js结论 React作为前端框架已经成为了现代web开发的重要组成部分。在全栈开发中,React通常…...
Linux - 线程池
线程池 什么是池? 池化技术的核心就是"提前准备并重复利用资源". 减少资源创建和销毁的成本. 那么线程池就是提前准备好一些线程, 当有任务来临时, 就可以直接交给这些线程运行, 当线程完成这些任务后, 并不会被销毁, 而是继续等待任务. 那么这些线程在程序运行过程…...
以Python构建ONE FACE管理界面:从基础至进阶的实战探索
一、引言 1.1 研究背景与意义 在人工智能技术蓬勃发展的当下,面部识别技术凭借其独特优势,于安防、金融、智能终端等众多领域广泛应用。在安防领域,可助力监控系统精准识别潜在威胁人员,提升公共安全保障水平;金融行业中,实现刷脸支付、远程开户等便捷服务,优化用户体…...
使用Sum计算Loss和解决梯度累积(Gradient Accumulation)的Bug
使用Sum计算Loss和解决梯度累积的Bug 学习 https://unsloth.ai/blog/gradient:Bugs in LLM Training - Gradient Accumulation Fix 这篇文章的记录。 在深度学习训练过程中,尤其是在大批量(large batch)训练中,如何高…...
mfc操作json示例
首先下载cJSON,加入项目; 构建工程,如果出现, fatal error C1010: unexpected end of file while looking for precompiled head 在cJSON.c文件的头部加入#include "stdafx.h"; 看情况,可能是加到.h或者是.cpp文件的头部,它如果有包含头文件, #include &…...
C语言练习(18)
一个班10个学生的成绩,存放在一个一维数组中,要求找出其中成绩最高的学生成绩和该生的序号。 #include <stdio.h>#define STUDENT_NUM 10 // 定义学生数量int main() {int scores[STUDENT_NUM]; // 定义存储学生成绩的一维数组int i;// 输入10个…...
LeetCode 热题 100_全排列(55_46_中等_C++)(递归(回溯))
LeetCode 热题 100_两数之和(55_46) 题目描述:输入输出样例:题解:解题思路:思路一(递归(回溯)): 代码实现代码实现(思路一(…...
编译chromium笔记
编译环境: windows10 powershell7.2.24 git 2.47.1 https://storage.googleapis.com/chrome-infra/depot_tools.zip 配置git git config --global user.name "John Doe" git config --global user.email "jdoegmail.com" git config --global …...
PHP语言的数据库编程
PHP语言的数据库编程 引言 随着互联网的发展,动态网站已成为主流,而动态网站的核心就是与数据库进行交互。PHP(超文本预处理器)是一种流行的开源服务器端脚本语言,被广泛用于Web开发。它以其简单易学和功能强大而受到…...
【PGCCC】PostgreSQL 中表级锁的剖析
本博客解释了 PostgreSQL 中的锁定机制,重点关注数据定义语言 (DDL) 操作所需的表级锁定。 锁定还是解锁的艺术? 人们通常将数据库锁与物理锁进行比较,这甚至可能导致您订购有关锁的历史、波斯锁和撬锁技术的书籍。我们大多数人可能都是通过…...
1.10 自洽性(Self-Consistency):多路径推理的核心力量
自洽性(Self-Consistency):多路径推理的核心力量 随着人工智能尤其是大规模语言模型的不断进化,如何提升其推理能力和决策准确性成为了研究的重点。在这一背景下,**自洽性(Self-Consistency)**作为一种新的推理方法,逐渐展现出其强大的潜力。自洽性方法通过多路径推理…...
【24】Word:小郑-准考证❗
目录 题目 准考证.docx 邮件合并-指定考生生成准考证 Word.docx 表格内容居中表格整体相较于页面居中 考试时一定要做一问保存一问❗ 题目 准考证.docx 插入→表格→将文本转换成表格→✔制表符→确定选中第一列→单击右键→在第一列的右侧插入列→布局→合并单元格&#…...
Linux 信号(Signal)详解
信号(Signal)是 Linux 系统中用于进程间通信的一种机制。它是一种异步通知,用于通知进程发生了某个事件。信号可以来自内核、其他进程或进程自身。 信号的基本概念 信号的作用: 通知进程发生了某个事件(如用户按下 Ct…...
【数据分享】1929-2024年全球站点的逐年最低气温数据(Shp\Excel\免费获取)
气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、湿度等指标!说到气象数据,最详细的气象数据是具体到气象监测站点的数据! 有关气象指标的监测站点数据,之前我们分享过1929-2024年全球气象站点…...
app版本控制java后端接口版本管理
java api version 版本控制 java接口版本管理 1 自定义 AppVersionHandleMapping 自定义AppVersionHandleMapping实现RequestMappingHandlerMapping里面的方法 public class AppVersionHandleMapping extends RequestMappingHandlerMapping {Overrideprotected RequestCondit…...
2024年度总结-CSDN
2024年CSDN年度总结 Author:OnceDay Date:2025年1月21日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 文章目录 2024年CSDN年度总结1. 整体回顾2…...
基于python的博客系统设计与实现
摘要:目前,对于信息的获取是十分的重要,我们要做到的不是裹足不前,而是应该主动获取和共享给所有人。博客系统就能够实现信息获取与分享的功能,博主在发表文章后,互联网上的其他用户便可以看到,…...
服务器日志自动上传到阿里云OSS备份
背景 公司服务器磁盘空间有限,只能存近15天日志,但是有时需要查看几个月前的日志,需要将服务器日志定时备份到某个地方,需要查询的时候有地方可查。 针对这个问题,想到3个解决方法: 1、买一个配置比较低…...
优化使用 Flask 构建视频转 GIF 工具
优化使用 Flask 构建视频转 GIF 工具 优化后的项目概述 在优化后的版本中,我们将实现以下功能: 可设置每个 GIF 的帧率和大小:用户可以选择 GIF 的帧率和输出大小。改进的用户界面:使用更现代的设计使界面更美观、整洁。自定义…...
leetcode:511. 游戏玩法分析 I
难度:简单 SQL Schema > Pandas Schema > 活动表 Activity: ----------------------- | Column Name | Type | ----------------------- | player_id | int | | device_id | int | | event_date | date | | games_playe…...
windows git bash 使用zsh 并集成 oh my zsh
参考了 这篇文章 进行配置,记录了自己的踩坑过程,并增加了 zsh-autosuggestions 插件的集成。 主要步骤: 1. git bash 这个就不说了,自己去网上下,windows 使用git时候 命令行基本都有它。 主要也是用它不方便&…...
【Python运维】Python与网络监控:如何编写网络探测与流量分析工具
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着互联网技术的快速发展,网络性能的监控与分析成为保障信息系统稳定运行的关键环节。本文深入探讨了如何利用Python语言构建高效的网络探…...
OpenCV相机标定与3D重建(61)处理未校准的立体图像对函数stereoRectifyUncalibrated()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 为未校准的立体相机计算一个校正变换。 cv::stereoRectifyUncalibrated 是 OpenCV 库中的一个函数,用于处理未校准的立体图像对。该函…...
字玩FontPlayer开发笔记12 Vue3撤销重做功能
字玩FontPlayer开发笔记12 Vue3撤销重做功能 字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 ElementUI开发,源代码:github | gitee 笔记 撤销重做功能是设计工具必不可少的模块,以前尝试使用成熟的库实现撤销重做功能…...
无人机图传模块:深入理解其工作原理与实际效用
无人机图传模块作为无人机系统的关键组成部分,承担着将无人机拍摄的图像和视频实时传输至地面控制站或接收设备的重任。本文将深入探讨无人机图传模块的工作原理及其在实际应用中的效用,帮助读者更好地理解这一技术的奥秘。 一、无人机图传模块的工作原…...
PDF文件提取开源工具调研总结
概述 PDF是一种日常工作中广泛使用的跨平台文档格式,常常包含丰富的内容:包括文本、图表、表格、公式、图像。在现代信息处理工作流中发挥了重要的作用,尤其是RAG项目中,通过将非结构化数据转化为结构化和可访问的信息࿰…...
Linux(Centos 7.6)命令详解:dos2unix
1.命令作用 将Windows格式文件件转换为Unix、Linux格式的文件(也可以转换成其他格式的) 2.命令语法 Usage: dos2unix [options] [file ...] [-n infile outfile ...] 3.参数详解 options: -c, --convmode,转换方式,支持ascii, 7bit, iso, mac,默认…...
梯度提升决策树树(GBDT)公式推导
### 逻辑回归的损失函数 逻辑回归模型用于分类问题,其输出是一个概率值。对于二分类问题,逻辑回归模型的输出可以表示为: \[ P(y 1 | x) \frac{1}{1 e^{-F(x)}} \] 其中 \( F(x) \) 是一个线性组合函数,通常表示为ÿ…...
跨域问题分析及解决方案
1、跨域 指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。 2、同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域; 3、跨域流程…...
【三国游戏——贪心、排序】
题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e510; int a[N], b[N], c[N]; int w[4][N]; int main() {int n;cin >> n;for(int i 1; i < n; i)cin >> a[i];for(int i 1; i < n; i)cin >> b[i…...
深入理解 Java 的数据类型与运算符
Java学习资料 Java学习资料 Java学习资料 在 Java 编程中,数据类型与运算符是构建程序的基础元素。它们决定了数据在程序中的存储方式以及如何对数据进行各种操作。 一、数据类型 (一)基本数据类型 整型: 用于存储整数数值&…...
WOA-CNN-GRU-Attention、CNN-GRU-Attention、WOA-CNN-GRU、CNN-GRU四模型对比多变量时序预测
WOA-CNN-GRU-Attention、CNN-GRU-Attention、WOA-CNN-GRU、CNN-GRU四模型对比多变量时序预测 目录 WOA-CNN-GRU-Attention、CNN-GRU-Attention、WOA-CNN-GRU、CNN-GRU四模型对比多变量时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于WOA-CNN-GRU-Attention、…...
(二叉树)
我们今天就开始引进一个新的数据结构了:我们所熟知的:二叉树; 但是我们在引进二叉树之前我们先了解一下树; 树 树的概念和结构: 树是⼀种⾮线性的数据结构,它是由 n ( n>0 ) …...
Linux shell 批量验证端口连通性
脚本 #!/bin/bash # #database check #set -o nounset LOCALIPifconfig | grep inet | head -1 | awk {print $2} | sed s/addr\:// IPLIST192.168.1.99 192.168.1.98 192.168.1.97 PORTLIST81 82 83 84 85 86 check_nc(){ for CHECK_IP in $IPLIST dofor CHECK_PORT in $PORT…...
Java 中实体类与操作类分离
目录 一、为啥要把实体类和操作类分开 二、实体类长啥样,怎么用 三、操作类的使命与实现 四、实战演练:实体类与操作类协同工作 五、拓展思考:这种分离带来的好处与进一步优化 六、总结与展望 家人们,今天我想跟你们唠唠我在…...
创建 pdf 合同模板
创建 pdf 合同模板 一、前言二、模板展示三、制作过程 一、前言 前段时间要求创建“pdf”模板,学会了后感觉虽然简单,但开始也折腾了好久,这里做个记录。 二、模板展示 要创建这样的模板 三、制作过程 新建一个“Word”,这里命…...
【Prometheus】PromQL进阶用法
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...