代码之家  ›  专栏  ›  技术社区  ›  Michael Zhavzharov

CXF、wsdl2java。自定义端口名称

  •  1
  • Michael Zhavzharov  · 技术社区  · 6 年前

    简短问题: 我可以绑定吗 wsdl:port 要在服务中生成自定义java字段名的名称?

    冗长的问题 : 我有一个包含以下部分的wsdl:

    <wsdl:service name="123xxx">
       <wsdl:port name="123xxxHttpSoap11Endpoint" binding="tns:123xxxSoap11Binding">
         <soap:address location="..."/>
       </wsdl:port>
    </wsdl:service>
    

    还有一个专家 wsdl2java 生成名称为的服务的目标 123xxx (我已经通过调用binding修复了它 MyService )在该服务中,它生成一个字段:

    public class MyService extends Service {
        ...
        public final static QName 123xxxHttpSoap11Endpoint = 
                     new QName("http://new.webservice.namespace", "123xxxHttpSoap11Endpoint");
        ...
    }
    

    这会导致编译错误,因为在Java中变量不能以数字开头。我无法找到一种方法来定制生成的代码,而不更改原始wsdl。

    那么,有没有办法通过 cxf 绑定,就像服务本身一样:

    <bindings...>
        <bindings node="wsdl:definitions/wsdl:service">
        <class name="MyService"/>
        </bindings>
    </bindings>
    

    或者有没有其他方法可以实现这一点?

    4 回复  |  直到 6 年前
        1
  •  6
  •   Michael Zhavzharov    6 年前

    最后我找到了解决办法。 当然,这是常见wsdl生成过程的开销,但这只是(或几乎是唯一)满足我的限制的方法。

    首先我查了 cxf 并发现有一种生成端口元素的方法:

    org.apache.cxf.tools.wsdlto.frontend.jaxws.processor.internal.ServiceProcessor#processPort
    

    这就创造了 JavaPort 名称,取自原始 wsdl 并且不会对其进行任何绑定:

    JavaPort jport = new JavaPort(NameUtil.mangleNameToClassName(port.getName().getLocalPart()));
    

    进一步说,我发现有可能注入自定义代码生成器,它负责创建 java 来自的类 cxf公司 模型

    经过研究我发现 this answer 这帮我成功了。

    因此,我使用此类类创建了一个单独的模块(检查注释):

    //note that I've put my class inside the package, 
    //which is used for other default generators in cxf
    package org.apache.cxf.tools.wsdlto.frontend.jaxws.generators;
    
    import java.util.List;
    import java.util.Map;
    
    import org.apache.cxf.tools.common.ToolContext;
    import org.apache.cxf.tools.common.ToolException;
    import org.apache.cxf.tools.common.model.JavaPort;
    import org.apache.cxf.tools.common.model.JavaServiceClass;
    
    public class CustomSEIGenerator extends SEIGenerator {
    
        @Override
        public void generate(ToolContext penv) throws ToolException {
            //no streams, because we still on java 7
            //fetch all services
            Map<String, JavaServiceClass> ss = penv.getJavaModel().getServiceClasses();
            for (Map.Entry<String, JavaServiceClass> s : ss.entrySet()) {
                //fetch all ports from each service
                for (JavaPort port : s.getValue().getPorts()) {
                    //set custom name to each port
                    port.setName("_" + port.getName);
                }
            }
        }
    }
    

    并放置了 tools-plugin.xml 进入 META-INF 文件夹:

    <?xml version="1.0" encoding="utf-8"?>
    <plugin xmlns="http://cxf.apache.org/tools/plugin" name="play" version="" provider="play.typesafe.com">
        <frontend name="sample" package="org.apache.cxf.tools.wsdlto.frontend.jaxws" profile="JAXWSProfile">
            <container name="JAXWSContainer" package="org.apache.cxf.tools.wsdlto.frontend.jaxws" toolspec="jaxws-toolspec.xml"/>
            <processor name="WSDLToJavaProcessor" package="org.apache.cxf.tools.wsdlto.frontend.jaxws.processor"/>
            <builder name="JAXWSDefinitionBuilder" package="org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11"/>
            <generators package="org.apache.cxf.tools.wsdlto.frontend.jaxws.generators">
                <generator name="CustomSEIGenerator"/>
                <generator name="AntGenerator"/>
                <generator name="ClientGenerator"/>
                <generator name="FaultGenerator"/>
                <generator name="ImplGenerator"/>
                <generator name="SEIGenerator"/>
                <generator name="ServerGenerator"/>
                <generator name="ServiceGenerator"/>
            </generators>
        </frontend>
    </plugin>
    

    (请注意,我已将自定义生成器放在默认生成器之前,以使其与修改后的模型一起工作)。

    接下来,我刚刚根据上面发布的答案修改了pom文件,很高兴看到它能正常工作。

        2
  •  3
  •   ACHC    6 年前

    除非您绑定到wsdl2java,否则请改用wsimport。它将在任何以数字开头的变量之前添加下划线。这也有一个马文式的目标。

        3
  •  2
  •   Isukthar    6 年前

    我建议您更改WSDL。WSDL中的此字段应该具有不能以数字开头的NCName类型。 如果启用WSDL验证,我认为您将直接在WSDL语法中遇到错误。因此,不确定您是否可以通过自定义绑定来事后更正此问题。

        4
  •  2
  •   Dams    6 年前

    正如Tarun Lalwani在评论I thing中提到的,您应该使用如下jaxb绑定:

    <plugin>
        <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-codegen-plugin</artifactId>
            <version>${cxf.version}</version>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <configuration>
                        <sourceRoot>
                            ${basedir}/src/main/java
                        </sourceRoot>
                        <wsdlOptions>
                            <wsdlOption>
                                <wsdl>
                                    ${basedir}/xxx/yourwsdl.wsdl
                                </wsdl>
                                    <extraargs>
                                    <!-- you can redefine the client -->
                                    <extraarg>-client</extraarg>
                                    <extraarg>-b</extraarg>
                                    <extraarg>${basedir}/xxx/binding.xml</extraarg>
                        </extraargs>
                        </wsdlOption>
                    </wsdlOptions>
                </configuration>
                <goals>
                    <goal>wsdl2java</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    绑定文件:

    <bindings
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        wsdlLocation="yourwsdl.wsdl"
        xmlns="http://java.sun.com/xml/ns/jaxws">
    
        <bindings node="wsdl:definitions/wsdl:portType[@name='123xxxHttpSoap11Endpoint']">
        <class name="yourservice"/>
        </bindings>
    </bindings>
    

    看见 JAXWS Customization