Spring Boot如何通过Get接口获取指定包内的所有shell脚本
问题根因梳理
- 不存在专门用于定位类路径下shell脚本的、与
java.class.path等价的独立系统属性。你存放的shell脚本本身就是类路径下的静态资源,和Java类共享同一套类路径加载规则,之前的代码失效不是路径属性不对,是核心逻辑完全错位:- 原代码沿用了扫描Java类的逻辑,扫描到
.sh文件后还尝试调用Class.forName()把shell脚本转为Java类对象,这在运行时根本不可能成功 - 原代码判断classpath条目是否以
.sh结尾的逻辑完全颠倒:类路径的组成项只会是磁盘目录、Jar/War包文件,不会把单个shell脚本直接作为类路径条目 - 手动硬编码解析
java.class.path的方式兼容性极差,在Spring Boot可执行Jar的嵌套Jar加载、自定义类加载器场景下经常出现扫描漏判的问题
- 原代码沿用了扫描Java类的逻辑,扫描到
可落地的调整方案
直接替换为Spring内置的类路径资源扫描机制即可,这套机制天然兼容本地IDE运行、打普通Jar、打Spring Boot可执行Jar的所有部署场景,不需要手动处理路径拆分、Jar解包的复杂逻辑:
- 把接口返回值从
List<Class<?>>调整为List<String>,存储扫描到的shell脚本名称即可,不需要也不能对shell脚本做类加载操作 - 用Spring提供的
PathMatchingResourcePatternResolver替代手动解析类路径的逻辑,自动匹配指定包下的所有.sh后缀文件 - 参考修正后的代码实现:
import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("api/overview") public class DME { // 替换为你实际存放shell脚本的类路径下的包路径,注意路径分隔符用/代替. private static final String SCRIPT_SCAN_PATH = "de/osp/scriptrunnerbackend/script/"; @GetMapping public List<String> listAvailableShellScripts() { List<String> scriptNameList = new ArrayList<>(); try { PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); // 扫描指定路径下所有后缀为.sh的类路径资源 Resource[] scriptResources = resourceResolver.getResources("classpath*:" + SCRIPT_SCAN_PATH + "*.sh"); for (Resource scriptResource : scriptResources) { // 提取脚本文件名,可根据需求调整返回的路径格式 String resourcePath = scriptResource.getURI().toString(); String scriptFileName = resourcePath.substring(resourcePath.lastIndexOf('/') + 1); scriptNameList.add(scriptFileName); } } catch (Exception e) { // 实际项目中可在此处补充错误日志打印逻辑,不要静默吞掉异常 } return scriptNameList; } }
落地注意事项
- 如果是Maven构建的项目,需要确认shell脚本所在的目录是被纳入资源打包范围的:默认配置下
src/main/java路径下的非Java文件不会被自动打包进Jar包,容易出现本地IDE能扫描到脚本、打Jar部署后就找不到的问题,需要在pom的资源配置节点显式放行.sh后缀的文件 - 原代码中所有针对Jar包解包、类路径拆分、类加载的逻辑都可以完全删掉,避免冗余代码带来的异常风险
内容的提问来源于stack exchange,提问作者Volnick
相关产品推荐
相关产品推荐

