简简单单探讨下starter

article/2025/6/7 12:39:52

前言

     今天其实首先想跟大家探讨下:微服务架构,分业务线了,接入第三方服务、包啥的是否自己定义一个stater更好?


一、starter是什么?

在 Spring Boot 中,Starter 是一种特殊的依赖模块,用于快速引入一整套相关的依赖和默认配置,以简化开发者的配置工作。

1.starter的核心作用

Starter 的本质是一个 Maven 或 Gradle 的依赖包,它:

  • 封装了某种功能所需的所有依赖库;

  • 提供了该功能的默认自动配置;

  • 遵循 Spring Boot 的自动化配置规范(@Conditional 机制);

  • 允许用户覆盖默认配置。

2.Starter 的内部结构(自定义时)

一个典型的自定义 Starter 包含两个模块:

  • starter 模块:用于提供自动配置类(通常使用 @Configuration + @Conditional),并注入 Bean。

  • starter-autoconfigure 模块:用于定义配置逻辑和默认行为。

也有时候直接打包成一个模块就行。

二、Starter自定义步骤

首先了解下starter的目录结构:
在这里插入图片描述

1.目前idea的New没看到有直接选择Starter这种(有说new project,maven勾选Create from archetype,试了下跟新建module差不多),但是问题不大,可以直接New Module,具体:

  • 1.新建Module,设置好name、group、artifact等等,注意name最好是项目名称开头-spring-boot-starter-模块功能。比如我这里是接入虹软的人脸识别,所以名称:项目名称-spring-boot-starter-arcface
  • 修改pom
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><-- 这个父级依赖,如果没有需要的在父级其实可以不要 --><parent><groupId>com.bsr.healthcheck</groupId><artifactId>bsr-framework</artifactId><version>${revision}</version></parent><modelVersion>4.0.0</modelVersion><artifactId>bsr-spring-boot-starter-arcface</artifactId><packaging>jar</packaging><name>${project.artifactId}</name><description>虹软人脸扩展</description><url/><dependencies><!-- 自定义的通用包 --><dependency><groupId>com.bsr.healthcheck</groupId><artifactId>bsr-common</artifactId></dependency><!-- Spring 核心 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><optional>true</optional></dependency><!-- 虹软人脸识别 --><dependency><groupId>com.arcsoft.face</groupId><artifactId>arcsoft-sdk-face</artifactId><version>3.0.0.0</version><scope>system</scope><systemPath>${project.basedir}/libs/arcsoft-sdk-face-3.0.0.0.jar</systemPath></dependency></dependencies></project>
  • 因为虹软的jar,目前在maven源上没有公开,都是申请的时候下载的,这里在目录下建一个libs,放jar、dll(这个后期应该是放到服务器上)

  • 删除启动App、resources下的配置文件

  • resources下新建META_INF目录,目录下新建spring.factories,内容:org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    com.bsr.healthcheck.framework.face.config.ArcFaceAutoConfiguration
    注意ArcFaceAutoConfiguration配置类目录要跟计划写的类对得上哦,最好是检查写好了,这里能点过去就ok的

  • src下建目录,写配置类、properties等
    我的starter的目录:
    在这里插入图片描述

2.具体代码

ArcFaceAutoConfiguration

/*** 虹软人脸识别** @author zwmac*/
@Slf4j
@Configuration
@EnableConfigurationProperties(ArcFaceProperties.class)
@ConditionalOnProperty(prefix = "arcface", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ArcFaceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic FaceEngineWrapper faceEngineWrapper(ArcFaceProperties properties) {if (SystemUtil.getOsInfo().isWindows()){return new FaceEngineWrapper(properties.getWinAppId(),properties.getWinSdkKey(),properties.getWinLibPath());}if(SystemUtil.getOsInfo().isLinux()){return new FaceEngineWrapper(properties.getAppId(),properties.getSdkKey(),properties.getLibPath());}if(SystemUtil.getOsInfo().isMac()){log.info("虹软人脸识别不支持 Mac OS X");//throw new IllegalStateException("Unsupported OS for ArcFace engine");}log.warn("系统未知,虹软人脸识别引擎初始化失败");return null;}@Lazy@Bean@ConditionalOnMissingBeanpublic ArcFaceService arcFaceService() {return new ArcFaceServiceImpl();}}

FaceEngineConfig

/*** @author zwmac*/
@Configuration
public class FaceEngineConfig {@Value("${arcface.app-id}")private String appId;@Value("${arcface.sdk-key}")private String sdkKey;@Value("${arcface.lib-path}")private String libPath;@Beanpublic FaceEngineWrapper faceEngineWrapper() {return new FaceEngineWrapper(appId, sdkKey, libPath);}
}

FaceEngineWrapper


/*** @author zwmac*/
@Lazy
@Slf4j
public class FaceEngineWrapper {private FaceEngine faceEngine;/*** 初始化人脸引擎* @param appId 授权id* @param sdkKey 授权key* @param libPath 脚本路径*/public FaceEngineWrapper(String appId, String sdkKey, String libPath) {try {faceEngine = new FaceEngine(libPath);//激活引擎int errorCode = faceEngine.activeOnline(appId, sdkKey);if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {log.error("引擎激活失败");}ActiveFileInfo activeFileInfo = new ActiveFileInfo();errorCode = faceEngine.getActiveFileInfo(activeFileInfo);if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {log.error("获取激活文件信息失败");}//引擎配置EngineConfiguration engineConfiguration = new EngineConfiguration();engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);engineConfiguration.setDetectFaceMaxNum(10);engineConfiguration.setDetectFaceScaleVal(16);//功能配置FunctionConfiguration functionConfiguration = new FunctionConfiguration();functionConfiguration.setSupportAge(true);functionConfiguration.setSupportFace3dAngle(true);functionConfiguration.setSupportFaceDetect(true);functionConfiguration.setSupportFaceRecognition(true);functionConfiguration.setSupportGender(true);functionConfiguration.setSupportLiveness(true);functionConfiguration.setSupportIRLiveness(true);engineConfiguration.setFunctionConfiguration(functionConfiguration);//初始化引擎errorCode = faceEngine.init(engineConfiguration);if (errorCode != ErrorInfo.MOK.getValue()) {log.error("初始化引擎失败");}} catch (RuntimeException e) {log.error("人脸引擎FaceEngine加载脚本异常,{}", e.getMessage(), e);}}public FaceEngine getEngine() {return this.faceEngine;}
/*public void destroy() {faceEngine.unInit();}*/@PreDestroypublic void destroy() {if (faceEngine != null) {faceEngine.unInit();log.info("人脸识别引擎已释放");}}
}

ArcFaceProperties


/*** @author zwmac*/
@ConfigurationProperties(prefix = "arcface")
@Data
public class ArcFaceProperties {private String appId;private String sdkKey;private String libPath;private String winAppId;private String winSdkKey;private String winLibPath;private float matchThreshold = 0.8f;private float rgbThreshold;private float irThreshold;
}

ArcFaceService

/*** @author zwmac*/
public interface ArcFaceService {/*** 校验是否活体* @param imgFile 照片文件File* @return 是否活体*/boolean checkLive(File imgFile);
}

ArcFaceServiceImpl


/*** @author zwmac*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ArcFaceServiceImpl implements ArcFaceService {@Resourceprivate FaceEngineWrapper engineWrapper;@Overridepublic boolean checkLive(File imgFile) {boolean liveOk = false;Assert.notNull(imgFile, "照片文件为空");ImageInfo imageInfo = getRGBData(imgFile);FaceEngine faceEngine = engineWrapper.getEngine();//人脸检测List<FaceInfo> faceInfoList = new ArrayList<>();int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "人脸检测失败");//特征提取FaceFeature faceFeature = new FaceFeature();errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "人脸特征提取失败");//开启活体检测errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "设置活体测试失败");List<LivenessInfo> livenessInfoList = new ArrayList<>();errorCode = faceEngine.getLiveness(livenessInfoList);Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "活体检测失败");int liveness = livenessInfoList.get(0).getLiveness();log.info("活体liveness:{}", liveness);liveOk = liveness == 1;//释放引擎engineWrapper.destroy();return liveOk;}
}

总结

  • 这里的ArcFaceService在业务模块是可以懒加载的,好处就不解释了
  • 目前starter里service就写了一个接口,需要的可以自己扩展
  • 其实以前我也不赞成微服务还搞好多starter,但是最近想法有点改变。
    – 首先是业务线细分后,可能多个服务都需要接入某项技术,用starter可以细粒度管理模块。
    – 其次,让业务更加专注业务,第三方仅仅是第三方服务
    – 最后,其实就是可以复用,但是不得不说开发工作量增加了
  • 总结一句话:Spring Boot Starter 就是为了“开箱即用”而准备的功能集装箱。
    – 通过引入一个 starter,就可以获得一整套某个功能的支持,开发者只需关注业务逻辑,而无需自己配置和管理底层依赖。
         最后,希望能帮到大家,未来之所以迷人,是因为是机遇也是挑战,加油!

http://www.hkcw.cn/article/krnCWNokjK.shtml

相关文章

字符编码全解析:ASCII、GBK、Unicode、UTF-8与ANSI

UTF - 8(全球字符能被唯一标识)、GBK、Unicode、ANSI 区别与关联 qwen模型分词器文件 1. ASCII(基础铺垫,理解编码起源) 作用:最早期为处理英文文本设计,是字符编码的基础,后演变成其他编码兼容的一部分 。范围:共 128 个字符(0 - 127),包含英文大小写字母、数字…

定时线程池失效问题引发的思考

最近在做的一个新功能&#xff0c;在结果探测的时候使用了定时线程池和普通线程池结合&#xff0c;定时线程池周期性创建子任务并往普通线程池提交任务。 问题&#xff1a; 在昨天测试老师发现&#xff0c;业务实际上已经成功了&#xff0c;但是页面还是一直显示进行中。 收到…

Win11/Win10 打不开 gpedit.msc 之 组策略编辑器安装

目前已整理两种方式&#xff0c;推荐使用第二种方式~ 方式1&#xff1a; 一般家庭版操作系统默认未安装 组策略编辑器&#xff0c; 只需要进行安装一下即可。 到文章结尾按照提示下载相关的bat文件&#xff0c; 下载后右键以管理员身份运行bat文件&#xff0c;&#xff08…

无人机甲烷检测技术革新:开启环境与能源安全监测新时代

市场需求激增&#xff0c;技术革新势在必行 随着全球气候变化加剧&#xff0c;甲烷作为第二大温室气体&#xff0c;其减排与监测成为国际社会关注焦点。据欧盟甲烷法规要求&#xff0c;2024 年起欧洲能源基础设施运营商需定期测量甲烷排放并消除泄漏。与此同时&#xff0c;极端…

谷歌地图手机版(Google maps)v11.152.0100安卓版 - 前端工具导航

谷歌地图(Google maps)是由谷歌官方推出的一款手机地图应用。软件功能强大&#xff0c;支持本地搜索查找世界各地的地址、地点和商家&#xff1b;支持在街景视图中查看世界各地的360度全景图&#xff1b;支持查找乘坐火车、公交车和地铁的路线&#xff0c;或者查找步行路线等 …

H5动态文字效果开发经验分享

这里写目录标题 一、效果介绍二、实现原理与代码解析1. 打字机效果实现2. 渐变文字动画实现 三、开发经验与技巧1. 性能优化2. 兼容性处理3. 用户体验提升 四、应用场景五、扩展思路 一、效果介绍 我们实现了两种常见且实用的文字动效&#xff1a; 打字机效果 &#xff1a;文…

春雪食品×MTC AI助手:创新驱动再升级,效率革命正当时!

当农牧食品企业遇上AI“助手”&#xff0c;会碰撞出怎样的火花&#xff1f;5月26日&#xff0c;春雪食品集团总部迎来了一场特别的签约仪式——携手MTC麦汇信息&#xff0c;共同探索AI数字化之路。春雪食品总裁郑钧、副总裁黄仕敏&#xff0c;MTC麦汇信息董事长卢富平、副总裁徐…

Abaqus连接器弹片正向力分析:

.学习重点: • 外部幾何匯入。 • 建立解析剛性面。 • 利用Partition與局部撒點來提高網格品質。 • 材料塑性行為(材料非線性)。 • 考慮大變形(幾何非線性)。 • 接觸(邊界非線性)。 • 平移組裝。 • 設定輸出參數。 • 討論Shear Locking & Hourglassing效應。 1) 設…

力扣刷题 -- 225. 用队列实现栈

1. 题目 2. 思路分析 思路&#xff1a;1)往非空队列里插入数据&#xff08;入队列&#xff09;&#xff1b; 2&#xff09;将非空队列的前size-1个元素挪到空队列&#xff1b; 3&#xff09;将非空队列的队尾元素出队列&#xff0c;并返回栈顶元素。 3. 代码实现 typedef …

【设计模式-4.7】行为型——备忘录模式

说明&#xff1a;本文介绍行为型设计模式之一的备忘录模式 定义 备忘录模式&#xff08;Memento Pattern&#xff09;又叫作快照模式&#xff08;Snapshot Pattern&#xff09;或令牌模式&#xff08;Token Pattern&#xff09;指在不破坏封装的前提下&#xff0c;捕获一个对…

ADRV9026 JESD204C测试

ADRV9026在650MHz到6GHz的宽频率范围内工作。 接收器通道支持高达200MHz的带宽&#xff0c; 数据传输速率高达24.33 Gbps&#xff0c; 可跨&#xff08;最多&#xff09; 四个JESD204B/JESD204C通道传输。 发射机信道在与接收机相同的频率范围内工作。 每个发射机信道支持高达4…

压缩格式未知或数据损坏:如何应对压缩包无法打开的情况

压缩包在日常工作和生活中非常常见&#xff0c;用于节省空间并方便文件传输。然而&#xff0c;用户在尝试解压文件时&#xff0c;有时会遇到诸如“压缩格式未知”或“数据已损坏”等错误信息。 这种情况可能导致文件无法打开&#xff0c;影响工作效率甚至造成数据丢失。本文将…

升级:用vue canvas画一个能源监测设备和设备的关系监测图!

用vue canvas画一个能源电表和设备的监测图-CSDN博客 上一篇文章&#xff0c;我是用后端的数据来画出监测图。这次我觉的&#xff0c;用前端来控制数据&#xff0c;更爽。 本期实现功能&#xff1a; 1&#xff0c;得到监测设备和设备的数据&#xff0c;然后进行存库 2&…

《数据挖掘》- 房价数据分析

这里写目录标题 采用的技术1. Python编程语言2. 网络爬虫库技术点对比与区别项目技术栈的协同工作流程 代码解析1. 导入头文件2. 读取原始数据3. 清洗数据4. 数据分割4.1 统计房屋信息的分段数量4.2 将房屋信息拆分为独立列4.3 处理面积字段4.4 删除原始房屋信息列 5. 可视化分…

Axure-元件流程图

Axure-02 线框图元件使用 目标 元件基本介绍 基础元件的使用 表单型元件的使用 菜单与表格元件的使用 案例&#xff1a;个人简历表 元件基本介绍 概述 在Axure RP中&#xff0c;元件是构建原型图的基础模块。 将元件从元件库里拖拽到画布中&#xff0c;即可添加元件到你…

深入解析ReactJS中JSX的底层工作原理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…

《Pytorch深度学习实践》ch5-Logistic回归

------B站《刘二大人》 1.Classification 经典的分类数据集&#xff1a;MNIST&#xff08;0 - 9&#xff09; 导入数据集&#xff1a;&#xff08;路径&#xff0c;训练集/测试集&#xff0c;是否下载&#xff09; import torchvision train_set torchvision.datasets.MINI…

HCIP(BGP综合实验)

一、实验拓扑 AS 划分&#xff1a; AS1&#xff1a;R1&#xff08;环回 L0:172.16.0.1/32&#xff0c;L1:192.168.1.0/24&#xff09;AS2&#xff1a;R2、R3、R4、R5、R6、R7&#xff08;内部运行 OSPF&#xff0c;AS 号为 64512 和 64513 的联盟&#xff09;AS3&#xff1a;R…

AI数字人技术革新进行时:井云数字人如何重塑人机交互未来?

老板们注意了&#xff01;不用反复真人出镜拍摄&#xff0c;AI数字人来帮你做口播&#xff0c;只需3分钟克隆你的形象和声音&#xff0c;输入文案24小时随时都能生成视频&#xff01; 在元宇宙概念持续升温、虚拟与现实加速融合的当下&#xff0c;AI数字人正以惊人的速度从科幻…

使用n8n工作流编排AI Agent处理爬取的网页信息

目录 使用docker本地部署n8n 例子 1.点击触发节点 2.RSS Read节点 3.Limit节点 4.FireCrawl节点 5.AI Agent节点 6.Aggregate节点 7.Markdown节点 8.Send Email节点 使用docker本地部署n8n docker-compose.yml&#xff1a; version: "3.8" services:n8n:…