Web Service(二):cxf 实现

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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsdhttp://cxf.apache.org/jaxwshttp://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 {@Autowiredprivate 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 {@Autowiredprivate MesTaskService mesTaskService;@Resourceprivate WebServiceContext context;@Autowiredprivate WsIdentityService wsIdentityService;@Autowiredprivate TaskAllCheckService taskAllCheckService;@Autowiredprivate TaskAllcheckUnqudetailsService taskAllcheckUnqudetailsService;    @Autowiredprivate 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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsdhttp://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 {@Overridepublic 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" })@Overridepublic 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;}@Overridepublic boolean handleFault(LogicalMessageContext context) {// TODO Auto-generated method stubreturn false;}@Overridepublic 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_

 

转载于:https://www.cnblogs.com/springlight/p/6483318.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:https://dhexx.cn/news/show-18686.html

如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网进行投诉反馈,一经查实,立即删除!


相关文章:

  • nand ECC 算法记录
  • 简单易懂的排序算法演示
  • 【动态规划】最大子段和问题,最大子矩阵和问题,最大m子段和问题
  • OpenCV学习:Windows+VS2010+OpenCV配置
  • java集合系列——Map之TreeMap介绍(九)
  • SQL Sever数据库的基本操作和它的建立
  • PHP查看IP时候能ping通
  • 导出数据库表为world文档说明,以及PowerDesigner导出表结构pdm设计文档
  • 201521123059 《Java程序设计》第三周学习总结
  • git如何回滚远程仓库
  • Mysql5.7双主安装与使用
  • 修饰符的探讨
  • 中学生心理辅导原则
  • 配置springMVC
  • .net中对象序列化技术
  • 项目过程总结 和某个字段的更新
  • 3.14上午
  • Centos7搭建pptp一键安装脚本
  • Linux基础实操二
  • JSONP简单例子
  • DeadObjectException
  • 个人学习进度(第四周)
  • sping加载bean都发生了些什么
  • 泛型接口
  • 安卓android eclipse运行提示no compatible targets were found
  • Unity3d 调用C++写的DLL
  • servlet 与 tomcat版本不匹配的问题
  • 通读cheerio API-网络爬虫
  • 指针和二级指针
  • HTML(超文本语言)
  • 软件测试--必应
  • openssh常用命令记录
  • 百度API从经纬度坐标到地址的转换服务
  • Android xUtils3.0使用手册(二) - 数据库操作
  • 浙江工业大学校赛 XiaoWei的战斗力
  • R语言中的字符串处理函数
  • IOS 线程的总结(及cell的图片下载)
  • Spring结合马士兵视频的学习经验
  • 初学 python 之 HAproxy配置文件操作
  • (一)Quartz2.2.1 简单例子
  • 继承中的盲点,成员或者析构函数,成员函数中为什么有时候需要定义,有时候不需要呢,(已解决)...
  • JavaScript Array(数组)对象
  • Linux CentOS 7 JDK7 Tomcat7 的配置
  • 网络安全——Base64编码、MD5、SHA1-SHA512、HMAC(SHA1-SHA512)哈希
  • python基础(初识Python)
  • 3.27上午
  • Canvas坐标轴中的Y轴距离是X轴的两倍
  • Java Map 接口
  • bzoj 2969: 矩形粉刷 概率期望
  • [bzoj2190][SDOI2008]仪仗队