1.开发服务端
a) 下载CXF:apache-cxf-3.1.6
b) 把cxf的jar包加入到项目中,其它不需要改变(同JDK开发webservice一样),webservice服务端开发完成。
2.开发客户端
a) 加入环境变量path中,E:\apache-cxf-3.1.6\bin
b) 在cmd命令下生成客户代码,命令为:wsdl2java url,该命令为cxf的bin目录下的功能。
c) 编写客户端测试代码
public class ClientTest {
public static void main(String[] args) {
HelloWSImplService factory = new HelloWSImplService();
HelloWs helloWs = factory.getHelloWSImplPort();
String result = helloWs.sayHello("xdy");
System.out.println(result);
}
}
WebService请求的流程
一次web service请求的本质:
1.客户端向服务端发送了一个soap消息(http请求+xml片断)。
2.服务器端处理完请求后,向客户端返回一个soap消息。
/**********************************华丽分割线******************************************/
CXF框架的使用
1、CXF的拦截器
为什么设计拦截器?
为了在webservice请求过程中,能动态操作请求和响应数据,CXF设计了拦截器。
拦截器分类:
1.按所处的位置分:服务器端拦截器,客户端拦截器。
2.按消息的方向分:入拦截器,出拦截器。
3.按定义者分:系统拦截器,自定义拦截器。
【示例】演示为客户端及服务端加入日志拦截器。
为服务端ServerTest加入日志拦截器。
public class ServerTest {
public static void main(String[] args) {
String address = "http://192.168.0.102:8989/day01_ws/hellows";
Endpoint endpoint = Endpoint.publish(address, new HelloWSImpl());
System.out.println(endpoint);
EndpointImpl endpointImpl = (EndpointImpl)endpoint;
//服务端的日志入拦截器
List> inInterceptors = endpointImpl.getInInterceptors();
inInterceptors.add(new LoggingInInterceptor());
//服务端的日志出拦截器
List> outInterceptors = endpointImpl.getOutInterceptors();
outInterceptors.add(new LoggingOutInterceptor());
System.out.println("发布webservice成功!");
}
}
为客户端ClientTest加入日志拦截器。
public class ClientTest {
public static void main(String[] args) {
HelloWSImplService factory = new HelloWSImplService();
HelloWs helloWs = factory.getHelloWSImplPort();
//发送请求的客户端对象
Client client = ClientProxy.getClient(helloWs);
//客户端的日志出拦截器
List> outInterceptors = client.getOutInterceptors();
outInterceptors.add(new LoggingOutInterceptor());
//客户端的日志入拦截器
List> inInterceptors = client.getInInterceptors();
inInterceptors.add(new LoggingInInterceptor());
String result = helloWs.sayHello("xdy");
System.out.println(result);
}
}
2、CXF自定义拦截器
AbstractPhaseInterceptor:抽象过程拦截器,一般自定义的拦截器都会继承于它
功能:通过自定义拦截器实现用户名和密码的检查
1.客户端拦截器:设置out拦截器,向soap消息中添加用户名和密码数据
public class MyInterceptor extends AbstractPhaseInterceptor {
private String name;
private String password;
public MyInterceptor(String name,String password) {
super(Phase.PRE_PROTOCOL);
this.name = name;
this.password = password;
}
/*
xiongdy
123456
xdy
*/
public void handleMessage(SoapMessage message) throws Fault {
List headers = message.getHeaders();
/*
xiongdy
123456
*/
//Document document = DOMHelper.createDocument();
Document document = DOMUtils.createDocument();
//
Element rootEle = document.createElement("xdy");
//xiongdy
Element nameEle = document.createElement("name");
nameEle.setTextContent(name);
rootEle.appendChild(nameEle);
//123456
Element passwordEle = document.createElement("password");
passwordEle.setTextContent(password);
rootEle.appendChild(passwordEle);
//添加为请求消息的
headers.add(new Header(new QName("xdy"), rootEle));
System.out.println("client-----handleMessage");
}
}
2.服务端拦截器:设置in拦截器,从soap消息中获取用户名和密码数据,如果不满足条件就不执行web service的方法
public class MyInterceptor extends AbstractPhaseInterceptor {
public MyInterceptor() {
super(Phase.PRE_PROTOCOL);
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
System.out.println("server-----handleMessage");
Header header = msg.getHeader(new QName("xdy"));
if(header==null) {
throw new Fault(new RuntimeException("用户名密码不存在 "));
} else {
Element data = (Element) header.getObject();
if(data==null) {
throw new Fault(new RuntimeException("用户名密码不存在22"));
} else {
String name = data.getElementsByTagName("name").item(0).getTextContent();
String password = data.getElementsByTagName("password").item(0).getTextContent();
if(!"xiongdy".equals(name) || !"123456".equals(password)) {
throw new Fault(new RuntimeException("用户名密码不正确"));
}
}
}
System.out.println("通过拦截器了!");
}
}
3.服务端测试代码:
public class ServerTest {
public static void main(String[] args) {
String address = "http://192.168.0.102:8989/day01_ws/hellows";
Endpoint endpoint = Endpoint.publish(address, new HelloWSImpl());
System.out.println(endpoint);
EndpointImpl endpointImpl = (EndpointImpl)endpoint;
//服务端的自定义入拦截器
List> inInterceptors = endpointImpl.getInInterceptors();
inInterceptors.add(new MyInterceptor());
System.out.println("发布webservice成功!");
}
}
4.客户端测试代码
public class ClientTest2 {
public static void main(String[] args) {
HelloWSImplService factory = new HelloWSImplService();
HelloWs helloWs = factory.getHelloWSImplPort();
//发送请求的客户端对象
Client client = ClientProxy.getClient(helloWs);
//客户端的自定义出拦截器
List> outInterceptors = client.getOutInterceptors();
outInterceptors.add(new MyInterceptor("xiongdy", "123456"));
String result = helloWs.sayHello("xdy");
System.out.println(result);
}
}
用CXF编写基于Spring的WebService
server端:
1. 新建web工程,导入cxf的jar包
2. 定义SEI和其实现
@WebService
public interface OrderService {
@WebMethod
public Order getOrderByNo(String orderNo);
}
@WebService
public class OrderServiceImpl implements OrderService {
public OrderServiceImpl() {
System.out.println("OrderServiceImpl()");
}
public Order getOrderByNo(String orderNo) {
System.out.println("getOrderByNo() orderNO=" + orderNo);
return new Order(3, orderNo, 10000000);
}
}
public class Order {
private int id;
private String orderNo;
private double price;
}
3. 发布web service
beans.xml
Web.xml
index.jsp
contextConfigLocation
classpath:beans.xml
org.springframework.web.context.ContextLoaderListener
CXFServlet
org.apache.cxf.transport.servlet.CXFServlet
1
CXFServlet
/*
client端
1. 新建web工程,导入cxf的jar包
2. 根据wsdl文档生成客户端代码(src下)
3. client-beans.xml
4. 编写测试代码:
public class ClientTest {
public static void main(String[] args) {
// 加载client-beans.xml
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("client-beans.xml");
// 根据bean的id加载所对应的OrderService
OrderService orderService = (OrderService) context.getBean("orderClient");
// 调用方法,发送soap请求
Order order = orderService.getOrderByNo("hao123");
System.out.println("client " + order.getId() + "_" + order.getOrderNo()+ "_" + order.getPrice());
}
}
用CXF编写基于Spring的WebService添加拦截器
客户端:
client-beans.xml:
客户端拦截器MyInterceptor:
public class MyInterceptor extends AbstractPhaseInterceptor {
private String name;
private String password;
public MyInterceptor(String name,String password) {
super(Phase.PRE_PROTOCOL);
this.name = name;
this.password = password;
System.out.println("MyInterceptor.....");
}
public MyInterceptor() {
super(Phase.PRE_PROTOCOL);
System.out.println("MyInterceptor.....^_^");
}
/*
xiongdy
123456
xdy
*/
public void handleMessage(SoapMessage message) throws Fault {
List headers = message.getHeaders();
/*
xiongdy
123456
*/
//Document document = DOMHelper.createDocument();
Document document = DOMUtils.createDocument();
//
Element rootEle = document.createElement("xdy");
//xiongdy
Element nameEle = document.createElement("name");
nameEle.setTextContent(name);
rootEle.appendChild(nameEle);
//123456
Element passwordEle = document.createElement("password");
passwordEle.setTextContent(password);
rootEle.appendChild(passwordEle);
//添加为请求消息的
headers.add(new Header(new QName("xdy"), rootEle));
System.out.println("client-----handleMessage");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
服务器端:
Beans.xml:
服务端拦截器MyInterceptor:
public class MyInterceptor extends AbstractPhaseInterceptor {
public MyInterceptor() {
super(Phase.PRE_PROTOCOL);
}
public void handleMessage(SoapMessage msg) throws Fault {
System.out.println("server-----handleMessage");
Header header = msg.getHeader(new QName("xdy"));
if(header==null) {
throw new Fault(new RuntimeException("用户名密码不存在 "));
} else {
Element data = (Element) header.getObject();
if(data==null) {
throw new Fault(new RuntimeException("用户名密码不存在22"));
} else {
String name = data.getElementsByTagName("name").item(0).getTextContent();
String password = data.getElementsByTagName("password").item(0).getTextContent();
if(!"xiongdy".equals(name) || !"123456".equals(password)) {
throw new Fault(new RuntimeException("用户名密码不正确"));
}
}
}
System.out.println("通过拦截器了!");
}
}