WebService学习系列之CXF开发WebService
手动编写服务端代码开发分为四步:
1.引入cxf相关jar包
2.新增服务接口
3.新增服务接口实现
4.新增发布服务类
手动编写客户端代码开发分为两步:
1.获取wsdl文件
2.新增客户端调用类
调用方式分为两种,分别是静态调用和动态调用
服务端客户端全自动生成代码
- 通过wsdl文件生成服务端代码和客户端代码的工程中不需要引入任何cxf的jar包(真强大,axis2框架生成的代码还需要引入axis2的jar包)
手动编码服务端开发
1.引入cxf相关jar
org.apache.cxf
cxf-rt-frontend-jaxws
3.1.9
org.apache.cxf
cxf-rt-transports-http-jetty
3.1.9
org.apache.cxf
cxf-core
3.1.9
2.新增服务接口
在接口上添加注解@WebService(serviceName="MyHelloWorldService")
package com.tg.cxf;
/**
* description:
*
* @author tanggao
* @date 2019/10/22 21:56
* @version 1.0
*/
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
/**
*
* ......................我佛慈悲......................
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -卍-|||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
.....................................................
...... 一切有为法,如梦幻泡影,如露亦如电,应作如是观 ........
......... 三界唯心,万法唯识 ...........
............ bug即空,空即bug,永无bug .............
.....................................................
*/
@WebService(serviceName="MyHelloWorldService")
public interface HelloWorldService {
public @WebResult(name="returnHello")String sayHello(@WebParam(name="name")String name);
public @WebResult(name="returnPerson")Person getPerson(@WebParam(name="name")String name);
}
3.新增服务接口实现
package com.tg.cxf;
/**
* description:
*
* @author tanggao
* @date 2019/10/22 21:59
* @version 1.0
*/
import javax.jws.WebParam;
/**
*
* ......................我佛慈悲......................
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -卍-|||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
.....................................................
...... 一切有为法,如梦幻泡影,如露亦如电,应作如是观 ........
......... 三界唯心,万法唯识 ...........
............ bug即空,空即bug,永无bug .............
.....................................................
*/
public class HelloWorldServiceImpl implements HelloWorldService {
public String sayHello(String name) {
return "hello,"+name;
}
public Person getPerson(String name) {
Person p =new Person();
p.setName(name);
p.setAge(24);
return p;
}
}
实现类依赖的Person类如下:
4.新增发布服务类
package com.tg.cxf;
/**
* description:
*
* @author tanggao
* @date 2019/10/22 22:02
* @version 1.0
*/
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/**
*
* ......................我佛慈悲......................
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -卍-|||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
.....................................................
...... 一切有为法,如梦幻泡影,如露亦如电,应作如是观 ........
......... 三界唯心,万法唯识 ...........
............ bug即空,空即bug,永无bug .............
.....................................................
*/
public class CxfServer {
public static void main(String[] args) {
System.out.println("web Service start");
HelloWorldServiceImpl implementor = new HelloWorldServiceImpl();
String address="http://localhost/helloWorld";
JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
factoryBean.setAddress(address); //设置暴露地址
factoryBean.setServiceClass(HelloWorldService.class); //接口类
factoryBean.setServiceBean(implementor); //设置实现类
factoryBean.create();
System.out.println("web Service started");
}
}
验证服务发布是否成功,访问wsdl,wsdl路径即为发布的路径加上?wsdl
http://localhost/helloWorld?wsdl
客户端开发步骤
1.获取wsdl文件
wsdl文件可以是实时的wsdl网址,比如:
http://localhost/helloWorld?wsdl
也可以是离线的wsdl文件
2.手动编写客户端静态调用代码
package com.tg.cxf;
/**
* description:
*
* @author tanggao
* @date 2019/10/22 22:05
* @version 1.0
*/
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
/**
*
* ......................我佛慈悲......................
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -卍-|||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
.....................................................
...... 一切有为法,如梦幻泡影,如露亦如电,应作如是观 ........
......... 三界唯心,万法唯识 ...........
............ bug即空,空即bug,永无bug .............
.....................................................
静态调用需要依赖service类,因为客户端调用cxf webservice接口的过程中需要服务器端提供service,很不方便,如果同一个项目中则没有区别。
*/
public class StaticClient {
public static void main(String[] args) {
// 创建WebService客户端代理工厂
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// 判断是否抛出异常
factory.getOutInterceptors().add(new LoggingInInterceptor());
// 注册webservice接口
factory.setServiceClass(HelloWorldService.class);
// 配置webservice地址
factory.setAddress("http://localhost/helloWorld?wsdl");
// 获得接口对象
HelloWorldService service = (HelloWorldService) factory.create();
// 调用接口方法
String result = service.sayHello("aaaaaaaaaa");
System.out.println("调用结果:" + result);
}
}
运行结果
静态调用需要依赖service类,因为客户端调用cxf webservice接口的过程中需要服务器端提供service,很不方便,如果同一个项目中则没有区别
3.手动编写客户端动态调用代码
package com.tg.cxf;
/**
* description:
*
* @author tanggao
* @date 2019/10/22 22:08
* @version 1.0
*/
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import javax.xml.namespace.QName;
public class DynamicClient {
public static void main(String[] args) {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
org.apache.cxf.endpoint.Client client = dcf
.createClient("http://localhost/helloWorld?wsdl");
// url为调用webService的wsdl地址
// namespace是命名空间,methodName是方法名
QName name = new QName("http://cxf.tg.com/", "sayHello");
String xmlStr = "aaaaaaaa";
// paramvalue为参数值
Object[] objects;
try {
objects = client.invoke(name, xmlStr);
System.out.println(objects[0].toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
一般都不会自己写代码,都是通过工具生成客户端代码
通过工具根据wsdl文件生成客户端调用类
官网下载cxf ,下载完后如下图
在bin目录中有一个wsdl2java命令
注意,如果要直接使用该命令,需要将bin加入环境变量中
准备wsdl文件,如下是本地保存的wsdl文件 C:\Users\Administrator\Desktop\daima\helloWorld.xml
打开cmd ,输入
wsdl2java -encoding utf-8 -p com.asiainfo.ws.boss -d E:\idea-yaxin\cxfclient\src -client C:\Users\Administrator\Desktop\daima\helloWorld.xml
参数
-encoding 指定编码集
-p 指定其wsdl的命名空间,也就是要生成代码的包名:
-d 指定要产生代码所在目录
-client 生成客户端测试web service的代码
在指定工程路径下生产了客户端代码
因为生成代码时指定了参数 -client,所以客户端调用类HelloWorldService_HelloWorldServicePort_Client 也生成了,如下类
package com.cxf.client;
/**
* Please modify this class to meet your needs
* This class is not complete
*/
import javax.xml.namespace.QName;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
/**
* This class was generated by Apache CXF 3.3.3
* 2019-11-02T18:14:45.976+08:00
* Generated source version: 3.3.3
*
*/
public final class HelloWorldService_HelloWorldServicePort_Client {
private static final QName SERVICE_NAME = new QName("http://cxf.tg.com/", "MyHelloWorldService");
private HelloWorldService_HelloWorldServicePort_Client() {
}
public static void main(String args[]) throws java.lang.Exception {
URL wsdlURL = MyHelloWorldService.WSDL_LOCATION;
if (args.length > 0 && args[0] != null && !"".equals(args[0])) {
File wsdlFile = new File(args[0]);
try {
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(args[0]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
MyHelloWorldService ss = new MyHelloWorldService(wsdlURL, SERVICE_NAME);
HelloWorldService port = ss.getHelloWorldServicePort();
{
System.out.println("Invoking sayHello...");
java.lang.String _sayHello_name = "";
java.lang.String _sayHello__return = port.sayHello(_sayHello_name);
System.out.println("sayHello.result=" + _sayHello__return);
}
{
System.out.println("Invoking getPerson...");
java.lang.String _getPerson_name = "";
com.cxf.client.Person _getPerson__return = port.getPerson(_getPerson_name);
System.out.println("getPerson.result=" + _getPerson__return);
}
System.exit(0);
}
}
直接修改一下传入的参数,查看运行结果
通过wsdl文件生成服务端代码
还可以通过已经制定好的wsdl文件生成服务端代码,
有两个好处:
1.可以通过制定好的wsdl文件,直接生成服务端代码,无需编码,节省编码时间
2.当我们写客户端时,如果要服务端当前不能调用,而我们又要测试客户端的业务逻辑,所有可以根据wsdl文件生成服务端,服务端直接返回成功结果给客户端调式用。
生成服务端命令
wsdl2java -encoding utf-8 -p com.cxf.server -impl -d E:\idea-yaxin\cxfserver\src -server C:\Users\Administrator\Desktop\daima\helloWorld.xml
参数
-encoding 代码编码集
-p 指定其wsdl的命名空间,也就是要生成代码的包名:
-d 指定要产生代码所在目录
-server 生成服务器启动web service的代码
-impl 生成web service的服务端代码
在指定工程生成了服务端代码
因为指定了参数-server ,所以生成了启动类HelloWorldService_HelloWorldServicePort_Server
修改一下生成类的wsdl文件路径
直接启动HelloWorldService_HelloWorldServicePort_Server类
查看wsdl文件
到此为止,webservice服务端代码生成成功!
cxf强大之处在于通过wsdl文件生成的客户端和服务端不需要引入任何cxf的jar包!!!!,但是Axis2生成的服务端和客户端确需要引入大量jar包,这就是我不喜欢用它的原因!