如何去除Apache CXF 3.3.0生成WSDL的tns命名空间末尾斜杠?
解决Apache CXF 3.3.0生成WSDL时命名空间末尾带斜杠的问题
我之前在用CXF生成WSDL时也碰到过这个自动加斜杠的情况,给你几个实用的解决思路,按推荐程度排序:
1. 手动通过@WebService注解指定命名空间(最推荐)
这是最直接也最符合JAX-WS规范的做法,完全绕开CXF自动生成命名空间的逻辑。在你的服务实现类或者端点接口上,明确设置targetNamespace属性为不带斜杠的地址:
import javax.jws.WebService; @WebService( targetNamespace = "http://impl.service.ti.commun.metier.civitas.fr", serviceName = "YourServiceName", portName = "YourServicePort" ) public class YourServiceImpl implements YourServiceEndpoint { // 你的服务实现代码 }
当你显式指定targetNamespace后,CXF就不会再调用PackageUtils去自动生成带斜杠的命名空间了,生成的WSDL里的tns命名空间就会是你指定的不带斜杠的版本。
2. 修改JaxWsImplementorInfo的目标命名空间(代码发布场景)
如果是通过Java代码直接发布服务,你可以手动修改JaxWsImplementorInfo的命名空间属性,去掉末尾的斜杠:
import org.apache.cxf.jaxws.support.JaxWsImplementorInfo; import javax.xml.ws.Endpoint; public class ServicePublisher { public static void main(String[] args) { JaxWsImplementorInfo implementorInfo = new JaxWsImplementorInfo(YourServiceImpl.class); // 移除命名空间末尾的斜杠 String originalNs = implementorInfo.getTargetNamespace(); if (originalNs != null && originalNs.endsWith("/")) { implementorInfo.setTargetNamespace(originalNs.substring(0, originalNs.length() - 1)); } // 发布服务 Endpoint endpoint = Endpoint.create(implementorInfo); endpoint.publish("http://localhost:8080/yourService"); System.out.println("Service published successfully!"); } }
3. 自定义WSDL生成拦截器(配置式发布场景)
如果是用Spring XML配置发布服务,且无法修改代码注解,可以写一个自定义的拦截器,在WSDL生成阶段修改命名空间:
第一步:编写自定义拦截器
import org.apache.cxf.wsdl.WSDLGeneratorInterceptor; import org.w3c.dom.Element; import javax.wsdl.Definition; import javax.wsdl.extensions.schema.Schema; import java.util.List; public class TrimNamespaceWsdlInterceptor extends WSDLGeneratorInterceptor { @Override protected void populateExtensionMappings(BindingOperationInfo boi, Definition def) { super.populateExtensionMappings(boi, def); // 修改WSDL的目标命名空间 String targetNs = def.getTargetNamespace(); if (targetNs != null && targetNs.endsWith("/")) { def.setTargetNamespace(targetNs.substring(0, targetNs.length() - 1)); } // 修改关联Schema的命名空间 List<?> schemas = def.getSchemas(); for (Object schemaObj : schemas) { if (schemaObj instanceof Schema) { Schema schema = (Schema) schemaObj; Element schemaElement = schema.getElement(); String schemaNs = schemaElement.getAttribute("targetNamespace"); if (schemaNs != null && schemaNs.endsWith("/")) { schemaElement.setAttribute("targetNamespace", schemaNs.substring(0, schemaNs.length() - 1)); } } } } }
第二步:在Spring配置中注册拦截器
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:endpoint id="yourService" implementor="com.your.package.YourServiceImpl" address="/yourService"> <jaxws:outInterceptors> <bean class="com.your.package.TrimNamespaceWsdlInterceptor"/> </jaxws:outInterceptors> </jaxws:endpoint> </beans>
内容的提问来源于stack exchange,提问作者Médéric Martin
相关产品推荐
相关产品推荐

