Spring Boot Batch如何访问需身份认证的远程HTTP资源列表
问题根因
PathMatchingResourcePatternResolver的通配符匹配逻辑仅支持本地文件系统、classpath等可直接遍历的资源类型,HTTP协议本身没有内置的目录遍历能力,所以你传入带*.xml通配符的HTTP路径时,框架会尝试将HTTP URL解析为本地文件路径进行匹配,自然就抛出了无法解析为本地文件的报错。同时默认的UrlResource也不支持自动携带Basic认证信息访问受保护的HTTP资源。
解决方案
核心思路是主动枚举远程目录下的所有XML文件路径,再为每个路径构造带认证信息的Resource,最后传入MultiResourceItemReader即可,实现步骤如下:
步骤1:获取远程XML文件列表
你需要先拿到/infiles目录下所有XML文件的文件名,有两种常见实现方式:
- 如果远程服务器开放了目录浏览权限,可以解析目录页的HTML提取所有
.xml后缀的链接 - 如果是内部服务器,建议直接提供一个返回该目录下所有XML文件名的接口,稳定性更高
这里以解析目录页为例,需要用到Jsoup库解析HTML,先引入依赖:
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.17.2</version> </dependency>
步骤2:实现带认证的文件读取逻辑
替换你原有的multiItemReader实现即可:
@Bean @StepScope public MultiResourceItemReader<Situation> multiItemReader() { String remoteBaseUrl = "http://10.**.**.**/infiles/"; String username = "your_username"; String password = "your_password"; // 1. 获取远程所有XML文件名 List<String> xmlFileNames = getRemoteXmlFileNames(remoteBaseUrl, username, password); // 2. 构造带Basic认证的Resource数组 Resource[] resources = xmlFileNames.stream() .map(fileName -> { try { return new UrlResource(remoteBaseUrl + fileName) { @Override protected URLConnection openConnection(URL url) throws IOException { URLConnection connection = super.openConnection(url); if (connection instanceof HttpURLConnection httpCon) { // 手动注入Basic认证头 String authStr = username + ":" + password; String encodedAuth = Base64.getEncoder().encodeToString(authStr.getBytes(StandardCharsets.UTF_8)); httpCon.setRequestProperty("Authorization", "Basic " + encodedAuth); } return connection; } }; } catch (MalformedURLException e) { logger.error("构造远程资源URL失败:{}", fileName, e); return null; } }) .filter(Objects::nonNull) .toArray(Resource[]::new); // 3. 构造MultiResourceItemReader return new MultiResourceItemReaderBuilder<Situation>() .name("multiItemReader") .delegate(reader()) .resources(resources) .setStrict(false) .build(); } // 提取远程目录下的XML文件名 private List<String> getRemoteXmlFileNames(String baseUrl, String username, String password) { List<String> xmlFileNames = new ArrayList<>(); try { String authStr = username + ":" + password; String encodedAuth = Base64.getEncoder().encodeToString(authStr.getBytes(StandardCharsets.UTF_8)); // 请求远程目录页,解析HTML提取XML链接 Document doc = Jsoup.connect(baseUrl) .header("Authorization", "Basic " + encodedAuth) .get(); Elements linkElements = doc.select("a[href$=.xml]"); for (Element link : linkElements) { xmlFileNames.add(link.attr("href")); } } catch (IOException e) { logger.error("获取远程XML文件列表失败", e); } return xmlFileNames; }
内容的提问来源于stack exchange,提问作者langar
相关产品推荐
相关产品推荐

