1. cxf简介

  Web Services 的一种实现方式。

  Apache CXF = Celtix + XFire,后更名为 Apache CXF ,简称为 CXF。

  CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。

2. JAX-WS

  JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA API。

  在 JAX-WS中,一个远程调用可以转换为一个基于XML的协议例如SOAP,在使用JAX-WS过程中,*开发者不需要编写任何生成和处理SOAP消息的代码*。JAX-WS的运行时实现会将这些API的调用转换成为对应的SOAP消息。

  * 在服务器端,用户只需要通过Java语言定义远程调用所需要实现的接口SEI(service endpoint interface),并提供相关的实现,通过调用JAX-WS的服务发布接口就可以将其发布为WebService接口。(发布服务  详见5.1)

  * 在客户端,用户可以通过JAX-WS的API创建一个代理(用本地对象来替代远程的服务)来实现对于远程服务器端的调用。(创建代理  详见5.2)

  JAX-WS 也提供了一组针对底层消息进行操作的API调用,你可以通过Dispatch 直接使用SOAP消息或XML消息发送请求或者使用Provider处理SOAP或XML消息。

3. cxf特点

  部署灵活、支持多种编程语言、多种传输方式。

4. 代码生成

  Java to WSDL;

  WSDL to Java;

  XSD to WSDL;

  WSDL to XML;

  WSDL to SOAP;

  WSDL to Service;

  

5. 实践

  5.1 服务器端

  Spring配置文件 cxf.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd"> <!-- cxf webservice -->
<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"/>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outFaultInterceptors>
<cxf:inFaultInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inFaultInterceptors>
</cxf:bus>
<bean id="serverPasswordCallback" class="util.web.ServerPasswordCallback" />
<bean id="authentication_server" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="FHDServer" />
<entry key="passwordCallbackRef">
<ref bean="serverPasswordCallback" />
</entry>
</map>
</constructor-arg>
</bean>
<!-- 注意下面的address,这里的address的名称就是访问的WebService的name -->
<!-- 外协完工登记 -->
<bean id="mesTaskServiceImpl" class="com.outsideasy.ws.mes.wxdata.MesTaskServiceImpl">
</bean>
<jaxws:server id="mesTaskServiceInter" serviceClass="com.outsideasy.ws.mes.wxdata.MesTaskServiceInter" address="/wxdata/mesTask"> <!-- 这里是发布的地址 -->
<jaxws:serviceBean>
<ref bean="mesTaskServiceImpl"/>
</jaxws:serviceBean>
<jaxws:inInterceptors>
<ref bean="authentication_server"></ref>
</jaxws:inInterceptors>
</jaxws:server>
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
</beans>

  ServerPasswordCallback.java (身份认证的callback,接收客户端的callback对象,获取认证信息进行验证)

package util.web;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.servlet.http.HttpServletRequest; import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.staxutils.W3CDOMStreamWriter;
import org.apache.log4j.Logger;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.RequestData;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import common.sysmodule.model.WsIdentity;
import common.sysmodule.service.WsIdentityService; public class ServerPasswordCallback implements CallbackHandler {
@Autowired
private WsIdentityService wsIdentityService;
protected static Logger logger = Logger.getLogger("service"); public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; //获取客户端Handler中传递过来的callback对象
String identify = pc.getIdentifier(); //获取账户信息 //身份验证
List<WsIdentity> list=wsIdentityService.getEnabledIdentity(identify); //通过账户在服务端表中查询账户信息,进行认证
if (list!=null && list.size()>0 && list.get(0).getIdentify().equals(identify)) {
pc.setPassword(list.get(0).getPsw());//验证用户名后,在设置密码就可以自动验证
} else {
throw new SecurityException("验证失败");
} } }

  MesTaskServiceInter.java (服务端申明接口)

package com.outsideasy.ws.mes.wxdata;

import javax.jws.WebService;

import com.outsideasy.ws.mes.wxdata.model.AttachedFileWithParams;
import com.outsideasy.ws.mes.wxdata.model.TaskRandomCheckAndFileDetails; @WebService //这里的申明是必需的*
public interface MesTaskServiceInter { /**
* @Description: 新增 发送者的 平台任务单 以及关联的工段 工序 bom材料。
* @param json格式的 信息主体 TaskAndGX,该对象包含了 任务单信息,工序 ,工段和bom材料信息
* @return json格式的 CXFResponse<PfTask>
* 如果success=true,新增成功,并返回PfTask对象;
* 如果success=false,新增失败,并返回失败信息errorMessage;
*/
public String addMesTaskAndTaskGx(String jsonobj);
/**
* @Description: 根据发送者的任务单号获取工段产量
* @param rwdh
* @return json格式的 CXFResponse<PfTaskOutput>
* 如果success=true,新增成功,并返回List<PfTaskOutput>;
* 如果success=false,新增失败,并返回失败信息errorMessage;
*/
public String getPfTaskOutputList(String rwdh);
}

  MesTaskServiceImpl.java

package com.outsideasy.ws.mes.wxdata;

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 javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.WebServiceContext;import com.outsideasy.ws.common.vo.CXFResponse;
import com.outsideasy.ws.mes.wxdata.model.AttachedFileWithParams;
import com.outsideasy.ws.mes.wxdata.model.TaskCheckAndUnquDetails;
import com.outsideasy.ws.mes.wxdata.model.TaskRandomCheckAndFileDetails;
import common.sysmodule.model.WsIdentity;
import common.sysmodule.service.WsIdentityService; @WebService //必需申明*
@SOAPBinding(style = Style.RPC) //必需申明*
public class MesTaskServiceImpl implements MesTaskServiceInter {
@Autowired
private MesTaskService mesTaskService;
@Resource
private WebServiceContext context;
@Autowired
private WsIdentityService wsIdentityService;
@Autowired
private TaskAllCheckService taskAllCheckService;
@Autowired
private TaskAllcheckUnqudetailsService taskAllcheckUnqudetailsService;
@Autowired
private TaskRandomCheckService taskRandomCheckService; public String getPfTaskOutputList(String rwdh){
Map<String,Object> params2=new HashMap<String,Object>();
params2.put("rwdh", rwdh);
params2.put("send_company", getsendInfo().getCompany_id());
List<PfTaskOutput> list=mesTaskService.getPfTaskOutputList(params2);
CXFResponse<PfTaskOutput> res=new CXFResponse<PfTaskOutput>();
if(list!=null && list.size()>0){
res.setSuccess(Const.SOAP_TRUE);
res.setList(list);
}else{
res.setSuccess(Const.SOAP_FALSE);
res.setErrorMessage("同步失败,生产方未在平台中录入产量");
}
return MyJsonUtil.obj2string(res);
} public String addMesTaskAndTaskGx(String jsonobj) {
int company_id=getsendInfo().getCompany_id();
TaskAndGX mtAndGx=MyJsonUtil.str2obj(jsonobj, TaskAndGX.class);
CXFResponse<PfTask> res=new CXFResponse<PfTask>();
res.setSuccess(Const.SOAP_TRUE);
if(mtAndGx.getTask()==null){
res.setErroeResponseInfo("发送失败,发送的任务单为空");
}else if(mtAndGx.getGxlist()==null || (mtAndGx.getGxlist()!=null && mtAndGx.getGxlist().size()==0)){
res.setErroeResponseInfo("发送失败,发送的工序为空");
}else if(mtAndGx.getBomlist()==null || (mtAndGx.getBomlist()!=null && mtAndGx.getBomlist().size()==0)){
res.setErroeResponseInfo("发送失败,发送的bom材料为空");
}else{
mesTaskService.addMesTaskAndTaskGx(res,company_id,mtAndGx);
}
return MyJsonUtil.obj2string(res);
} }

  5.2 客户端(创建代理)

    Spring 配置文件 cxf.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd"> <context:property-placeholder location="classpath:sysconfig/publishInfo.properties" /> <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"/>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref bean="loggingOutInterceptor"/>
</cxf:outFaultInterceptors>
<cxf:inFaultInterceptors>
<ref bean="loggingInInterceptor"/>
</cxf:inFaultInterceptors>
</cxf:bus>
<bean id="clientPasswordCallback" class="erp.util.web.ClientPasswordCallback"/>
<bean id="authentication_client" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="FHDClient" />
<entry key="passwordCallbackRef">
<ref bean="clientPasswordCallback" />
</entry>
</map>
</constructor-arg>
</bean>
<jaxws:client id="supplierInter" serviceClass="com.outsideasy.ws.erp.supplier.SupplierInter"
address="http://${cxf_url}/ws/erp/supplier/supplierInter">
<jaxws:handlers>
<bean class="erp.util.web.SessionLogicalHandler"></bean>
</jaxws:handlers>
<jaxws:outInterceptors>
<!-- <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> -->
<!-- SAAJInInterceptor只在CXF是2.0.X版本时或之前版本时才是必须的 -->
<!-- <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/> -->
<ref bean="authentication_client"></ref>
</jaxws:outInterceptors>
</jaxws:client>
<jaxws:client id="supplierAccessInter" serviceClass="com.outsideasy.ws.erp.supplier.SupplierAccessInter"
address="http://${cxf_url}/ws/erp/supplier/supplierAccessInter"> <!-- 访问地址 cxf_url = 192.168.1.101:8995 *-->
<jaxws:handlers>
<bean class="erp.util.web.SessionLogicalHandler"></bean>
</jaxws:handlers>
<jaxws:outInterceptors>
<!-- <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> -->
<!-- SAAJInInterceptor只在CXF是2.0.X版本时或之前版本时才是必须的 -->
<!-- <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/> -->
<ref bean="authentication_client"></ref>
</jaxws:outInterceptors>
</jaxws:client>
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
</beans>

  客户端callback对象  ClientPasswordCallback.java

package erp.util.web;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class ClientPasswordCallback implements CallbackHandler { @Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword("topsun"); // 验证密码
pc.setIdentifier("admin"); // 验证账号
} }

  SessionLogicalHandler.java

package erp.util.web;

import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext; import org.apache.cxf.jaxws.handler.logical.LogicalMessageContextImpl; public class SessionLogicalHandler implements LogicalHandler<LogicalMessageContext>{ public SessionLogicalHandler() {
super();
} public static List<String> http_headers_cookie=null;//静态 所有的 SessionLogicalHandler 共享 一个 cookie
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public boolean handleMessage(LogicalMessageContext context) {
// TODO Auto-generated method stub
// javax.xml.ws.handler.MessageContext.Scope s=
// context.getScope(MessageContext.HTTP_REQUEST_HEADERS);
// Set-Cookie=[JSESSIONID=48B10A68BB05F69F8ED82A33F566C5D8; Path=/myapp;
// HttpOnly] LogicalMessageContextImpl c = (LogicalMessageContextImpl) context; if (c.get(MessageContext.HTTP_RESPONSE_HEADERS) != null) {//response 时 记录服务端返回的session信息
Map<String, List> header = (Map<String, List>) c.get(MessageContext.HTTP_RESPONSE_HEADERS);
List<String> ls = header.get("Set-Cookie");//获取header 中cookie的信息
if(ls!=null){
SessionLogicalHandler.SetHttp_headers_cookie(ls);
}
}else if(c.get( MessageContext.HTTP_REQUEST_HEADERS)!=null && http_headers_cookie!=null){//request 请求的时候 把cookie信息设置进去
Map<String, List> header = (Map<String, List>) c.get( MessageContext.HTTP_REQUEST_HEADERS);
header.put("cookie", http_headers_cookie);
}else if(c.get( MessageContext.HTTP_REQUEST_HEADERS)==null && http_headers_cookie!=null){//request 请求的时候 把cookie信息设置进去
Map<String, List> header = new HashMap<String, List>();
header.put("cookie", http_headers_cookie);
c.put(MessageContext.HTTP_REQUEST_HEADERS, header);
}
return true;
} @Override
public boolean handleFault(LogicalMessageContext context) {
// TODO Auto-generated method stub
return false;
} @Override
public void close(MessageContext context) {
// TODO Auto-generated method stub }
private synchronized static void SetHttp_headers_cookie(List<String> ls){
if(http_headers_cookie==null){
http_headers_cookie=ls;
}
}
}

  SupplierAccessInter.java (客户端的代理接口,客户端直接调用此接口即可访问ws服务端)

package com.outsideasy.ws.erp.supplier;

import javax.jws.WebService;

@WebService //必需申明 *
public interface SupplierAccessInter {
/**获取历史审核记录
* 参数:json格式的map
* 包含 company_id 公司编号
* 返回值:json 格式CXFResponse
* 2016-5-19*/
public String getPfAuthcationInfoList(String jsonmap);
/**供应商变更
*参数:json格式的map
*返回值:String
*2016-5-17
**/
String updateSupplierChangeStateByWS(String jsonmap);
}

6.总结

  6.1 cxf 是 WebService的实现方式,符合ws规范

  6.2 利用 jax-ws 可以轻松发布一个WebService服务

  6.3 此项目是利用 cxf + jax-ws 发布的一个WebService服务

  6.4 主要使用的是 代理设计模式

7. 项目支持(仅作为个人笔记使用)

  ws + erp

参考资料:

  1. http://baike.baidu.com/link?url=WOTPK-J7UxJuXZ6hMr8OPYDMItaEHwva8wzOEUSM3wKXF5KgBBXRM8VfgA-kUE_RrAoNMYFipZY0VK_kCtpw8_

Web Service(二):cxf 实现的更多相关文章

  1. Web Service学习-CXF开发Web Service的权限控制(二)

    Web Service怎样进行权限控制? 解决思路:server端要求input消息总是携带实username.password信息,假设没实username和password信息.直接拒绝调用 解决 ...

  2. Web Service学习-CXF开发Web Service实例demo(一)

    Web Service是什么? Web Service不是框架.更甚至不是一种技术. 而是一种跨平台,跨语言的规范 Web Service解决什么问题: 为了解决不同平台,不同语言所编写的应用之间怎样 ...

  3. CXF实战之在Tomcat中公布Web Service(二)

    服务接口及实现类请參考WebService框架CXF实战(一) 创建Maven Web项目,在pom.xml中加入CXF和Spring Web的引用,因为CXFServlet须要Spring Web的 ...

  4. 【转】基于CXF Java 搭建Web Service (Restful Web Service与基于SOAP的Web Service混合方案)

    转载:http://www.cnblogs.com/windwithlife/archive/2013/03/03/2942157.html 一,选择一个合适的,Web开发环境: 我选择的是Eclip ...

  5. Apache CXF实战之四 构建RESTful Web Service

    Apache CXF实战之一 Hello World Web Service Apache CXF实战之二 集成Sping与Web容器 Apache CXF实战之三 传输Java对象 这篇文章介绍一下 ...

  6. Apache CXF实现Web Service(5)—— GZIP使用

    Apache CXF实现Web Service(5)-- GZIP使用 参考来源: CXF WebService整合Spring Apache CXF实现Web Service(1)--不借助重量级W ...

  7. Web Service学习之一:Web Service原理

    一.定义 Web Service 不是框架也不是技术 而是解决远程调用.跨平台调用.跨语言调用问题的一种规范. 二.应用1.同一个公司新.旧系统的整合:比如CRM系统与OA.客服系统相互调用2.不同公 ...

  8. Web Service简单入门示例

    Web Service简单入门示例     我们一般实现Web Service的方法有非常多种.当中我主要使用了CXF Apache插件和Axis 2两种. Web Service是应用服务商为了解决 ...

  9. Web Service(下)

    4.WSDL文档 <?xml version='1.0' encoding='UTF-8'?> <wsdl:definitions xmlns:xsd="http://ww ...

  10. 《基于 Web Service 的学分制教务管理系统的研究与实现》论文笔记(十一)

    标题:基于 Web Service 的学分制教务管理系统的研究与实现 一.基本内容 时间:2014 来源:苏州大学 关键词:: 教务管理系统 学分制 Web Service 二.研究内容 1.教务管理 ...

随机推荐

  1. solr与mysql数据同步的方案

    1.使用activeMQ http://blog.csdn.net/zhou2s_101216/article/details/77855413 2.通过配置实现定时同步 http://blog.cs ...

  2. Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer)

    Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.映射字节缓冲区 1>.什么是虚拟内存 答:虚拟内 ...

  3. xen list_domains stat 解析

    XenServer中可以使用list_domains命令来查看所有VM以及Dom0的运行状态以及简单的资源消耗,如下: [root@xenserver ~]# list_domains id | uu ...

  4. .net MVC框架里怎么写控件

    .net的MVC框架如果选择了Razor引擎就需要自己来写控件了,这里列出了一些简单的控件的书写方法 @*这是TextBox控件的写法*@ @Html.TextBox("textbox1&q ...

  5. SHELL (2) —— Shell变量的核心基础知识和实践

    摘自:Oldboy Linux运维——SHELL编程实战 Shell变量:用一个固定的字符串(也可能是字符.数字等的组合)代替更多.更复杂的内容,该内容里可能还会包含变量.路径.字符串等其它的内容. ...

  6. 面板支持单个,多个元素的jQuery图片轮播插件

    一.先附上demo <!doctype html> <html> <head> <meta charset="utf-8"> < ...

  7. Oracle 基本操作符

    1.一般操作符 (1)!= 不等于 select empno,ename,job from scott.emp where job!='manager' (2)^= 不等于 select empno, ...

  8. Vue's Demo

    *.vue=<template> </template>+<style></style>+<script></script> s ...

  9. 关于Hadoop未授权访问可导致数据泄露通知

    尊敬的腾讯云客户: 您好!近日,外部媒体报道全球Hadoop服务器因配置不安全导致海量数据泄露,涉及使用Hadoop分布式文件系统(HDFS)的近4500台服务器,数据量高达5120 TB (5.12 ...

  10. Project Euler Problem1

    Multiples of 3 and 5 Problem 1 If we list all the natural numbers below 10 that are multiples of 3 o ...