Spring Boot+Gradle+Kotlin多模块中,模块B如何获取模块A静态文件列表?
解决方案
问题根源
ResourcePatternResolver的getResources()方法仅支持对类路径、文件系统等本地资源的通配符(如/**)解析,对于http:协议的远程资源,它无法识别通配符规则,因此返回空列表。
方案一:模块A提供文件列表接口(推荐)
让模块A暴露一个接口,直接返回test-data/static/files目录下的所有文件名,模块B通过调用该接口获取列表后,再按需读取单个文件。
模块A实现
- 添加Controller类,利用Spring的资源解析能力遍历本地目录:
@RestController @RequestMapping("/api/files") class FileListController(private val resourcePatternResolver: ResourcePatternResolver) { @GetMapping("/list") fun getFileList(): List<String> { // 匹配本地files目录下的所有txt文件 val resources = resourcePatternResolver.getResources("classpath:/test-data/static/files/*.txt") return resources.map { it.filename ?: "" } } }
- 确保模块A的application.properties配置不变:
spring.web.resources.static-locations=classpath:/test-data/static
模块B实现
修改ResourcesProviderService,通过HTTP请求调用模块A的接口获取文件列表:
@Service class ResourcesProviderService( private val resourceLoader: ResourceLoader, private val restTemplate: RestTemplate ) { fun getResource(filename: String): Resource = resourceLoader.getResource("http://localhost:8181/files/$filename") fun getAllFilenames(): List<String> { return restTemplate.getForObject("http://localhost:8181/api/files/list", List::class.java) as List<String> } }
方案二:开启模块A的静态目录浏览(仅测试/非生产环境)
如果无法修改模块A的代码,可以开启Spring Boot的静态目录浏览功能,模块B通过HTTP请求获取目录内容后解析文件名。
模块A配置
在application.properties中添加配置,并编写WebConfig开启目录浏览:
spring.web.resources.static-locations=classpath:/test-data/static spring.mvc.static-path-pattern=/files/**
@Configuration class WebConfig : WebMvcConfigurer { override fun addResourceHandlers(registry: ResourceHandlerRegistry) { registry.addResourceHandler("/files/**") .addResourceLocations("classpath:/test-data/static/files/") .setCachePeriod(0) .resourceChain(true) .addResolver(ResourceResolver { request, path, locations, chain -> val targetResource = chain.resolveResource(request, path, locations) // 若请求的是目录,返回文件列表JSON if (targetResource == null) { val dir = locations.first().createRelative(path) if (dir.exists() && dir.isDirectory) { val fileNames = dir.listFiles()?.map { it.name } ?: emptyList() ByteArrayResource(ObjectMapper().writeValueAsBytes(fileNames)).apply { filename = "file-list.json" } } else { null } } else { targetResource } }) } }
模块B实现
调用模块A的目录URL解析文件列表:
@Service class ResourcesProviderService( private val resourceLoader: ResourceLoader, private val restTemplate: RestTemplate ) { fun getResource(filename: String): Resource = resourceLoader.getResource("http://localhost:8181/files/$filename") fun getAllFilenames(): List<String> { return restTemplate.getForObject("http://localhost:8181/files/", List::class.java) as List<String> } }
注意事项
- 方案一为生产环境首选,可控性强、安全性高;
- 方案二仅适合测试场景,生产环境开启目录浏览存在信息泄露风险;
- 模块B需确保与模块A网络互通,避免防火墙或跨域限制。
内容的提问来源于stack exchange,提问作者asfarasiknow
相关产品推荐
相关产品推荐

