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

文章目录

  • 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.总结
  • 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


    2.相关链接

  • CSDN:Sunrays-Framework 开发笔记
  • GitCode:Sunrays-Framework 开源地址
  • 官方文档:Sunrays-Framework 官方文档 必读部分提供了七万字的完整语雀开发文档
  • CleanShot 2025-01-20 at 11.42.31@2x

    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

    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. 程序启动时,动态获取并打印以下信息:
    3. 日志存储的根目录的绝对路径
    4. 应用的访问地址(包括端口)
    5. 前端请求时可用的日期格式
    6. ApplicationEnvironmentPreparedListener
    7. 获取日志根目录及模块名,并将其设置为环境变量供 log4j2-spring.xml 使用。
    8. TraceIdLoggingAspect
    9. 每次请求开始时打印一行日志,包含请求的 traceId,以便于日志追踪。
    10. LogAspect
    11. 日志切面(AOP),匹配所有 controllerservice 包中的方法,记录以下信息:
    12. 方法的执行时间
    13. 请求参数
    14. 返回结果
    15. 使用自定义的 banner.txt
    16. 读取项目的版本号,并在启动时展示自定义的 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会更加完善和强大,帮助更多的开发者走得更远,做得更好。

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

    作者:S-X-S

    物联沃分享整理
    物联沃-IOTWORD物联网 » 「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程

    发表回复