Cxf应用之客户端与服务端

之前写过类似的文章,但真正使用起来的时候,发现客户端的调用更倾向于使用动态代理的方式来完成。所以服务端的配置就要进行的修改。本文正是在此背景下产生的。

1. Maven

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.1.1</version>
</dependency>

2. 客户端

// ---------------------- 工具类
public final class CxfUtil {
    /**
     * 
     * @param url 
     * @param serviceName 方法名
     * @param parms
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static <T> T getServiceResult(String url, String serviceName, Object... parms) {
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        org.apache.cxf.endpoint.Client client = dcf.createClient(url);
        try {
            Object[] objects = client.invoke(serviceName, parms);
            return (T) objects[0];
        } catch (Exception e) {
            throw ExceptionUtil.wrapRuntime(e);
        }
    }
}

// ---------------------- 测试
public class Tester {

    final String BASE_URL_PATH = "http://localhost:9090/zzz/webservice/";

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void zipFile() {
        final String url = BASE_URL_PATH + "mxyzService?wsdl";
        final String serviceName = "zipFile";
        Object serviceResult = CxfUtil.getServiceResult(url, serviceName, "123");
        System.out.println(serviceResult);

    }

}

3. 服务端

3.1 接口

package com.xx.yy.cxf.service;

@WebService((targetNamespace = "http://service.cxf.yy.xx.com")// 命名空间,一般是接口的包名倒序)
interface IHelloWorld {
    String sayHello(@WebParam(name = "username") String username);
}

3.2 接口实现

这里有个注意的位置就是 这里targetNamespace 的值必须和上面接口IHelloWorld中相应的targetNamespace 的值完全一致

@WebService(serviceName = "helloService"//服务名, 可以省略, cxf会自动生成 本类类名+"Service" 这样格式的名称
        , targetNamespace = "http://service.cxf.yy.xx.com"//包名倒序,并且和接口定义保持一致(一模一样!!!比如这里, com后面是没有 / 的), 
        , endpointInterface = "com.xx.yy.cxf.service.IHelloWorld") //接口的完整路径
public class HelloWorldImpl implements IHelloWorld {  
    @Override  
    public String sayHello(String username) {
        return "Hello " + username;  
    }

3.3 其他配置

参见 cxf-spring-pratice-service 中的第3,4小节。

4. 总结

写下本文的主要动机是上面第3.2小节中的问题,同事在写WebService服务端接口时就出现了类似的问题。

5. 错误:No operation was found with the name {xxx}

解决方案有两种:1. 修改服务端。2. 修改客户端。

  1. 修改服务端的方案参见上面的第三小节。出现这种错误肯定是哪一步马虎了。

  2. 而修改客户端可以按照下面这样进行配置

JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance(); 
Client client = factory.createClient(ASMX_WSDL_URL_PATH); // 记得要加入"?llwsdl" 
// 重点就是下面这句了; 至于第一个参数的由来, 参加下图
QName opName = new QName("http://tempuri.org/", "ExportXZQDataToService");  // 指定到接口类所在包 
Object[] res = client.invoke(opName, "123456"); 
System.out.println("Say: " + res[0]); 

QName第一个参数的由来

  1. springboot1.5.4 集成cxf完整实例
  2. spring boot整合cxf发布webservice服务和cxf客户端调用
  3. CXF异常:No operation was found with the name
  4. CXF动态客户端总是提示No operation was found with the name {…},命名空间问题
  5. 注解解释

猜你喜欢

转载自blog.csdn.net/lqzkcx3/article/details/80192680