下面的例子是摘抄的CXF官网的例子,然后自己动手测试成功之后的结果
另外,添加了验证的处理
首先是添加Maven依赖:
<dependencies> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf-version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf-version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring-version}</version> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cxf-version>2.7.8</cxf-version> <spring-version>3.2.6.RELEASE</spring-version> </properties>
然后开始server端:
在web.xml中添加CXF的servlet(拦截符合 /cxf/* 的所有请求):
<servlet> <servlet-name>CXFService</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CXFService</servlet-name> <url-pattern>/cxf/*</url-pattern> </servlet-mapping>
在applicationContext.xml中引入CXF的配置文件:cxf-servlet.xml,这样是为了将CXF的配置放到单独的文件中
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动注入功能 --> <context:annotation-config /> <!-- 启动扫描component功能 --> <context:component-scan base-package="com.tch.test.cxf.server" /> <import resource="cxf-servlet.xml"/> </beans>
cxf-servlet.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"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="helloWorld" implementor="#helloWorldWebService" address="/HelloWorld"> <jaxws:inInterceptors> <!-- 添加头信息处理的拦截器 --> <ref bean="soapHeaderInterceptor"/> </jaxws:inInterceptors> </jaxws:endpoint> </beans>
头信息处理拦截器:
package com.tch.test.cxf.server.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.springframework.stereotype.Component;
import org.w3c.dom.NodeList;
/**
* 获取soap头信息
*/
@Component("soapHeaderInterceptor")
public class ReadSoapHeader extends AbstractPhaseInterceptor<SoapMessage> {
private SAAJInInterceptor saa = new SAAJInInterceptor();
public ReadSoapHeader() {
super(Phase.PRE_PROTOCOL);
// super(Phase.USER_LOGICAL);
getAfter().add(SAAJInInterceptor.class.getName());
}
public void handleMessage(SoapMessage message) throws Fault {
// 获取request。
HttpServletRequest request = (HttpServletRequest) message
.get(AbstractHTTPDestination.HTTP_REQUEST);
System.out.println(request.getRequestURI());
System.out.println(request.getRequestURL());
SOAPMessage mess = message.getContent(SOAPMessage.class);
if (mess == null) {
saa.handleMessage(message);
mess = message.getContent(SOAPMessage.class);
}
SOAPHeader head = null;
try {
head = mess.getSOAPHeader();
} catch (SOAPException e) {
e.printStackTrace();
}
if (head == null) {
return;
}
try {
//读取自定义的节点
NodeList nodes = head.getElementsByTagName("tns:spId");
NodeList nodepass = head.getElementsByTagName("tns:spPassword");
boolean isVerifyPassed = false;
//获取节点值,简单认证
if (nodes.item(0).getTextContent().equals("wdw")) {
if (nodepass.item(0).getTextContent().equals("wdwsb")) {
isVerifyPassed = true;
System.out.println("认证成功");
}
}
if(! isVerifyPassed){//表明没有验证通过
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
} catch (Exception e) {
SOAPException soapExc = new SOAPException("认证错误");
throw new Fault(soapExc);
}
}
}
接下来是服务端发布的服务接口:
package com.tch.test.cxf.server.service;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
String sayHi(String text);
}
实现类:
package com.tch.test.cxf.server.service;
import javax.jws.WebService;
import org.springframework.stereotype.Component;
@Component("helloWorldWebService")
@WebService(endpointInterface = "com.tch.test.cxf.server.service.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
System.out.println("sayHi called , text : "+text);
return "Hello " + text;
}
}
哦了,然后启动项目,就发布web服务了。
访问以下看看是否成功:(cxf-server是我的项目名称)
http://localhost:8080/cxf-server/cxf/HelloWorld?wsdl
成功的话,就会看到下面的内容了:
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.server.cxf.test.tch.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloWorldImplService" targetNamespace="http://service.server.cxf.test.tch.com/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.server.cxf.test.tch.com/" elementFormDefault="unqualified" targetNamespace="http://service.server.cxf.test.tch.com/" version="1.0"> <xs:element name="sayHi" type="tns:sayHi"/> <xs:element name="sayHiResponse" type="tns:sayHiResponse"/> <xs:complexType name="sayHi"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHiResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="sayHiResponse"> <wsdl:part element="tns:sayHiResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHi"> <wsdl:part element="tns:sayHi" name="parameters"></wsdl:part> </wsdl:message> <wsdl:portType name="HelloWorld"> <wsdl:operation name="sayHi"> <wsdl:input message="tns:sayHi" name="sayHi"></wsdl:input> <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"></wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="sayHi"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHi"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHiResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="HelloWorldImplService"> <wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort"> <soap:address location="http://localhost:8080/cxf-server/cxf/HelloWorld"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
这样,发布服务就成功了。
接下来是调用服务,也就是服务消费端:(我的消费端项目名称是cxf-client)
同样的,在applicationContext.xml里面引入单独的CXF配置文件cxf-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 启动扫描component功能 --> <context:component-scan base-package="com.tch.test.cxf.server" /> <import resource="cxf-servlet.xml"/> </beans>
cxf-servlet.xml的内容:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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="helloClient" serviceClass="com.tch.test.cxf.server.service.HelloWorld" address="http://localhost:8080/cxf-server/cxf/HelloWorld"> <jaxws:outInterceptors> <!-- 添加头信息的拦截器 --> <ref bean="addSoapHeaderInterceptor"/> </jaxws:outInterceptors> </jaxws:client> </beans>
添加头信息的拦截器:
package com.tch.test.cxf.server.interceptor;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* 在发送消息前,封装Soap Header 信息
*/
@Component("addSoapHeaderInterceptor")
public class AddSoapHeader extends AbstractSoapInterceptor {
private static String nameURI="http://127.0.0.1:8080/cxfTest/ws/HelloWorld";
public AddSoapHeader(){
super(Phase.WRITE);
}
public void handleMessage(SoapMessage message) throws Fault {
String spPassword="wdwsb";
String spName="wdw";
QName qname=new QName("RequestSOAPHeader");
Document doc=DOMUtils.createDocument();
//自定义节点
Element spId=doc.createElement("tns:spId");
spId.setTextContent(spName);
//自定义节点
Element spPass=doc.createElement("tns:spPassword");
spPass.setTextContent(spPassword);
Element root=doc.createElementNS(nameURI, "tns:RequestSOAPHeader");
root.appendChild(spId);
root.appendChild(spPass);
SoapHeader head=new SoapHeader(qname,root);
List<Header> headers=message.getHeaders();
headers.add(head);
System.out.println(">>>>>添加header<<<<<<<");
}
}
其中的接口跟cxf-server是一样的:
package com.tch.test.cxf.server.service;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
String sayHi(String text);
}
接下来我们测试一下调用是否成功:
package com.tch.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tch.test.cxf.server.service.HelloWorld;
public class T1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // your Spring ApplicationContext
HelloWorld client = (HelloWorld) context.getBean("helloClient");
System.out.println(client.sayHi("this is cxf demo"));
}
}
如果成功就可以看到输出了 Hello this is cxf demo 啦!如果修改一下AddSoapHeader里面的头信息内容,就会发现验证失败,从而达到验证账号密码的效果。。。