使用wsimport生成JAX-WS客户端
wsimport -keep WebService.wsdl
JAX-WS在运行时需要查找wsdl位置的原因是什么? 这是一个错误吗?
我找到了这篇伟大的帖子: JAX-WS client : what's the correct path to access the local WSDL?
但它没有说明为什么我们在运行时需要wsdl
答案 0 :(得分:7)
这是一个错误吗?
不,这不是一个错误,但从概念的角度来看是合理的。
JAX-WS在运行时需要查找wsdl位置的原因是什么?
在构建时,您从WSDL生成类,这意味着您需要知道服务支持哪种操作以及消息具有什么结构(aka portTypes
,types
,{{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();
}
}
一些参考: