为什么JAX-WS客户端在运行时访问WSDL?

时间:2013-11-20 16:11:03

标签: wsdl jax-ws

使用wsimport生成JAX-WS客户端

wsimport -keep WebService.wsdl

JAX-WS在运行时需要查找wsdl位置的原因是什么? 这是一个错误吗?

我找到了这篇伟大的帖子: JAX-WS client : what's the correct path to access the local WSDL?

但它没有说明为什么我们在运行时需要wsdl

2 个答案:

答案 0 :(得分:7)

  

这是一个错误吗?

不,这不是一个错误,但从概念的角度来看是合理的。

  

JAX-WS在运行时需要查找wsdl位置的原因是什么?

在构建时,您从WSDL生成类,这意味着您需要知道服务支持哪种操作以及消息具有什么结构(aka portTypestypes,{{1 }})。

在运行时,会发挥许多不同的信息。例如,服务运行的实际地址可能已更改。 messages变得相关:消息应该在SOAP 1.1或1.2中发送还是两种格式都可以?此外,可以将各种策略(安全性,可靠消息传递等)附加到服务上。所有这些都是动态的,在构建时大多不相关。理想情况下,您应该能够将客户端指向使用相同结构的不同服务,并且它应该是开箱即用的。

我想回答一下我认为你可能有的另一个问题:

  

如果只有一项服务永远不会改变,这不是一个总开销吗?

是的,确实如此。如果单个服务具有永远不会从其构建时状态更改的特定WSDL,则在运行时重新加载WSDL是不必要的,并且浪费了资源。但是,如果JAX-WS不允许更复杂的场景,例如绑定或策略确实发生变化,或者服务的端点不止一个,那么JAX-WS就会做得很糟糕。

尽管如此,大多数JAX-WS实现都允许某种机制在本地存储WSDL,而不是在运行时为调用加载它。在RI中,只需将bindings中的wsdlLocation指向类路径上的文件就可以了。

答案 1 :(得分:1)

我认为,也许您需要一个代码解决方案。以下解决方案要求您将WSDL文件存储在resources文件夹中,该文件夹是maven类项目的资源文件夹。

@Bean
public WeatherWebServiceServiceSoap weatherWebServiceServiceSoap() throws Exception{
    URL wslLocation = generatedWsdlLocation();
    if(log.isDebugEnabled()) {
        log.debug("WSDL Location: " + wslLocation.toString());
    }
    // cover wslLocation with the arg constructor
    WeatherWebServiceService weatherWebServiceService = new WeatherWebServiceService(wslLocation);
    weatherWebServiceService.setHandlerResolver(
        portInfo -> webServiceSOAPHandlerList.stream().map(s -> (Handler)s).collect(Collectors.toList()));

    WeatherWebServiceServiceSoap serviceSoap = weatherWebServiceService.getWeatherWebServiceServiceSoap();
    BindingProvider bindingProvider = ((BindingProvider)serviceSoap);

    bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
        wsdlProperties.getAddressLocation());

    return serviceSoap;
}

private URL generatedWsdlLocation() throws MalformedURLException {
    URL baseUrl = ClassUtil.getLocation(this.getClass());
    // the value of WebServiceConstants.WEATHER_WSDL_RESOURCES_LOCATION should be the relative path of your wsdl in resources(e.g. src/main/resources/wsdl, then the value should be wsdl/).
    return new URL(baseUrl, WebServiceConstants.WEATHER_WSDL_RESOURCES_LOCATION);
}

ClassUtil允许您获取jarfile中存储wsdl文件的类路径。

/**
 * ref: https://github.com/scijava/scijava-common/blob/scijava-common-2.62.1/src/main/java/org/scijava/util/ClassUtils.java#L296-L355
 */
@Slf4j
public class ClassUtil {

    /**
     * get the jar classes path where the <code>clazz</codee> belongs to.
     *
     * <p>
     * if in file system(e.g. /path/to/package/TheClass.class) return file directory (e.g. file:/path/to); if in jar (e.g.
     * /path/to/the-jar.jar!/the/package/TheClass), return path in jar( e.g. jar:file:/path/to/the-jar.jar!/BOOT-INF/classes!/)
     * return null when error occured.
     * </p>
     */
    public static URL getLocation(Class<?> clazz) {
        if (clazz == null) {
            // could not load the class
            return null;
        }
        try {
            URL codeSourceLocation = clazz.getProtectionDomain().getCodeSource().getLocation();
            if (codeSourceLocation != null) {
                return codeSourceLocation;
            }
        } catch (Exception e) {
            // SecurityException: Cannot access protection domain.
            // NullPointerException: Protection domain or code source is null.
        }
        final URL classResource = clazz.getResource(clazz.getSimpleName() + ".class");
        if (classResource == null) {
            // cannot find class resource
            return null;
        }
        String url = classResource.toString();
        // java.io.File -> java/io/File.class
        String suffix = clazz.getCanonicalName().replace('.', '/') + ".class";
        if (!url.endsWith(suffix)) {
            if (isDebugEnable()) {
                log.debug("Weired URL: {} should end with {}", url, suffix);
            }
            // weired URL
            return null;
        }

        String classesUrl = url.substring(0, url.length() - suffix.length());
        try {
            return new URL(classesUrl);
        } catch (MalformedURLException e) {
            if (isDebugEnable()) {
                log.debug(e.getMessage(), e);
            }
            return null;
        }
    }

    public static URL getFileLocation(Class<?> clazz) {
        URL url = getLocation(clazz);
        if(url == null) {
            return url;
        }
        String path = url.toString();
        if(path.startsWith("jar:")) {
            // remove "jar:" prefix and "!/" suffix
            path = path.substring(4, path.length() - 2);
        }
        try {
            return new URL(path);
        } catch (MalformedURLException e) {
            if (isDebugEnable()) {
                log.debug(e.getMessage(), e);
            }
            return null;
        }
    }

    private static boolean isDebugEnable() {
        return log.isDebugEnabled();
    }
}

一些参考: