如何避免在CXF或JAX-WS生成的webservice客户端中指定WSDL位置?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (332)

当我通过maven使用来自CXF的wsdl2java(它生成类似wsimport的内容)生成一个webservice客户机时,我的服务以如下代码开头:

@WebServiceClient(name = "StatusManagement", 
                  wsdlLocation = "c:/some_absolute_path_to_a_wsdl_file.wsdl",
                  targetNamespace = "http://tempuri.org/") 
public class StatusManagement extends Service {

    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
    public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
    static {
        URL url = null;
        try {
            url = new URL("c:/some_absolute_path_to_a_wsdl_file.wsdl");
        } catch (MalformedURLException e) {
            System.err.println("Can not initialize the default wsdl from c:/some_absolute_path_to_a_wsdl_file.wsdl");
            // e.printStackTrace();
        }
        WSDL_LOCATION = url;
    }

生成的类不会在除我的计算机之外的任何其他计算机中工作。

第一个想法是将WSDL文件(加上它导入的所有东西,其他WSDL和XSD)放在JAR文件中,并对其进行类路径处理。但我们想避免这种情况。因为所有这些东西都是由基于WSDL和XSD的CXF和JAXB生成的,所以我们认为在运行时不需要知道WSDL。

wsdlLocation属性的目的是覆盖WSDL位置(至少这是我在某个地方看到的),它的默认值是“”。由于我们使用的是maven,所以我们尝试将<wsdlLocation></wsdlLocation>在CXF的配置中,尝试强制源生成器将wsdlLocation保留为空白。但是,这只会使它忽略XML标记,因为它是空的。我们做了一次非常丑陋的可耻的攻击,用<wsdlLocation>" + "</wsdlLocation>.

这也改变了其他地方:

@WebServiceClient(name = "StatusManagement", 
                  wsdlLocation = "" + "",
                  targetNamespace = "http://tempuri.org/") 
public class StatusManagement extends Service {

    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
    public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
    static {
        URL url = null;
        try {
            url = new URL("" + "");
        } catch (MalformedURLException e) {
            System.err.println("Can not initialize the default wsdl from " + "");
            // e.printStackTrace();
        }
        WSDL_LOCATION = url;
    }

所以,我的问题是:

  1. 即使所有的类都是由CXF和JAXB生成的,我们真的需要WSDL位置吗?如果是,为什么?
  2. 如果我们真的不需要WSDL位置,那么如何才能使CXF不生成并且完全避免它呢?
  3. 那次黑客攻击会带来什么副作用?我们仍然不能测试这个结果,所以如果有人能提前说的话,那就太好了。
提问于
用户回答回答于

今天我终于找到了这个问题的正确答案。

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-codegen-plugin</artifactId>
    <version>${cxf.version}</version>
    <executions>
        <execution>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
            <configuration> 
                <sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
                <wsdlOptions>
                    <wsdlOption>
                        <wsdl>${project.basedir}/src/main/resources/wsdl/FooService.wsdl</wsdl>
                        <wsdlLocation>classpath:wsdl/FooService.wsdl</wsdlLocation>
                    </wsdlOption>
                </wsdlOptions>
            </configuration>
            <goals>
                <goal>wsdl2java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

注意,我在wsdlLocation带着classpath:。这告诉插件WSDL将在类路径上而不是绝对路径上。然后,它将生成类似于以下代码的代码:

@WebServiceClient(name = "FooService", 
                  wsdlLocation = "classpath:wsdl/FooService.wsdl",
                  targetNamespace = "http://org/example/foo") 
public class Foo_Service extends Service {

    public final static URL WSDL_LOCATION;

    public final static QName SERVICE = new QName("http://org/example/foo", "Foo");
    public final static QName FooSOAPOverHTTP = new QName("http://org/example/foo", "Foo_SOAPOverHTTP");
    static {
        URL url = Foo_Service.class.getClassLoader().getResource("wsdl/FooService.wsdl");
        if (url == null) {
            java.util.logging.Logger.getLogger(Foo_Service.class.getName())
                .log(java.util.logging.Level.INFO, 
                     "Can not initialize the default wsdl from {0}", "classpath:wsdl/FooService.wsdl");
        }       
        WSDL_LOCATION = url;
    }
用户回答回答于

wsdlLocation = "WEB-INF/wsdl/WSDL.wsdl"

使用相对于类路径的路径。

我相信在运行时可能需要WSDL来验证在封送/解封送处理期间的消息。

扫码关注云+社区