You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Gradle+Kotlin多模块中,模块B如何获取模块A静态文件列表?

解决方案

问题根源

ResourcePatternResolver的getResources()方法仅支持对类路径、文件系统等本地资源的通配符(如/**)解析,对于http:协议的远程资源,它无法识别通配符规则,因此返回空列表。


方案一:模块A提供文件列表接口(推荐)

让模块A暴露一个接口,直接返回test-data/static/files目录下的所有文件名,模块B通过调用该接口获取列表后,再按需读取单个文件。

模块A实现

  1. 添加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 ?: "" }
    }
}
  1. 确保模块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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:43:23