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

如何去除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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:28:58