无外网环境下不校验WSDL加载Apache CXF SOAP Web服务的方案咨询
问题根因
报错是因为CXF加载WSDL关联的XSD时,会自动拉取XSD中引用的在线公共资源(比如w3.org的XML结构定义文件),离线环境无法访问公网域名,导致解析失败。
关于是否可以跳过WSDL校验
- 服务端场景:不建议直接跳过,CXF启动时需要依赖WSDL/XSD结构生成服务端点,强制跳过会导致参数解析、响应格式完全异常,除极简动态代理场景外,绝大多数生产环境不可行。
- 客户端场景:如果是CXF调用第三方SOAP服务的客户端,可以通过配置关闭校验,但该场景是服务端加载自身WSDL报错,关闭校验方案不适用。
可行解决方案(无需逐个修改全量外部引用)
方案1:配置实体解析器映射在线地址到本地资源
该方案无需修改原有WSDL/XSD的引用内容,仅需新增映射规则即可:
- 提前下载所有用到的外部XSD文件,放入项目
src/main/resources/schemas/目录 - 自定义实体解析器实现类,核心代码示例:
public class LocalSchemaEntityResolver implements EntityResolver { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { // 匹配在线地址,返回本地资源流 if (systemId.contains("www.w3.org/2001/XMLSchema.xsd")) { return new InputSource(getClass().getResourceAsStream("/schemas/XMLSchema.xsd")); } // 其他外部地址依次添加匹配规则 return null; } }
- 在cxf-beans.xml中为服务端点绑定该解析器:
<jaxws:endpoint id="yourService" implementor="com.xxx.YourServiceImpl" address="/yourService"> <jaxws:entityResolver> <bean class="com.xxx.LocalSchemaEntityResolver" /> </jaxws:entityResolver> </jaxws:endpoint>
方案2:禁用外部资源加载(适合对校验要求不高的场景)
如果业务无需严格校验外部XSD约束,可以通过配置关闭XML解析器的外部资源拉取行为,无需额外下载文件:
- 在服务启动JVM参数中添加如下配置:
-Djavax.xml.accessExternalSchema=file -Dorg.apache.cxf.disable.sax.resolve.dtd=true -Djavax.xml.stream.isSupportingExternalEntities=false
- 在cxf-beans.xml中添加全局Bus配置:
<bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus"> <property name="properties"> <map> <entry key="org.apache.cxf.schema.validate" value="false"/> </map> </property> </bean>
注意:该方案会丢失外部XSD对应的格式校验能力,非法请求参数可能不会被拦截,需自行评估业务风险。
方案3:本地代理重定向(适合零代码修改的场景)
如果客户离线环境允许修改HOSTS和部署静态资源服务,可以选择该方案,完全不用调整项目代码和配置:
- 在服务器HOSTS文件中将所有用到的外部域名(如www.w3.org)映射到本地静态资源服务器IP
- 将所有需要的XSD文件按照原在线路径的目录结构,部署到本地静态资源服务的对应路径下
内容的提问来源于stack exchange,提问作者George Thomas
相关产品推荐
相关产品推荐

