首页 > 编程语言 >「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程

「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程

时间:2025-01-22 09:31:07浏览次数:3  
标签:Java String sunrays 自研 2024 common key import public

文章目录

0.序言

很荣幸能够参与到 2024年博客之星评选活动。在此,请允许我简单地介绍一下自己:

我的成长历程

我是 2025届 的一名计算机专业学生,从小学到高中,我一直是那个努力学习、听话的孩子。周围的人都在埋头苦读,似乎学习和考试就是我们人生的全部意义

进入大学后,我依然保持着高中的学习状态。即使室友们在深夜 12:30 熄灯,我也坚持早起学习,坐在课堂的第一排,每一堂课都全神贯注。大一时,我的专业成绩排名 第四,连续两年获得 奖学金。虽然在外人眼中,我是一个“出类拔萃”的学生,但内心深处的迷茫和压力始终伴随着我。

某一天,我开始思考:人生的意义究竟是什么? 难道就是不停地学习和考试吗?于是,我开始阅读各类哲学书籍,试图从中找到人生的答案。《幸福之路》、 《苏菲的世界》、《苏格拉底的申辩》…… 这些书让我渐渐意识到,人生并不只是学习和考试,更重要的是找到属于自己的方向和热爱。那时,加入了鱼皮的知识星球,看到许多伙伴分享 Java学习心得,心中悄然燃起了对编程的渴望。从那一刻起,成为 Java后端工程师成为了我的第一个梦想。

于是,我开始了漫长的自学之旅。从 韩顺平老师的600小时Java课程 到手写 TomcatServletSpringSpringMVCMyBatis 的底层实现,我每天学习 8到11小时,甚至连春节都只休息了一天。用八个月时间,完成了正常一年才能学完的内容。通过这段时间的努力,我掌握了完整的 Java体系,并且反复研究 设计模式,通过视频、书籍和总结的方式学了四遍。这一年的时间,我的语雀文档笔记已经到达了一百万字。

CleanShot 2025-01-20 at 12.18.44@2x

CleanShot 2025-01-20 at 12.18.55@2x

不仅如此,我还跟随鸡翅老哥的 Club项目,完成了 八万行后端代码,完成了五期的全部内容,并独自将项目部署到 8台服务器 上。看着群里连做这个项目到处问问题的人都进了字节,而我却能独自解决所有问题,我就更有信心了,也让我无比坚定了自己的选择。

为了秋招,我根据简历整理出了 八万字的面试题,每天按计划背诵,虽然枯燥无味,但我依然坚持了下来。

遇到挫折,陷入低谷

然而,秋招的经历让我第一次真正体会到现实的压力。第一次大厂面试,我因为算法准备的不充分而被刷掉,面试官的一句话更让我深受打击:“你们这些应届生项目我看不上,很多人连项目都没有,你基础太差了。”这一刻,我感受到前所未有的打击,难道只有算法才算基础?我辛辛苦苦做的 Java底层项目经验 就不值一提吗?

在秋招的最后,我获得了一个小厂自研的工作。然后因为正在等待中厂的意向,我选择去小厂试一试,在 10月末,中厂发了意向,考虑到这个公司在网上风评不错,并且在这个小厂感觉每天技术都在退步,只是做一些业务的处理,完全用不到我学的那么多技术,并且小厂在一个月试用期后离职就要付公司一个月的培训费用,就先离职了。

然而,11月末中厂的意向突然被毁掉,那一刻的巨大落差让我瞬间陷入了迷茫。那些曾经不眠不休、全力以赴的日子,似乎在一瞬间都变得毫无意义。这种挫败感让我深陷痛苦,彻夜难眠,反复思考:我究竟错在哪里?

从小到大,我几乎没有真正休息过。大三时,我更是将全部的精力都投入到 Java 学习中。别人在午休时,我在埋头钻研;别人在享受娱乐、玩游戏时,我却依然坚持学习。我几乎舍弃了生活中的一切,只为了让自己在未来能够更加出色。那段时间,我用辛勤的努力为自己构筑了一座信念之塔,然而却在这一刻轰然倒塌

重拾信心,迎接未来

失意的阴影笼罩着我,质疑与痛苦一度让我无法自拔。过去的每一份坚持与牺牲,都像是一场徒劳的幻梦,让人怀疑努力的意义。然而,也正是在这一刻,我开始意识到——或许,这只是前行路上的一块绊脚石,而不是终点。我必须学会站起来,重新出发。

经历了这段低谷期,我重新审视自己,发现其实我并没有尽全力。如果每天 8到11小时 不够,那就努力把时间延长到 12小时;如果算法不行,那就每天刷 10道算法题;如果我的项目不够好,那就自研框架并反复优化。

虽然在小厂没有待多久,而且离职资料完全被删除,但是因为当时用小厂自研的框架写过几个接口,即使没有看过具体框架的代码,我也凭借着扎实的 Java基础,以及 设计模式 的基础,用了几天时间经过逐步的思考、优化,最终的实现效果竟然与原框架不谋而合

通过参与企业项目,我了解了一些企业开发中的痛点,并不断优化和增加框架功能,这些经验不仅丰富了我的技术积累,也让我更加坚定了继续前行的决心。

开源与分享

加入 CSDN 后,我秉承 开源精神,并专注于技术分享与输出。在半年多的时间里,发布275篇高质量文章平均质量分90分,得到了12000多粉丝的关注,铁粉数量900多

此次,我决定将自己半年多来精心编写的框架 Sunrays-Framework 开源到 GitCode,并在CSDN附上详细的文档和教程,希望能帮助更多正在学习的朋友,也希望我的经验能够激励更多人相信,只要 坚持不懈,终将迎来希望。

CleanShot 2025-01-19 at 21.41.33@2x

我为何如此看重这次评选

这次评选不仅仅是对我过去半年努力的肯定,更是我 春招路上最后的底气。作为一名即将毕业的学生,在 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.主要功能

CleanShot 2025-01-20 at 12.14.57@2x


本人在此承诺:只要我做Java一天,框架就会不断的升级!

永久开源,永久免费!


2.相关链接

CleanShot 2025-01-20 at 11.42.31@2x

2.系统要求

为确保系统正常运行,以下是本项目所需的技术栈及版本要求。


构建工具

工具版本
Maven3.6.3 或更高版本

框架和语言

技术版本
Spring Boot2.4.2
Spring Cloud2020.0.1
Spring Cloud Alibaba2021.1
JDK1.8

数据库与缓存

技术版本
MySQL5.7
Redis6.2.6

消息队列与对象存储

技术版本
RabbitMQ3.8.8
MinIO2024-12-19

3.快速入门

0.配置Maven中央仓库

1.打开settings.xml

CleanShot 2025-01-19 at 23.16.59@2x

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

CleanShot 2025-01-18 at 18.50.39@2x

2.基本目录结构

CleanShot 2025-01-18 at 23.05.33@2x

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.测试运行

CleanShot 2025-01-18 at 23.00.01@2x

6.请求测试
1.Controller的返回结果是String,默认自动被包装了

CleanShot 2025-01-18 at 22.50.50@2x

2.自带链路追踪以及全链路的日志输出

CleanShot 2025-01-18 at 22.49.06@2x

4.基础知识(必读)

1.项目架构

1.图示

CleanShot 2025-01-18 at 23.14.51@2x

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-commonsunrays-common-cloud 的测试 demo,继承 sunrays-framework
  • 描述:用于验证 sunrays-commonsunrays-common-cloud 子模块的功能和集成。
6. sunrays-combinations
  • 职责:管理业务依赖,或者作为中台,继承 sunrays-framework
  • 描述:通过组合 sunrays-commonsunrays-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

在实际开发中,如果不需要进行隐私数据的保护,就可以不引入这个依赖:

  1. 不需要在application.yml配置文件中配置.env文件的路径,也不需要创建.env文件了
  2. 将我示例中的${xxx}的部分直接替换为真实的数据即可,比如:

CleanShot 2025-01-19 at 12.48.42@2x

5.核心模块介绍

1.common-log4j2-starter

1.功能介绍
  1. ApplicationReadyListener
    • 程序启动时,动态获取并打印以下信息:
      • 日志存储的根目录的绝对路径
      • 应用的访问地址(包括端口)
      • 前端请求时可用的日期格式
  2. ApplicationEnvironmentPreparedListener
    • 获取日志根目录及模块名,并将其设置为环境变量供 log4j2-spring.xml 使用。
  3. TraceIdLoggingAspect
    • 每次请求开始时打印一行日志,包含请求的 traceId,以便于日志追踪。
  4. LogAspect
    • 日志切面(AOP),匹配所有 controllerservice 包中的方法,记录以下信息:
      • 方法的执行时间
      • 请求参数
      • 返回结果
  5. 使用自定义的 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.创建模块

CleanShot 2025-01-19 at 12.52.54@2x

2.目录结构

CleanShot 2025-01-19 at 13.10.11@2x

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.启动

CleanShot 2025-01-19 at 13.13.16@2x

2.请求

CleanShot 2025-01-21 at 09.39.53@2x

2.common-web-starter

1.功能介绍
1.JacksonConfig提供对日期类型的序列化支持
  • 配置 Jackson 的 ObjectMapper 来为 Date 类型指定自定义的序列化和反序列化格式。这样,前后端可以统一日期格式。
2.修饰SpringMVC 中的请求处理适配器
  • 通过自定义注解 IgnoredResultWrapper 和装饰器模式对 SpringMVC 中的请求处理适配器进行扩展,控制响应结果的包装及处理方式。
3.将前台传进的多种日期格式自动反序列化为 Date 类型
  • 使用 @InitBinder 来解析来自前端的多种日期格式,确保它们能正确反序列化为 Date 类型。
2.配置示例

配置 Maven 来打包项目时,指定 .jar 文件的名称为项目的 artifactIdversion,并使用 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.创建模块

CleanShot 2025-01-19 at 13.36.45@2x

2.目录结构

CleanShot 2025-01-19 at 13.51.28@2x

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.第一种方式:直接使用自动包装成功结果

CleanShot 2025-01-19 at 13.55.25@2x

2.第二种方式:使用 @IgnoredResultWrapper注解忽略掉自动包装

CleanShot 2025-01-19 at 13.55.48@2x

3.第三种方式:直接使用ResultWrapper来自己封装结果

CleanShot 2025-01-19 at 13.56.10@2x

4.测试打包功能 clean install

CleanShot 2025-01-19 at 13.56.58@2x

CleanShot 2025-01-19 at 13.57.14@2x

3.common-mybatis-plus-starter

1.功能介绍
1.自定义分页封装
  • 只需传递 pageNumpageSizetotaldata 即可自动完成分页封装,简化分页逻辑。
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.在插件设置中选择从本地导入配置

CleanShot 2025-01-19 at 14.38.51@2x

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
   

CleanShot 2025-01-19 at 14.40.10@2x

2.IDEA连接数据库
1.点击右上角的数据库标志,然后点击加号,选择要连接的数据库

CleanShot 2025-01-19 at 14.47.49@2x

2.填写数据库信息进行连接

CleanShot 2025-01-19 at 14.50.06@2x

3.创建并使用数据库 sunrays_framework

CleanShot 2025-01-19 at 14.53.54@2x

CleanShot 2025-01-19 at 14.54.04@2x

create database sunrays_framework;
use sunrays_framework;
4.创建示例表

CleanShot 2025-01-19 at 14.55.42@2x

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 = InnoDB
  DEFAULT 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连接刚才创建的数据库

CleanShot 2025-01-19 at 15.11.53@2x

CleanShot 2025-01-19 at 15.12.17@2x

3.项目环境搭建
1.创建模块 common-mybatis-plus-starter-demo

CleanShot 2025-01-19 at 14.59.01@2x

2.目录结构

CleanShot 2025-01-19 at 15.07.33@2x

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. 引入依赖

  3.     <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.启动测试

CleanShot 2025-01-19 at 15.15.09@2x

CleanShot 2025-01-19 at 15.15.17@2x

4.使用EasyCode生成代码
1.选中指定的表,右键生成代码

CleanShot 2025-01-19 at 15.17.06@2x

2.选择Module和Package以及之前导入的模板,点击OK

CleanShot 2025-01-19 at 15.18.54@2x

3.生成的代码

CleanShot 2025-01-19 at 15.21.51@2x

5.测试分页查询
1.不加任何条件查询第一页,页面大小为三的数据

CleanShot 2025-01-19 at 15.24.40@2x

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方法的入参格式化打印

CleanShot 2025-01-19 at 15.27.18@2x

2.统计数量的sql格式化打印

CleanShot 2025-01-19 at 15.27.57@2x

3.查询数据的sql格式化打印

CleanShot 2025-01-19 at 15.28.39@2x

4.controller和service方法的出参格式化打印

4.部分生成代码说明
1.ExampleTableController.java
1.展示

CleanShot 2025-01-19 at 15.37.16@2x

CleanShot 2025-01-19 at 15.37.32@2x

CleanShot 2025-01-19 at 15.38.02@2x

2.介绍
  1. 该文件是Controller
  2. 继承了BaseController,提供了Date类型的自动转换,和一些快捷的响应方法
  3. 提供了一些基础的接口实现
  4. 如果想要自定义接口,直接在下面调用Service即可,跟平常的使用方式是一样的
2.ExampleTableService.java
1.展示

CleanShot 2025-01-19 at 15.41.55@2x

CleanShot 2025-01-19 at 15.57.46@2x

2.介绍
  1. 该文件是Service接口
  2. 两个泛型分别是与数据库对应的entity的类型以及id类型
  3. 使用的时候也是跟平常一样,在接口内加一个方法
3.ExampleTableServiceImpl.java
1.展示

CleanShot 2025-01-19 at 15.45.21@2x

CleanShot 2025-01-19 at 15.52.09@2x

2.介绍
  1. 该文件是Service的实现类
  2. 三个泛型分别是调用MyBatis Plus方法的Mapper类型,与数据库对应的entity的类型以及id类型
  3. 构造器是为了在运行时动态给父类设置具体的操作Mybatis Plus的Mapper
  4. 调用框架自动生成的方法使用super.xxx,调用自己实现的方法用注入的Mapper
  5. 使用的时候,就不需要管那么多,直接实现Service方法即可
4.ExampleTableMapper.java
1.展示

CleanShot 2025-01-19 at 15.56.22@2x

2.介绍
  1. 该文件是Mapper接口
  2. 提供了三个基础的方法
  3. 使用起来也是跟平常一样,加方法
5.ExampleTableMapper.xml
1.展示

CleanShot 2025-01-19 at 16.00.13@2x

2.介绍
  1. 该文件是Mapper的实现类
  2. 提供了三个基础方法的实现
  3. 使用起来就直接实现Mapper接口的方法去写sql就行
5.示例:使用框架编写一个需求
1.需求

分页查询id大于5的用户

2.目录结构

CleanShot 2025-01-19 at 16.54.27@2x

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_table
    where 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_deleted
    from example_table
    where id > 5
    and is_deleted = 0
    limit #{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) -> {
                // 查询数据,并转换为vo
                List<ExampleTable> exampleTableList =
                        exampleTableMapper.queryByPageAboutId(offset, limit);
                List<ExampleTableVo> exampleTableVos = ExampleTableConverter.INSTANCE.convertPoList2VoList(exampleTableList);
                return exampleTableVos;
            }
    );
    return paginate;
}
7.ExampleTableController.java 新增req和分页查询方法
    @Data
    public 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.查询结果

CleanShot 2025-01-19 at 16.58.08@2x

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服务的accessKey
    secretKey: ${MINIO_SECRET_KEY}  # minio服务的secretKey
3.案例演示
1.创建模块

CleanShot 2025-01-19 at 17.08.30@2x

2.目录结构

CleanShot 2025-01-19 at 17.18.16@2x

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服务的accessKey
    secretKey: ${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";
    }

    @Resource
    private 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.创建一个存储桶

CleanShot 2025-01-19 at 17.28.35@2x

2.检查刚才创建的桶是否存在

CleanShot 2025-01-19 at 17.30.20@2x

3.上传文件并返回预览和下载链接
1.上传到test桶(已经使用mc开放了读权限)

CleanShot 2025-01-19 at 17.34.34@2x

2.预览和下载

CleanShot 2025-01-19 at 17.33.53@2x

CleanShot 2025-01-19 at 17.35.08@2x

3.如果没有开放读权限预览就是下面的报错

CleanShot 2025-01-19 at 17.36.49@2x

5.common-redis-starter

1.功能介绍
1. 快捷操作:
  • 支持五大基础数据类型(String、Hash、List、Set、SortedSet)的全面操作。
  • 常用功能包括新增、删除、修改、查询及批量操作,使用便捷。
2. 灵活性:
  • 提供自定义缓存键名生成方法,支持默认分隔符(:)及自定义分隔符的拼接。
  • 通过 Lua 脚本支持原子操作,提升操作性能。
3. 数据安全性:
  • 缓存数据采用 JSON 序列化存储,自动保留类型信息,确保数据在反序列化时的准确性。
  • 完善的类型转换支持,提供类型安全的 Redis 操作。
4. 高效的管理:
  • 支持对键设置过期时间、延长有效期、批量删除等操作。
  • 针对不同场景,提供丰富的类型专用方法,如:批量获取、排序操作、分数范围查询等。

6.丰富的操作功能:
String 类型:
  • 快速设置键值。
  • 设置带过期时间的缓存。
  • 支持条件操作(如键不存在时才设置值)。
Hash 类型:
  • 单值、多值的添加与删除。
  • 获取单个值、多个值及完整键值对。
  • 支持键值对的批量操作。
List 类型:
  • 左/右添加与弹出。
  • 根据索引操作列表元素。
  • 支持获取指定范围及完整列表内容。
Set 类型:
  • 元素的添加、删除及批量操作。
  • 集合长度查询及随机元素获取。
  • 检查集合是否包含某个元素。
SortedSet 类型:
  • 添加元素及分数更新。
  • 获取指定分数范围的元素及排序结果。
  • 支持获取元素排名及分数。

CleanShot 2025-01-19 at 19.34.40@2x

2.配置示例
spring:
  redis:
    host: ${REDIS_HOST}  # Redis服务器地址 ip
    port: ${REDIS_PORT}  # Redis服务器端口
    password: ${REDIS_PASSWORD}  # Redis服务器密码
3.案例演示
1.创建模块

CleanShot 2025-01-19 at 19.22.47@2x

2.目录结构

CleanShot 2025-01-19 at 19.39.32@2x

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服务器地址 ip
    port: ${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
    @Data
    public 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 {

    @Autowired
    private RSet rSet;

    /**
     * 静态内部类表示简单的自定义对象
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public 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 {

    @Autowired
    private RSortedSet rSortedSet;

    // 自定义类型
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public 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 {

    @Resource
    private 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 {

    @Autowired
    private 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.设置缓存值

CleanShot 2025-01-19 at 19.46.57@2x

2.获取缓存值

CleanShot 2025-01-19 at 19.47.34@2x

6.common-rabbitmq-starter

1. 功能介绍
1.自定义消息转换器
  • 发送消息时根据数据类型动态设置 Content-Typeapplication/jsontext/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.父模块

CleanShot 2025-01-20 at 14.49.43@2x

2.生产者 publisher

3.消费者 consumer

CleanShot 2025-01-20 at 14.53.41@2x

2.目录结构

CleanShot 2025-01-20 at 15.12.16@2x

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:
    # 服务器地址 ip
    host: ${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
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanout.exchange.testExchange");
    }

    /**
     * 创建一个队列
     *
     * @return
     */
    @Bean
    public Queue fanoutQueue() {
        return QueueBuilder.durable("testQueue") // 持久化队列
                .lazy()               // 惰性队列
                .build();
    }

    /**
     * 交换机和队列绑定
     */
    @Bean
    public 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 {

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * bean对象
     */
    @Data
    static 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对象
     */
    @Data
    static 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.发送消息

CleanShot 2025-01-20 at 15.32.20@2x

CleanShot 2025-01-20 at 15.32.12@2x

2.接受消息

CleanShot 2025-01-20 at 15.32.38@2x

7.总结

半年多的创作历程,每一行代码、每一个功能模块,都凝结了我无数个日日夜夜的努力与付出。从最初的构想到如今逐步完善的框架,我经历了无数的挑战,攻克了一个又一个技术难题,每一步都让我更加坚定要为开发者们带来更好、更高效的开发工具。

Sunrays-Framework 是我心血的结晶,它不仅包含了我对技术的探索,更承载了我对开发者的责任与承诺。在过去的半年里,我深入研究、精心打磨,将 MyBatis-PlusRedisRabbitMQMinio 等技术组件集成在其中,力求让框架既强大又易用,帮助开发者节省时间、提升效率,快速构建高质量的分布式系统。

尽管教程展示了框架的一个小部分,但框架的功能远远不止这些。它提供了 丰富的模块化设计优雅的日志处理高效的配置管理 等一系列功能,能在不同场景下满足开发者的需求。想要深入了解更多功能和最佳实践,官方文档是你必不可少的学习资源,它将带领你全面掌握框架的各个方面。

而这一切的实现离不开你们的支持与鼓励!我知道,每一个投票背后都是你们对我创作的认可和对开源精神的支持。你们的每一票,都是我继续前行的动力,是我不断优化、改进框架的不竭源泉。我会继续不断努力,让 Sunrays-Framework 成为每位开发者不可或缺的工具,为更多的开发者带来便利和提升。

最后,衷心感谢各位在百忙之中抽出宝贵时间阅读这篇文章,支持我,投票给我!你们的支持对我意义非凡,它不仅是对我过去半年来努力的肯定,更将成为我继续坚持下去的动力源泉。我相信,在大家的支持下,未来的 Sunrays-Framework会更加完善和强大,帮助更多的开发者走得更远,做得更好。

每一份支持,都是我前进的动力,每一次反馈,都是我成长的机会。谢谢大家,真的感谢你们的每一票!

标签:Java,String,sunrays,自研,2024,common,key,import,public
From: https://blog.csdn.net/m0_64637029/article/details/145275796

相关文章

  • 2024年CSDN博客年度总结 Java | 成神之路
    目录 博客创作之旅的前期沉淀年度创作成果​编辑博客创作历程创作风格与技巧创作收获与成长未来规划结束语 博客创作之旅的前期沉淀我于2020年入驻CSDN,初涉技术领域时,作为Java编程的小白,并未即刻投身创作。彼时,我将大量精力投入到知识汲取中。学习期间,我对笔......
  • 计算机毕业设计Springboot基于Java的医院床位管理系统 基于Spring Boot的Java医院床位
    计算机毕业设计Springboot基于Java的医院床位管理系统18b553a9(配套有源码程序mysql数据库论文)本套源码可以先看具体功能演示视频领取,文末有联xi可分享随着医疗行业的不断发展,医院床位管理系统的开发成为了提升医疗服务效率的关键环节。传统的人工管理方式不仅效率低下,还......
  • 基于java+Uniapp的博客平台微信小程序设计与实现
    ......
  • Java复习第四天
    一、代码题1.相同的树(1)题目给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。示例1:输入:p=[1,2,3],q=[1,2,3]输出:true示例2:输入:p=[1,2],q=[1,null,2]输出:false示例3:输入:p=......
  • Java 大视界 -- Java 大数据中的强化学习算法实践与优化 (57)
           ......
  • java基础Day5 java流程控制(1)
    一、用户交互ScannerScanner对象Demo01Demo02Demo03使用next()方式接收packagescanner;importjava.util.Scanner;publicclassDemo01{publicstaticvoidmain(String[]args){//创建一个扫描器对象,用于接收键盘数据Scannersc=new......
  • 「2024·我的成长之路」:年终反思与展望
    文章目录1.前言2.创作历程2.1摆烂期2.2转变期3.上升期2.个人收获3.经验分享4.展望未来1.前言2025年1月16日,2024年博客之星入围公布,很荣幸获得了这次入围的机会。2024年对我个人是里程碑的一年,是意义非凡的一年,是充满变化的一年。2.创作历程2.1摆烂期我加......
  • 【教学类-13-06】20240119数字色块图的代码优化-简化代码路径+班级位置空缺
    背景需求:第一笔有客户购买“9图的数字像素图”,我都没有在百度网盘里备份。  ​​​​​​​打开代码文件夹,发现生成的PDF很多,不知道是哪一个?找到是这份,可是里面有大1班了,客户不一定是大1班。所以word模版的班级要空着,就需要修改模版删除中3的文字,按四个空格(2个汉......
  • JAVA概述
    一.Java的历史​Java诞生于1995年,创始人为大胡子gosling,后来给甲骨文公司收购。二.Java概述2.1Java的重要特点Java是面向对象的(oop)Java是健壮的,有强类型机制、异常处理、垃圾的自动收集等Java是跨平台的,生成的class文件可以在各个系统平台运行(基于Java虚拟机JVM)Java是......
  • THUWC2024
    Day0早上吃过早饭就走了,在火车站与检票员友好协商后去了wang54321的位置。路上无事可做,只能颓。建了一个微信群叫没丢行李小分队,了解5k的光辉事迹。12点左右到北京,吃过饭去人大附中报道。从东门进的(不是正门),没有任何指示牌,差评,六个人无脑漫游了一会找不到报道地点。后来询......