Java Webservice实现

Java可以实现Webservice的框架很多比如Axis1、Axis2、CXF等。 我比较倾向于使用CXF比较简单易学,容易与Spring框架集成。开发中需要注意的是客户端与服务端使用不同框架的时候会有一些细节问题,还有就环境变量、路径、方法名修改等的常见问题。

SpringBoot+CXF框架

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 修改Namespace注解
*/
@WebService(targetNamespace = "http:http://webservice.infotech.vip")
public interface TestService {

// 修改方法名
@WebMethod(operationName = "Test")
public String test(@WebParam(name = "Id") String id);
}


/**
* 配置
*/
@Configuration
public class CxfConfig {

}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CxfClient {

// 1.代理类工厂的方式,需要接口类,通过wsdl2java生成接口类
public static void test1() {
String address = "http://127.0.0.1:8080/soap/test?wsdl";
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
factoryBean.setAddress(address);
// 设置接口类
jaxWsProxyFactoryBean.setServiceClass(TestService.class);
...
}

// 2.动态调用
public static void test() {
// 创建动态客户端
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://127.0.0.1:8080/soap/test?wsdl");
// 需要密码的情况需要加上用户名和密码
// client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
Object[] objects = new Object[0];
try {
// invoke("方法名",参数1,参数2,参数3....);
objects = client.invoke("test", "123");
System.out.println("返回数据:" + objects);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}

}

需要注意,可能出现XML转对象报错,可以添加拦截器打印请求与接收日志,更改写法。对应简单应用还可以不使用框架直接拼接xml 进行HTTP post发送请求,直接解析接收的xml数据

还有一种方式是生成客户端代码的方式。

模拟生成工具

  • SoapUI 很好的测试工具,可以看到完整报文
  • myeclipse的web service生成
  • wsdl2java.bat
  • jdk自带工具生成wsimport
    1
    2
    3
    4
    5
    6
    7
    @org.junit.Test
    public void test() throws Exception {
    UserService_Service service = new UserService_Service();
    UserService port = service.getUserServicePort();
    String age = port.getUserAge("xx");
    System.out.println(age);
    }

直接解析XML

DOM解析:
原理: 一次性加载xml文档,不适合大容量的文件读取
DOM解析可以任意进行增删改成
DOM解析任意读取任何位置的数据,甚至往回读
DOM解析面向对象的编程方法(Node,Element,Attribute)
Java开发者编码比较简单。
SAX解析:
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
SAX解析只能读取
SAX解析只能从上往下,按顺序读取,不能往回读
SAX解析基于事件的编程方法。java开发编码相对复杂

使用java soap包,进行交互

dom4j
javax.xml.soap.MessageFactory;

实际可能遇到问题

java.lang.ClassCastException: 服务端实体类 cannot be cast to 客户端实体类错误解决?

bean类所在路径必须是webservice服务端的路径一致。
所以开发时需要记录好一下信息:

  1. targetNamespace(也就是bean的路径),xmlns:tns,name
  2. 接口的方法名、请求参数与类型、返回值类型 比如: FormResponse test(FormRequest form)

可以再本地环境通过wsdl生成的客户端与服务端进行自测

Boolean

Boolean类型cxf要用get如果是is会导致xml反序列化失败

参考