Wildfly部署Spring Web应用时因vfs外部Schema访问受限导致Schema无法读取的问题
嗨,我之前在Wildfly上部署Spring Web应用时,也踩过这个VFS(虚拟文件系统)导致Schema引用失败的大坑!你遇到的这个org.xml.sax.SAXParseException本质是Wildfly用VFS封装了所有部署内容,普通的XML解析器没法正确识别vfs:/content/...这种特殊路径,所以当schema1.xsd用相对路径找schema2.xsd时,解析器根本找不到对应的文件。
给你几个亲测有效的解决办法:
用Spring的Resource体系直接加载Schema(最推荐)
Spring本身就有一套完善的资源加载机制,能适配Wildfly的VFS。比如你用Jaxb2Marshaller或者其他XML解析Bean时,直接指定ClassPath下的Schema文件,不用依赖相对路径引用:@Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setPackagesToScan("com.your.app.package"); // 直接把所有关联的Schema都通过ClassPathResource加载 marshaller.setSchemas( new ClassPathResource("schemas/schema1.xsd"), new ClassPathResource("schemas/schema2.xsd") ); return marshaller; }这样Spring会帮你处理VFS路径的问题,直接从类路径里捞到对应的Schema文件。
给XML解析器自定义EntityResolver
如果你的Schema是在配置文件里引用的(比如Spring的applicationContext.xml),可以自定义一个EntityResolver,用Spring的ResourcePatternResolver来查找资源:@Component public class SpringResourceEntityResolver implements EntityResolver { @Autowired private ResourcePatternResolver resourceResolver; @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { // 从systemId里提取路径,比如截取最后面的schema文件名 String schemaName = systemId.substring(systemId.lastIndexOf('/') + 1); Resource resource = resourceResolver.getResource("classpath:schemas/" + schemaName); return new InputSource(resource.getInputStream()); } }然后在你的XML解析器里设置这个EntityResolver,让它用Spring的方式找Schema。
调整Wildfly的XML解析权限(不推荐,影响安全)
如果你实在不想改代码,可以在Wildfly的standalone.xml(或domain.xml)里修改EE子系统的配置,允许XML解析器访问外部VFS资源:<subsystem xmlns="urn:jboss:domain:ee:5.0"> <xml-parsers> <parser-settings name="default"> <sax-parser-factory> <!-- 开启加载外部DTD/Schema的权限 --> <feature name="http://apache.org/xml/features/nonvalidating/load-external-dtd" value="true"/> </sax-parser-factory> </parser-settings> </xml-parsers> </subsystem>不过这个办法会降低应用的安全性,不建议在生产环境用。
总的来说,用Spring自带的Resource加载方式是最省心的,既不用改服务器配置,也能完美适配Wildfly的VFS机制,我当时就是用第一个办法解决的,部署一次就成功了!
内容来源于stack exchange

