【www.bbyears.com--apache】
先在Eclipse中新建一个Java Project
(可以不是WTP的Dynamic Web Project)
选择Java Project
再看pom.xml
我们使用cxf 3.1.4版本,
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
cxf-test-standalone-ws-helloworld
cxf-rt-frontend-jaxws
cxf-rt-transports-http
cxf-rt-transports-http-jetty
cxf-rt-ws-security
cxf-rt-ws-policy
jsr311-api
slf4j-api
slf4j-simple
commons-httpclient
commons-io
junit
maven-jetty-plugin
maven-compiler-plugin
另外有例子给出的slf4j是slf4j-jdk14 (http://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14)的版本,如果用jdk5以上的同学可以将其替换成slf4j-simple实现。
CXF Web Service (Annotation)实现,上代码
CXF支持两种方式发布一个web service,一种是Java Annotation(Bottom up),另外一种是先定义好wsdl和xsd schema然后通过工具生成(Top down),我们这里的例子先介绍Java Annotation。
首先我们需要定义一个web service接口类HelloWorld,并加上Annotation
package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public interface HelloWorld {
@WebMethod
@WebResult String sayHi(@WebParam String text);
}
在此我们先不介绍 @WebService、 @WebMethod、@WebResult还有@WebParam如何工作的。
然后我们需要用HelloWorldImpl来实现这个接口类,
package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services;
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String name) {
String msg = "Hello " + name + "!";
return msg;
}
}
发布一个Web Service
我们先用一个最简单的方式,使用javax.xml.ws.Endpoint来发布
package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.server;
import javax.xml.ws.Endpoint;
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorldImpl;
public class SimpleServer {
public static void main(String[] args) throws Exception {
System.out.println("Starting Server");
HelloWorldImpl implementor = new HelloWorldImpl();
String address = "http://localhost:9000/ws/HelloWorld";
Endpoint.publish(address, implementor);
}
}
注意:这里的address路径是大小写敏感的,如果发布成"http://localhost:9000/ws/helloWorld",而客户端使用/HelloWorld会找不到服务。
直接Run As..-> Java Application
我们可以在Eclipse中看到一个jetty服务正常运行
Starting Server
128 [main] INFO org.apache.cxf.service.factory.ReflectionServiceFactoryBean - Creating Service {http://services.helloworld.ws.standalone.cxftest.richaaaard.cnblog.com/}HelloWorldImplService from class com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld
487 [main] INFO org.apache.cxf.endpoint.ServerImpl - Setting the server's publish address to be http://localhost:9000/ws/HelloWorld
506 [main] INFO org.eclipse.jetty.server.Server - jetty-8.1.15.v20140411
554 [main] INFO org.eclipse.jetty.server.AbstractConnector - Started SelectChannelConnector@localhost:9000
此时,我们通过浏览器访问http://localhost:9000/ws/HelloWorld?WSDL
如何访问我们发布的这个服务呢?
我们利用jaxws中的JaxWsProxyFactoryBean来消费这个服务
package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.client;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld;
public class Client {
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(HelloWorld.class);
factory.setAddress("http://localhost:9000/ws/HelloWorld");
HelloWorld helloworld = (HelloWorld) factory.create();
String reply = helloworld.sayHi("HI");
System.out.println("Server said: " + reply);
System.exit(0);
}
}
同样右键选择Client.java,Run As.. ->Java Application,我们可以看到运行后台执行的日志最后成功返回“Server said: Hello HI!”
114 [main] INFO org.apache.cxf.service.factory.ReflectionServiceFactoryBean - Creating Service {http://services.helloworld.ws.standalone.cxftest.richaaaard.cnblog.com/}HelloWorldService from class com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld
531 [main] INFO org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld - Outbound Message
---------------------------
ID: 1
Address: http://localhost:9000/ws/HelloWorld
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload:
--------------------------------------
748 [main] INFO org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld - Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[258], content-type=[text/xml;charset=UTF-8], Server=[Jetty(8.1.15.v20140411)]}
Payload:
--------------------------------------
Server said: Hello HI!
上面Outbound Message和Inbound Message是我们加的两个Logging Interceptor输出的日志,关于Interceptor的原理和更多使用方式,会专题介绍。
这样就完成了一个Web Service的发布和消费
*服务端的扩展
除了用一个最简单的javax.xml.ws.Endpoint来发布CXF web service,我们还可以使用cxf-rt-frontend-jaxws.jar中的JaxWsServerFactoryBean来发布一个web service,它可以让我们更多的控制web service的行为,比如说加Logging Interceptor之类
package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.server;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld;
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorldImpl;
public class Server {
public static void main(String[] args) throws Exception {
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(HelloWorld.class);
HelloWorldImpl implementor = new HelloWorldImpl();
factory.setServiceBean(implementor);
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setAddress("http://localhost:9000/ws/HelloWorld");
factory.create();
System.out.println("Server start...");
Thread.sleep(60 * 1000);
System.out.println("Server exit...");
System.exit(0);
}
}
Web Service的CXF实现(Spring整合方式)
新建Java Web项目,采用maven管理jar包,本文章只是提供核心代码文件如下:
(1)maven的pom.xml
(2)cxf-base.xml
(3)cxf-bz-client.xml 客户端配置
(4)cxf-bz-server.xml服务端配置
(5)WSOrderService 业务接口定义
(6)WSOrderServiceImpl 业务接口实现
(7)BZClientHandler,BZServiceHandler 用户认证拦截
(8)web.xml 项目web配置
(9)demo.properties url和用户配置信息
备注:其中涉及spring相关配置文件未列出。
1) 主要核心pom.xml配置如下:
spring-aop
spring-asm
spring-beans
spring-context
spring-core
spring-expression
spring-jdbc
spring-orm
spring-tx
spring-web
spring-context-support
cxf-rt-frontend-jaxws
cxf-rt-transports-common
cxf-rt-core
cxf-rt-transports-http-jetty
(2)cxf-base.xml
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd">
(3)cxf-bz-client.xml
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
default-lazy-init="true">
(4)cxf-bz-server.xml
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
default-lazy-init="true">
(5)WSOrderService定义业务接口
package com.lshop.ws.server.bz.order.service;
import java.util.Date;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import com.lshop.ws.server.bz.order.bean.LvOrderDtoResposne;
@WebService(name = "WSOrderService")
@SOAPBinding(style=Style.RPC)
public interface WSOrderService {
/**
* 同步已经审核的订单到商务接口定义
* @Method: synAuditOrderToBZ
* @Description:
* @param startTime 审核开始时间
* @param endTime 审核结算时间
* @return OrderList
*/
public LvOrderDtoResposne synAuditOrderToBZ(
@WebParam(name = "startTime") String startTime,
@WebParam(name = "endTime") String endTime);
}
(6)WSOrderServiceImpl业务实现类
package com.lshop.ws.server.bz.order.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.jws.WebService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import com.gv.core.hibernate3.HibernateBaseDAO;
import com.gv.core.service.impl.BaseServiceImpl;
import com.gv.core.util.ObjectUtils;
import com.lshop.common.pojo.logic.LvOrderDetails;
import com.lshop.common.pojo.logic.LvOrderPackageDetails;
import com.lshop.common.util.DateUtils;
import com.lshop.ws.server.bz.order.bean.LvOrderDto;
import com.lshop.ws.server.bz.order.bean.LvOrderDtoResposne;
import com.lshop.ws.server.bz.order.bean.LvProductDto;
import com.lshop.ws.server.bz.order.bean.Result;
@Service("WSOrderService")
@WebService(endpointInterface = "com.lshop.ws.server.bz.order.service.WSOrderService")
public class WSOrderServiceImpl extends BaseServiceImpl implements WSOrderService {
@Resource
private HibernateBaseDAO dao;
private static final Log logger = LogFactory.getLog(WSOrderServiceImpl.class);
/**
* 同步已经审核的订单到商务接口定义
* @Method: synAuditOrderToBZ
* @Description:
* @param startTime 审核开始时间(查询范围起始时间,格式:yyyy-mm-dd HH:mm:ss)
* @param endTime 审核结束时间(查询范围结束时间,格式:yyyy-mm-dd HH:mm:ss)
* @return OrderList
*/
@Override
public LvOrderDtoResposne synAuditOrderToBZ(String startTime, String endTime) {
if(logger.isInfoEnabled()){
logger.info("*****WSOrderServiceImpl.synAuditOrderToBZ() method begin*****");
}
LvOrderDtoResposne lvOrderDtoResposne=new LvOrderDtoResposne();
List
//判断查询日期时间差
//根据审核时间查询已经审核订单集合
try {
if(ObjectUtils.isNotEmpty(startTime)&&ObjectUtils.isNotEmpty(endTime)){
String hql=" select DISTINCT ls.ord as ord from LvOrderLogs ls,LvOrder o " +
" where ls.ord=o.oid " +
" and o.isServiceAudit=1 " +
" and o.isFinanceAudit=1 " +
" and o.isdelete=0 " +
" and ls.createTime>=:startTime and ls.createTime <=:endTime ";
Map param=new HashMap();
param.put("startTime", DateUtils.convertToDateTime(startTime));
param.put("endTime", DateUtils.convertToDateTime(endTime));
List listTmp = dao.getMapListByHql(hql, param).getList();
if(ObjectUtils.isNotEmpty(listTmp)){
for (int i = 0; i < listTmp.size(); i++) {
Map map=(Map) listTmp.get(i);
//查询订单信息
LvOrderDto lvOrderDto=this.getOrderInfo(String.valueOf(map.get("ord")));
orderList.add(lvOrderDto);
}
}
}
lvOrderDtoResposne.setOrderList(orderList);
lvOrderDtoResposne.getResult().setStatus(Result.STATUS_SUCCEED);
lvOrderDtoResposne.getResult().setMessage("成功");
} catch (Exception e) {
lvOrderDtoResposne.getResult().setStatus(Result.STATUS_FAIL);
lvOrderDtoResposne.getResult().setMessage(e.getMessage());
e.printStackTrace();
}
if(logger.isInfoEnabled()){
logger.info("*****WSOrderServiceImpl.synAuditOrderToBZ() method end*****");
}
return lvOrderDtoResposne;
}
/**
*
* @Method: getOrderDetailsByOid
* @Description: 根据订单号查询订单详情及对应的产品信息
* @param oid 订单号
* @return List
*/
protected List
return null;
}
/**
*
* @Method: getOrderInfo
* @Description: 根据订单号查询订单
* @param oid 订单号
* @return List
*/
protected LvOrderDto getOrderInfo(String oid){
return null;
}
}
(7)BZClientHandler,BZServiceHandler用户认证拦截。
package com.lshop.ws.util;
import java.io.IOException;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;
public class BZClientHandler implements SOAPHandler
private String accountNum;
private String password;
public String getAccountNum() {
return accountNum;
}
public void setAccountNum(String accountNum) {
this.accountNum = accountNum;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
System.out.println("Server : handleMessage()......");
try{
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
//if no header, add one
if (soapHeader == null){
soapHeader = soapEnv.addHeader();
}
SOAPElement accountNumNode = soapHeader.addChildElement(new QName("http://service.webservice.datainterface.bz.gv.com/","accountNum"));
accountNumNode.setNodeValue("accountNum");
accountNumNode.setValue(accountNum);
SOAPElement passwordNode = soapHeader.addChildElement(new QName("http://service.webservice.datainterface.bz.gv.com/","password"));
passwordNode.setNodeValue("password");
passwordNode.setValue(password);
soapMsg.writeTo(System.out);
return true;
}catch(SOAPException e){
System.err.println(e);
}catch(IOException e){
System.err.println(e);
}
//continue other handler chain
return false;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()......");
return true;
}
@Override
public void close(MessageContext context) {
System.out.println("Server : close()......");
}
@Override
public Set
System.out.println("Server : getHeaders()......");
return null;
}
private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
try {
SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = soapBody.addFault();
soapFault.setFaultString(reason);
throw new SOAPFaultException(soapFault);
}
catch(SOAPException e) { }
}
}
(8)web.xml配置web servcie请求拦截url.
(9)demo.properties
bz.sys.url=http\://127.0.0.1\:8080
bz.ws.account=demo
bz.ws.password=demo400
配置完成可以通过下面的服务端url访问:
http://127.0.0.1:8080/ws/WSOrderService?wsdl
客户端先生成客户端java文件,在调用接口实现即可。