您的位置:首页 > 其它

【WebService开发】之使用CXF开发WebService

2016-03-19 22:18 435 查看
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<Interceptor<? extends Message>> inInterceptors = endpointImpl.getInInterceptors();
inInterceptors.add(new LoggingInInterceptor());
//服务端的日志出拦截器
List<Interceptor<? extends Message>> 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<Interceptor<? extends Message>> outInterceptors = client.getOutInterceptors();
outInterceptors.add(new LoggingOutInterceptor());
//客户端的日志入拦截器
List<Interceptor<? extends Message>> 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<SoapMessage> {
private String name;
private String password;

public MyInterceptor(String name,String password) {
super(Phase.PRE_PROTOCOL);
this.name = name;
this.password = password;
}

/*
<Envelope>
<head>
<xdy>
<name>xiongdy</name>
<password>123456</password>
</xdy>
</head>
<body>
<sayHello>
<arg0>xdy</arg0>
</sayHello>
</body>
</Envelope>
*/
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
/*
<xdy>
<name>xiongdy</name>
<password>123456</password>
</xdy>
*/
//Document document = DOMHelper.createDocument();
Document document = DOMUtils.createDocument();
//<xdy>
Element rootEle = document.createElement("xdy");

//<name>xiongdy</name>
Element nameEle = document.createElement("name");
nameEle.setTextContent(name);
rootEle.appendChild(nameEle);

//<password>123456</password>
Element passwordEle = document.createElement("password");
passwordEle.setTextContent(password);
rootEle.appendChild(passwordEle);

//添加为请求消息的<soap:Header>
headers.add(new Header(new QName("xdy"), rootEle));

System.out.println("client-----handleMessage");
}
}

2.服务端拦截器:设置in拦截器,从soap消息中获取用户名和密码数据,如果不满足条件就不执行web service的方法

public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
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
4000
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<Interceptor<? extends Message>> 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<Interceptor<? extends Message>> 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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置一些cxf的核心bean -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<!--
终端:发布webservice(将SEI的实现类对象与web service所提供的网络地址关联)
-->
<jaxws:endpoint id="orderService"
implementor="com.xdy.ws.OrderServiceImpl" address="/orderService" />
</beans>

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- 配置上下文初始化参数:指定cxf的spring的beans.xml -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>

<!-- 加载上面参数的配置文件的listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 匹配所有请求,将请求先交给cxf框架处理 -->
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

client端

1. 新建web工程,导入cxf的jar包

2. 根据wsdl文档生成客户端代码(src下)

3. client-beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置发送请求的客户端 -->
<jaxws:client id="orderClient"
serviceClass="com.xdy.ws.OrderService" address="http://localhost:8080/wsspringserver/orderService" />
</beans>

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:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置发送请求的客户端 -->
<jaxws:client id="orderClient"
serviceClass="com.xdy.ws.OrderService" address="http://localhost:8080/wsspringserver/orderService" >
<jaxws:outInterceptors>
<bean class="com.xdy.ws.interceptor.MyInterceptor">
<property name="name" value="xiongdy"></property>
<property name="password" value="123456"></property>
</bean>
</jaxws:outInterceptors>
</jaxws:client>
</beans>

客户端拦截器MyInterceptor:

public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
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.....^_^");
}

/*
<Envelope>
<head>
<xdy>
<name>xiongdy</name>
<password>123456</password>
</xdy>
</head>
<body>
<sayHello>
<arg0>xdy</arg0>
</sayHello>
</body>
</Envelope>
*/
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
/*
<xdy>
<name>xiongdy</name>
<password>123456</password>
</xdy>
*/
//Document document = DOMHelper.createDocument();
Document document = DOMUtils.createDocument();
//<xdy>
Element rootEle = document.createElement("xdy");

//<name>xiongdy</name>
Element nameEle = document.createElement("name");
nameEle.setTextContent(name);
rootEle.appendChild(nameEle);

//<password>123456</password>
Element passwordEle = document.createElement("password");
passwordEle.setTextContent(password);
rootEle.appendChild(passwordEle);

//添加为请求消息的<soap:Header>
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:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- 配置一些cxf的核心bean -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<!--
终端:发布webservice(将SEI的实现类对象与web service所提供的网络地址关联)
-->
<jaxws:endpoint id="orderService"
implementor="com.xdy.ws.OrderServiceImpl" address="/orderService" >
<jaxws:inInterceptors>
<bean class="com.xdy.ws.interceptor.MyInterceptor"/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>

服务端拦截器MyInterceptor:

public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

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("通过拦截器了!");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: