Vic*_*usa 157 java wsdl cxf wsdl2java
当我使用来自CXF的wsdl2java(生成类似于wsimport的东西)生成一个webservice客户端时,通过maven,我的服务从这样的代码开始:
@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;
}
Run Code Online (Sandbox Code Playgroud)
硬编码的绝对路径真的很糟糕.生成的类不能在除我之外的任何其他计算机上工作.
第一个想法是将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;
}
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是:
即使所有类都是由CXF和JAXB生成的,我们是否真的需要WSDL位置?如果是,为什么?
如果我们真的不需要WSDL位置,那么使CXF不生成并完全避免它的正确和干净的方法是什么?
我们可以通过该黑客获得哪些不良副作用?我们仍然无法测试看看会发生什么,所以如果有人可以提前说,那就太好了.
Kyl*_*yle 202
我终于在今天找到了这个问题的正确答案.
<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>
Run Code Online (Sandbox Code Playgroud)
请注意,我已将值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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这仅适用于版本2.4.1或更高版本的cxf-codegen-plugin.
BPS*_*BPS 20
我们用
wsdlLocation = "WEB-INF/wsdl/WSDL.wsdl"
Run Code Online (Sandbox Code Playgroud)
换句话说,使用相对于类路径的路径.
我相信在运行时可能需要WSDL来在编组/解组期间验证消息.
Mar*_*ers 17
对于那些org.jvnet.jax-ws-commons:jaxws-maven-plugin
用于在构建时从WSDL生成客户端的人:
src/main/resources
wsdlLocation
与classpath:
wsdlLocation
加上/
例:
/src/main/resources/foo/bar.wsdl
jaxws-maven-plugin
与<wsdlDirectory>${basedir}/src/main/resources/foo</wsdlDirectory>
和<wsdlLocation>/foo/bar.wsdl</wsdlLocation>
1)在某些情况下,是的.如果WSDL包含诸如策略之类的内容以及指示运行时行为的内容,那么在运行时可能需要WSDL.不会为与策略相关的事物生成工件.此外,在一些不起眼的RPC/Literal情况下,并非所有需要的命名空间都在生成的代码中输出(按照规范).因此,他们需要wsdl.虽然模糊不清的案例.
2)我认为会有所作为.什么版本的CXF?这听起来像个bug.你可以在那里尝试一个空字符串(只是空格).不确定这是否有效.也就是说,在您的代码中,您可以使用获取WSDL URL的构造函数并只传递null.不会使用wsdl.
3)只是上面的限制.
我能够产生
static {
WSDL_LOCATION = null;
}
Run Code Online (Sandbox Code Playgroud)
通过将pom文件配置为wsdlurl为null:
static {
WSDL_LOCATION = null;
}
Run Code Online (Sandbox Code Playgroud)
CXF 3.1.7 更新
就我而言,我将 WSDL 文件放入其中src/main/resources
,并将此路径添加到 Eclipse 中的 Srouces 中(右键单击“项目”->“构建路径”->“配置构建路径...”->“源[选项卡]”->“添加文件夹”)。
这是我的pom
文件的样子,可以看出不需要任何wsdlLocation
选项:
<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/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>classpath:wsdl/FOO_SERVICE.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
这是生成的Service。可以看出,URL 是从 ClassLoader 获取的,而不是从绝对文件路径获取的
@WebServiceClient(name = "EventService",
wsdlLocation = "classpath:wsdl/FOO_SERVICE.wsdl",
targetNamespace = "http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/")
public class EventService extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventService");
public final static QName EventPort = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventPort");
static {
URL url = EventService.class.getClassLoader().getResource("wsdl/FOO_SERVICE.wsdl");
if (url == null) {
java.util.logging.Logger.getLogger(EventService.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "classpath:wsdl/FOO_SERVICE.wsdl");
}
WSDL_LOCATION = url;
}
Run Code Online (Sandbox Code Playgroud)
@Martin Devillers 解决方案效果很好。为了完整起见,提供以下步骤:
src/main/resource
在pom文件中,添加wsdlDirectory和wsdlLocation(不要错过wsdlLocation开头的/),如下所示。wsdlDirectory 用于生成代码,而 wsdlLocation 在运行时用于创建动态代理。
<wsdlDirectory>src/main/resources/mydir</wsdlDirectory>
<wsdlLocation>/mydir/my.wsdl</wsdlLocation>
Run Code Online (Sandbox Code Playgroud)然后在你的java代码中(使用无参数构造函数):
MyPort myPort = new MyPortService().getMyPort();
Run Code Online (Sandbox Code Playgroud)这是 pom 文件中的完整代码生成部分,生成的代码中有 Fluent api。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-fluent-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-tools</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>wsdl-to-java-generator</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xjcArgs>
<xjcArg>-Xfluent-api</xjcArg>
</xjcArgs>
<keep>true</keep>
<wsdlDirectory>src/main/resources/package</wsdlDirectory>
<wsdlLocation>/package/my.wsdl</wsdlLocation>
<sourceDestDir>${project.build.directory}/generated-sources/annotations/jaxb</sourceDestDir>
<packageName>full.package.here</packageName>
</configuration>
</execution>
</executions>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
152161 次 |
最近记录: |