使用Maven 插件 cxf-codegen-plugin生成WebService測試程序


WebService的測試程序開發
CXF 中包含了一個 Maven 插件 cxf-codegen-plugin,能夠將 Wsdl 文件動態生成 webservice 本地類。下面針對Apace cxf 進行介紹如何配置,以及webservice中的幾種常見安全驗證方式。

Apache CXF簡介
Apache CXF = Celtix + XFire。Apache CXF 是一個開源的 Services 框架,CXF 利用 Frontend 編程 API 來構建和開發 Web Services , 支持 SOAP, XML/HTTP, RESTful HTTP, 和 CORBA ,並且可以在多種協議上運行,如HTTP, JMS 和 JBI.

官方地址:http://cxf.apache.org/

將WSDL文件轉化為Java代碼
CXF 中包含了一個 Maven 插件 cxf-codegen-plugin,能夠將 Wsdl 文件動態生成 webservice 本地類。 具體方法:在eclipse中建立maven項目,然后將pom中增加配置如下,然后運行mvn run,mvn install, mvn test等,即可生成代碼。 
詳細的pom.xml配置文件見最下方附注。

Maven 配置
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>http://172.0.0.1:8080/myService.wsdl</wsdl>
</wsdlOption>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/myService.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
使用上述maven插件,代碼會自動生成客戶端,其名稱類似於class ServiceName_ServicePort_Client,不過自動生成的客戶端代碼比較繁瑣,不便於維護,建議自己重新建立自己的測試用例。copy艷超的代碼如下:

@Test
public void blurNameTest(){
//實例化接口
CompanyRemote companyRemoteClient = new CompanyRemoteImplService().
//調用接口中的方法 getCompanyRemoteImplPort();
companyList = companyRemoteClient.getAllCompanysByBlurName("百度");

System.out.println(companyList.size());
}
WebService客戶端的安全認證
WebService客戶端與服務器端進行通信時,經常需要在soap文件中增加安全認證信息。在我的項目中,涉及到了2種安全認證方式:

1. 在soap文件的header中增加用戶名和密碼校驗
<soap:Envelope>
<soapenv:Header>
<wsse:Security ...>
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>test</wsse:Username>
<wsse:Password Type=".."...>123456</wsse:Password>
<wsse:Nonce EncodingType="...">4AJ7sPA8NRQ74faqignO3g==</wsse:Nonce>
<wsu:Created>2013-06-20T12:33:05.001Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

<soapenv:Body>
...
</soapenv:Body>
</soap:Envelope>
方法為建立一個攔截器

import org.apache.ws.security.WSPasswordCallback;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

/**
* Created with IntelliJ IDEA.
* User: shenyanchao
* Date: 5/15/13
* Time: 2:00 PM
*/
public class WsClientAuthHandler implements CallbackHandler {


public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
pc.setIdentifier("test");
pc.setPassword("123456");// ▲【這里必須設置密碼】▲
}
}
}
然后在客戶端中添加該攔截器

FeeFinanceService_Service server=new FeeFinanceService_Service();
String username = "test";//服務器端分配的用戶名
String password = "123456";//服務器端分配的密碼
FeeFinanceService port = server.getFeeFinanceServicePort();

Client client = ClientProxy.getClient(port);

Map<String, Object> props = new HashMap<String, Object>();

props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.USER, "cxfclient");
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, WsClientAuthHandler.class.getName());

WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(props);

client.getOutInterceptors().add(wss4jOut);

List<JtReq> reqlist = new ArrayList<JtReq>();
JtReq req = new JtReq();
req.setBusinessNumb("T");
2. 安全驗證在soap中插入,但是實際發送soap文件時會出現在html的頭文件中
POST /cmssoap/ws/fee_biz_service HTTP/1.1[\r][\n]
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction:
Authorization: Basic dGVzdDoxMjM0NTY=
Content-Length: 1475
Host: 10.237.4.242:8900

<soap:Envelope>
...
</soap:Envelope>
該程序,可以直接在函數中增加授權驗證

public void testInsert() throws ValidationException_Exception {

String username = "test";//服務器端分配的用戶名
String password = "123456";//服務器端分配的密碼

Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("test",
"123456".toCharArray());
}
});



FeeBizService_Service server=new FeeBizService_Service();

FeeBizService port = server.getFeeBizServicePort();


BindingProvider bp = (BindingProvider)port;

Map<String,Object> context = bp.getRequestContext();

context.put(BindingProvider.USERNAME_PROPERTY, username);
context.put(BindingProvider.PASSWORD_PROPERTY, password);



List<Fee> fees = new ArrayList<Fee>();

String str = port.sendFee(fees);
3. 在soap的header中直接增加用戶名和密碼
<soap:Envelope>
<soapenv:Header>
<wsse:Username>youthflies</wsse:Username>
<wsse:Password>youthflies</wsse:Password>
</soapenv:Header>

<soapenv:Body>
...
</soapenv:Body>
</soap:Envelope>
建立攔截器

/**
* @author youthflies
* 自定義的soap攔截器,用來添加header信息
*/
public class SoapHeaderInterceptor extends AbstractSoapInterceptor
{
public SoapHeaderInterceptor()
{
super(Phase.WRITE);
}

@Override
public void handleMessage(SoapMessage message) throws Fault
{
// TODO Auto-generated method stub
List headers=message.getHeaders();
headers.add(getHeader("username", "youthflies"));
headers.add(getHeader("password", "youthflies"));
}

//http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
private Header getHeader(String key, String value)
{
QName qName=new QName("http://webservice.webxml.com.cn/", key);

Document document=DOMUtils.createDocument();
Element element=document.createElementNS("http://webservice.webxml.com.cn/", key);
element.setTextContent(value);

SoapHeader header=new SoapHeader(qName, element);
return(header);
}

}
case中,添加攔截器:

//實例化接口實現類
MobileCodeWS mobileCodeWS = new MobileCodeWS();
//實例化接口
MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getMobileCodeWSSoap();

Client client = ClientProxy.getClient(mobileCodeWSSoap);
client.getOutInterceptors().add(new SoapHeaderInterceptor());

//調用接口中的方法
System.out.println(mobileCodeWSSoap.getMobileCodeInfo("13898767654", ""));
附錄一:
SVN上生成webservice測試文件的代碼路徑:(請忽略SVN地址,外面的人沒法用)

https://xxx.xxx.xxx/myspace/iteqa/InterfaceTest/cxf4ws
生成的代碼會在src/main/java路徑下面,而自己的測試代碼可以放到src/test下面,提交到SVN時,只提交src/test下的文件即可。

完整的pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.yourGroupId</groupId>
<artifactId>yourArtifactId</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<cxf.version>2.7.3</cxf.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
</dependency>
<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-ws-security</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.10</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-bindings-soap</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<executable>javac</executable>
<compilerVersion>1.6</compilerVersion>
<fork>true</fork>
<verbose>true</verbose>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>

<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.sourceDirectory}</sourceRoot>
<defaultOptions>
<extraargs>
<extraarg>-impl</extraarg>
<extraarg>-verbose</extraarg>
<extraarg>-validate</extraarg>
<!--<extraarg>-client</extraarg>-->
</extraargs>
</defaultOptions>
<wsdlOptions>
<!--<wsdlOption>
<wsdl>http://itebeta.xxx.com:8102/webservice/CompanyService?wsdl</wsdl>
</wsdlOption>
<wsdlOption>
<wsdl>http://itebeta.xxx.com:8102/webservice/CompanyServiceN?wsdl</wsdl>
</wsdlOption>
<wsdlOption>
<wsdl>http://itebeta.xxx.com:8102/webservice/UserServiceN?wsdl</wsdl>
</wsdlOption>-->
<wsdlOption>
<wsdl>http://xxx.xxx.4.242:8900/cmssoap/ws/fee_finance_service?wsdl</wsdl>
<extraargs>
<!--<extraarg>-exsh</extraarg>
<extraarg>true</extraarg>-->
<!--<extraarg>-all</extraarg>-->
</extraargs>
</wsdlOption>

</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>

</plugin>

</plugins>

<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.cxf
</groupId>
<artifactId>
cxf-codegen-plugin
</artifactId>
<versionRange>
[2.1.4,)
</versionRange>
<goals>
<goal>wsdl2java</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM