# sakura-springboot-plugin **Repository Path**: Cutie_Sakura/sakura-springboot-plugin ## Basic Information - **Project Name**: sakura-springboot-plugin - **Description**: 自定义的gradle插件,可将SpringBoot 项目扩展支持插件化开发. - **Primary Language**: Java - **License**: LGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 12 - **Forks**: 2 - **Created**: 2021-07-13 - **Last Updated**: 2024-09-30 ## Categories & Tags **Categories**: spring-boot-ext **Tags**: SpringBoot, gradle插件, 插件化开发 ## README # 工程简介 将speingboot项目扩展改造成支持插件化开发的Gradle插件项目. 可使项目运行时,动态加载指定目录下的jar包到依赖内, 实现插件化开发效果. 有点类似lib依赖外置的感觉, 启动后自动加载指定目录内的jar包为依赖. 有的同学可能尝试过,将某些插件jar直接通过压缩工具放入xxx.jar类的lib内,启动后放入的jar不会被加载, 或者外置lib的项目,将插件jar放入外置的lib文件内,启动后放入的jar也不会被加载. 通过本插件工具,即可实现,在不改动原始xxx.jar 的情况下,启动xxx.jar时,自动加载加指定目录的插件.

--- 更多配置参数,详见控制台 ## 特点功能 * 与原生ide内多模块开发依赖一致,无差异,效果相同, * 方便快捷,一次添加,终身受益 * 插件配置式插拔于springboot项目。 * 在springboot上可以进行插件式开发, 扩展性极强, 可以针对不同项目开发不同插件, 进行不同插件jar包的部署。 * 在插件应用模块上可以使用Spring注解定义组件, 进行依赖注入。 * 支持在插件中开发Rest接口。 * 支持在插件中单独定义持久层访问等需求。 * 可以遵循主程序提供的插件接口开发任意扩展功能。 * 支持注解进行任意业务场景扩展, 并使用定义的坐标进行场景命中。 * 支持自定义扩展开发接口, 使用者可以在预留接口上扩展额外功能。 * 支持插件之间的通信。 * 支持插件接口文档: Swagger、SpringDoc。 * 插件支持拦截器的定制开发。 ### 可配参数 |名称|默认值|说明|自定义参数| |:---:|:---:|:---:|:---:| custom|false|是否开启自定义模式|× springBootLoaderJarPath|null|SpringBoot启动器jar包路径|开启自定义后必填项 compileDir|project.getBuildDir();|编译路径|× cacheDir|new File(compileDir, "libs")|缓存路径|× cacheName|"sakuraCache"|缓存目录|× buildDir|new File(compileDir, "libs")|构建目录|× buildJarName|project.getName() + "-" + project.getVersion()|构建jar名称|× myLauncherName|"MyLauncher"|启动器类名|√ myLauncherPackageName|"com.sakura.hk.plugin"|启动器包名|√ pluginPathProperty|"sakura.plugin.path"|从JVM获取插件所在径路的属性名|√ pluginPathProperty|"sakura.plugin.name"|从JVM获取插件所在文件夹名称的属性名|√ pluginPathName|"myPlugin"|默认插件所在文件夹名称|√ suffix|"sakura"|生成jar包的后缀|× delCache|true|是否删除缓存文件|× type|SakuraBootType.JAR|打包类型|× ### 参数详细说明 > 自定义模式参数即为必须开启自定义模式配置才生效的参数 > * × 更改后无需开启自定义模式即可生效 > * √ 更改后需要开启自定义模式才剩下 * **custom** 指示是否开启自定义模式 - true 开启 - false 关闭(默认值) * **springBootLoaderJarPath** SpringBoot启动器jar包路径 开启自定义模式后必填,涉及到java代码的动态编译,需要依赖, 及当前Springboot项目所使用的spring-boot-loader包的硬盘路径,如没有可前往mavne下载 ,或在项目中依赖`compileOnly 'org.springframework.boot:spring-boot-loader'` 后刷新项目,gradle会自动下载依赖 ,随后前往`.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-loader\`目录下查找与项目使用Springboot版本相同的jar包路径 默认值: null * **compileDir** 编译路径 项目编译路径,在gradle项目中,默认为根目录下build目录,一般情况下不需更改. 默认值为:project.getBuildDir() 插件默认自动获取当前项目Build目录 * **cacheDir** 缓存路径 插件工作时缓存文件存放路径, 默认值: new File(compileDir, "libs") 即为编译路径下的libs目录, * **cacheName** 缓存目录 插件工作时,所有缓存文件均存放于缓存路径下的 缓存目录文件下 默认值: "sakuraCache" `缓存路径`下的`sakuraCache`目录 * **buildDir** 构建路径 可理解为Springboot插件执行bootJar任务后生成jar包的路径, 默认值: new File(compileDir, "libs") 即为编译路径下的libs目录, * **buildJarName** 构建jar的名称 可理解为Springboot插件执行bootJar任务后生成jar包的名称, 默认值 : project.getName() + "-" + project.getVersion() 即为当前 项目名称-项目版本, 如在bootJar 配置中更改jar名称或添加jar后缀,许手动更改此项 * **myLauncherName** 启动器类名 插件生成的启动类的类名 默认值: "MyLauncher" * **myLauncherPackageName** 启动器类包名(包路径) 插件生成的启动类的包名 默认值: "com.sakura.hk.plugin" * **pluginPathProperty** 从JVM获取插件所在径路的属性名 插件所在的路径,即为启动jar的时候 添加`-Dsakura.plugin.path` 定义插件所在的路径, 如 `System.getProperty("sakura.plugin.path")` 获取为null的时候, 使用`System.getProperty("user.dir")`获取当前启动路径 默认值 : "sakura.plugin.path" * **pluginPathProperty** 从JVM获取插件所在文件夹名称的属性名 插件所在的路径下具体的文件夹名,即为启动jar的时候 添加`-Dsakura.plugin.name` 定义插件所在的文件夹, 如 `System.getProperty("sakura.plugin.name")` 获取为null的时候, 将使用 **pluginPathName** 参数 作为插件所在文件名 默认值 : "sakura.plugin.name" * **pluginPathName** 默认插件所在文件夹名称 不开启自定义模式更改无效,可在启动jar的时候 添加`-Dsakura.plugin.name` 指定插件所在文件夹, 当`System.getProperty("sakura.plugin.name")` 获取为null的时候 使用默认值 默认值: "myPlugin" * **suffix** 生成jar包的后缀 插件任务生成的jar包后缀,用来和Springboot生成的jar包区分 默认值: "sakura" * **delCache** 是否删除缓存文件 运行插件任务后,是否删除插件工作时候产生的缓存文件 - true 开启(默认值) - false 关闭 * **type** 打包类型 选择是jar包还是War包 - tSakuraBootType.JAR (默认值) - faSakuraBootType.WAR (可能存在bug,推荐使用JAR) ### 任务详细说明 * **akuraInit** 初始化准备任务 打印显示了当前插件工作的各种参数 * **decompressionSpringbootBuild** 解压springboot生成的jar包 解压缩Springboot构建,输出到缓存目录 * **generateMyMainClassFile** 生成启动类 生成启动主类编译文件,并存在与指定位置 * **setSpringbootStartupMainClass** 更改springboot指定的启动类 将springboot指定的启动类更改为 `generateMyMainClassFile` 任务生成的启动类 * **generateNewBuildJar** 生成新的jar包 生成被sakrua插件定制化后的jar包 * **clearCache** 是否删除缓存文件 将sakrua插件工作时产生的缓存文件清理 * **sakuraPlugInBuild** 调用sakura插件编译项目 插件工作的入口,类似bootJar任务,以前打包执行`bootJar`,现在打包执行`sakuraPlugInBuild` ## 示例 示例位于根目录**Examples**内 ### 定义 * **api** 接口模块,定义了一些接口 * **main-progeam** 主程序,集成api模块,需要调用实现类 * **plus-in** api接口的实现 ### 实现 **api** 模块定义 `ISample`接口,代码如下 ```java package com.sakura.hk.examples; /** * 一个样品示例 * * @Author: sakura * @Date: 2021/7/19 */ public interface ISample { public void getName(); public void getId(); } ``` **plus-in** 模块实现 api接口,并使用Spring的相关方式进行bean注册 * 使用@Bean 注册ASample 代码去下所示 ``` java package com.sakura.hk.examples; /** * @Author: Sakura * @Date: 2021/7/19 */ public class ASample implements ISample { private String id = "A:001"; private String name =" 我是@Bean注册的,我当小弟吧"; @Override public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "ASample{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } } //******************************************************************************* package com.sakura.hk.examples; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author: Sakura * @Date: 2021/7/19 */ @Configuration public class Config { @Bean public ISample aSample() { return new ASample(); } } ``` * 使用@Component 注册BSample 代码去下所示 ```java package com.sakura.hk.examples; import org.springframework.stereotype.Component; /** * @Author: Sakura * @Date: 2021/7/19 */ @Component public class BSample implements ISample { private String id = "B:001"; private String name ="我是@Component注册的,我想当老大"; @Override public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "ASample{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } } ``` * **main-progeam** 主程序,集成api模块,需要调用实现类 其中`build.gradle` 配置了本示例的插件 实现CSample,作为示例,通过**Exhibition** 展示获取的Bean ,示例实现代码如下 ```java package com.sakura.hk.examples.main.progeam; import com.sakura.hk.examples.ISample; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.List; /** * @Author: Sakura * @Date: 2021/7/19 */ @Component public class Exhibition { @Autowired private List sampleList; @PostConstruct public void start() { System.out.println(sampleList); } } ``` ### 运行效果 ``` PS C:\sakura\sakura-springboot-plugin\Examples\main-progeam\build\libs> java -jar .\main-progeam-0.0.1-SNAPSHOT-sakura.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.3.7.RELEASE) 2021-07-19 23:11:51.800 INFO 8504 --- [ main] c.s.h.e.m.p.MainProgeamApplication : Starting MainProgeamApplication on DESKTOP-RDKKTNL with PID 8504 (C:\sakura\sakura-springboot-plugin\Examples\main-progeam\build\libs\main-progeam-0.0.1-SNAPSHOT-sakura.jar started by Sakura in C:\sakura\sakura-springboot-plugin\Examples\main-progeam\build\libs) 2021-07-19 23:11:51.803 INFO 8504 --- [ main] c.s.h.e.m.p.MainProgeamApplication : No active profile set, falling back to default profiles: default [ASample{id='C:001', name='我是主程序提供的,我是老大'}, ASample{id='B:001', name='我是@Component注册的,我想当老大'}, ASample{id='A:001', name='我是@Bean注册的,我当小弟吧'}] 2021-07-19 23:11:52.479 INFO 8504 --- [ main] c.s.h.e.m.p.MainProgeamApplication : Started MainProgeamApplication in 1.249 seconds (JVM running for 3.487) PS C:\sakura\sakura-springboot-plugin\Examples\main-progeam\build\libs> ``` # 常见问题 ## 版本号说明 * 首位,大版本,通常指功能或框架大变动 * 中间,小版本,通常指功能更新 * 末尾,修复版本,通常为bug修订 ## 快速上手 拉取项目编译或下载编译好的jar, 改动 **build.gradle** 文件内容, 以申请提交gradle官方仓库,等待审批中 * 引入依赖 ```groovy buildscript { repositories { // 本地仓库或指定目录 mavenLocal() } dependencies { // 添加依赖 // 指定加载某路径下jar为依赖示例 // compile fileTree(dir:'../lib',includes:['*jar']) // classpath fileTree(dir:'lib/sakura-springboot-plugin-0.1.1.jar') classpath 'com.sakura.hk:sakura-springboot-plugin:Latest Version' } } // 引入插件 apply plugin: 'sakrua.springboot.plugin' ``` * 启动gradle Tasks任务列表下 **sakuraSptingBoot** 分组内的 **sakuraPlugInBuild** 任务,即可完成打包. * 打包完成后,默认识别运行目录下 myPlugin 文件下的jar为插件 # 贡献者们 主项目的贡献者们和 生态周边项目 的作者们: sakrua 感谢大家的贡献。 # 规划功能 * ~~不开启自定义模式下,动态识别指定插件目录~~ * 识别多目录 * 定制插件过滤规则 * 编写高大上的说明文档 ==>> 40% * 准备一个LOGO * ~~编辑示例~~ * 编辑插件原理说明 * 加个license检查,防止通过注入插件破坏原项目内的license检测机制 # 插件原理讲解 // TODO 下次更新 ## 我要赞赏 如果你喜欢帮助到了你,可以点右上角 ⭐Star 支持一下,谢谢 ^_^



# 技术交流 如果有什么问题或建议可以 ISSUE交流技术,分享经验。 QQ群: 15392541