`
wufeng219219
  • 浏览: 4698 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

axis1.4 传递嵌套list的复杂对象

阅读更多
项目需要,发布webservice服务端,向客户端传递复杂对象。对象包含了list<>,反复研究了一下,发现webservice不能够直接传递list对象,必须转换成对象数组才能传递。javaBean:
package com.wensi.service.server;

import java.io.Serializable;

public class LoginResponse implements Serializable{
	private boolean flag;//操作员登录验证是否通过:true 验证通过  false 验证失败
	private OperatorBean operator;//登录成功后返回的操作员信息,登录失败返回null
	private AuthorityBean[] authorityArray;//登录成功后返回操作员的权限,登录失败返回null
	private String checkNum;//校验码
	
	public boolean isFlag() {
		return flag;
	}
	public void setFlag(boolean flag) {
		this.flag = flag;
	}
	public OperatorBean getOperator() {
		return operator;
	}
	public void setOperator(OperatorBean operator) {
		this.operator = operator;
	}
	public AuthorityBean[] getAuthorityArray() {
		return authorityArray;
	}
	public void setAuthorityArray(AuthorityBean[] authorityArray) {
		this.authorityArray = authorityArray;
	}
	public String getCheckNum() {
		return checkNum;
	}
	public void setCheckNum(String checkNum) {
		this.checkNum = checkNum;
	}
}

这是一个复杂的自定义对象,该对象嵌套了基本类型、自定义对象以及自定义对象数组。其余的对象我就不细说了,来看一下,axis1.4用来发布服务的wsdd文件:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>
 <handler type="java:com.wensi.service.server.BSHeaderHandler" name="BSHeaderHandler"/>
 <service name="ZNWService" provider="java:RPC">
 
  <requestFlow>  
       <handler type="BSHeaderHandler"/>  
  </requestFlow> 
 
  <parameter name="className" value="com.wensi.service.server.ZNWService"/>
  <parameter name="allowedMethods" value="*"/>
  <parameter name="scope" value="session"/>
  	
<!-- 这里定义了方法的参数以及返回值 --> 
 <operation name="login" returnType="ns:LoginResponse">
  	<parameter name="userName" type="tns:string"/>
  	<parameter name="password" type="tns:string"/>
  </operation>

<!-- 这里定义了自定义对象的映射 -->
  <typeMapping 
  	  qname="ns:OperatorBean"
  	  xmlns:ns="ZNWService"
  	  type="java:com.wensi.service.server.OperatorBean"
  	  deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"   
	  encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
	  serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
  /> 

   <typeMapping 
  	  qname="ns:AuthorityBean"
  	  xmlns:ns="ZNWService"
  	  type="java:com.wensi.service.server.AuthorityBean"
  	  deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"   
	  encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
	  serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
  /> 
	 
  <arrayMapping 
      qname="ns:ArrayOfAuthorityBean"
      xmlns:ns="ZNWService"
      type="java:com.wensi.service.server.AuthorityBean[]"
      innerType="ns:AuthorityBean"
      xmlns:ns2="ZNWService"
      deserializer="org.apache.axis.encoding.ser.ArrayDeserializerFactory"   
	  encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
	  serializer="org.apache.axis.encoding.ser.ArraySerializerFactory"
	  
 /> 
 
  <typeMapping 
  	  qname="ns:LoginResponse"
  	  xmlns:ns="ZNWService"
  	  type="java:com.wensi.service.server.LoginResponse"
  	  deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"   
	  encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
	  serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
  />  
  
   </service>
 <transport name="http">      
    <requestFlow>      
        <handler type="URLMapper"/>      
    </requestFlow>      
  </transport> 
</deployment>

注意:<transport name="http">     
    <requestFlow>     
        <handler type="URLMapper"/>     
    </requestFlow>     
  </transport>
如果没有该配置,将无法在浏览器中显示wsdl详细信息。

<handler type="java:com.wensi.service.server.BSHeaderHandler" name="BSHeaderHandler"/>

<requestFlow> 
       <handler type="BSHeaderHandler"/> 
</requestFlow>
是实现一个相当于拦截器的功能,客户端在调用服务端的接口之前,必须经过这个方法的处理。

在这里,我写了一个权限验证的拦截器,代码如下:
package com.wensi.service.server;

import org.apache.axis.AxisFault;   
import org.apache.axis.Message;   
import org.apache.axis.MessageContext;   
import org.apache.axis.handlers.BasicHandler;   
import javax.xml.soap.SOAPException;   
import javax.xml.soap.SOAPHeader;   
import org.apache.axis.message.SOAPHeaderElement;   
import org.apache.axis.message.SOAPEnvelope;   
import org.apache.axis.message.MessageElement;   

import com.wensi.common.Util;

import javax.xml.namespace.QName;   

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

@SuppressWarnings("unchecked")
public class BSHeaderHandler extends BasicHandler {   
    private static final long serialVersionUID = 1L; 
    private String operNum;//操作员编号
    private String checkNum;//校验码
    private String time;//访问接口的时间
    String endpoint = ServiceConstant.endpoint;//webservice的具体路径
    Map map = ServiceConstant.checkMap;//包含校验码信息的map
    
    // 在执行service前先处理handler   
    // invoke()会被自动调用,而且 SOAP 信息可以由 msgContext 取得   
    public void invoke(MessageContext msgContext) throws AxisFault {   
        boolean processedHeader = false;   
        try {   
            // 取得 Request 的 SOAP 信息   
            Message msg = msgContext.getRequestMessage();   
            SOAPEnvelope envelope = msg.getSOAPEnvelope();   
            SOAPHeader header = envelope.getHeader();   
            Iterator it = header.examineAllHeaderElements();   
            SOAPHeaderElement hel;   
            while (it.hasNext()) {   
                hel = (SOAPHeaderElement) it.next();   
                String headerName = hel.getNodeName();   
                if (headerName.equals("cp:MessageHeader")) {   
                    // 对于 mustUnderstand 设为 true 的 Header,必须   
                    // 利用下列的方式把它设为"已经处理",否则 service   
                    // 会回传 Did not understand "MustUnderstand"   
                    hel.setProcessed(true);   
                    checkUser(hel);   
                    processedHeader = true;   
                }   
            }   
        } catch (SOAPException e) {   
            throw new AxisFault("无法处理 SOAP Header.", e);   
        }   
        if (!processedHeader) {   
            throw new AxisFault("接收 SOAP Header 失败");   
        }   
    }   
    private void checkUser(SOAPHeaderElement hel) throws AxisFault { 
    	String current = Util.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss");//当前时间字符串
        MessageElement element1 = hel.getChildElement(new QName(   
        		endpoint, "isLogin"));   
      
        MessageElement element2 = hel.getChildElement(new QName(   
        		endpoint, "operNum"));
        
        MessageElement element3 = hel.getChildElement(new QName(   
        		endpoint, "checkNum"));   
   
        MessageElement element4 = hel.getChildElement(new QName(   
        		endpoint, "time"));   
        
        
        //用户访问的不是登录接口,则进行校验码验证
        if(null == element1 && null != element2 && null != element3 && null != element4){
        	operNum = element2.getValue();
        	checkNum = element3.getValue();
        	time = element4.getValue();
        	Boolean flag1 = false;
        	if(map.keySet().contains(operNum)){
        		CheckNumBean check = (CheckNumBean) map.get(operNum);
        		System.out.println(check.getCheckNum());
        		if(check.getCheckNum().equals(checkNum)){
        			flag1 = true;
        		}
        	}
        		
        	Boolean flag2 = false;
        	if(flag1){
        		//计算服务器时间与soapHeader时间戳之间的差值
        		Long between = countTime(time,current);
        		//时差在一个小时之内,算正常
        		if(Math.abs(between) < 3600L){
        			flag2 = true;
        		}
        	}
        	
        	if(!(flag1 && flag2)){
        		throw new AxisFault("校验失败");
        	}
        	
        	//更新map内信息
        	CheckNumBean check = (CheckNumBean) map.get(operNum);
        	check.setLastTime(check.getCurrentTime());
        	check.setCurrentTime(current);	
        } else if(null == element1 && (null == element2 || null == element3 || null == element4)){
        	throw new AxisFault("校验失败");
        }
    } 
    
    //计算时间差
    private Long countTime(String str1, String str2){
	  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
	  Date begin = null;
	  Date end = null;
	try {
		begin = df.parse(str1);
		end = df.parse(str2);
	} catch (ParseException e) {
		e.printStackTrace();
	}   
	  long between=(end.getTime()-begin.getTime())/1000;//除以1000是为了转换成秒 
	  return between;
    }
}  

由于客户端是手持机,而这边的客户端是java ssh架构,所以存储用户信息,正能依靠内存来完成。
客户端调用的时候,需要向soapHeader放验证信息。
客户端代码如下:
package com.wensi.service.client;


import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Date;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.encoding.XMLType;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.ser.ArrayDeserializerFactory;
import org.apache.axis.encoding.ser.ArraySerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.message.SOAPHeaderElement;

import com.wensi.common.Util;
import com.wensi.service.server.AccountCustomerBean;
import com.wensi.service.server.AccountFlag;
import com.wensi.service.server.AccountResponse;
import com.wensi.service.server.AuthorityBean;
import com.wensi.service.server.LoginResponse;
import com.wensi.service.server.OperatorBean;
import com.wensi.service.server.ServiceConstant;


public class ZNWServiceClient {
	String endpoint = ServiceConstant.endpoint;//webservice的具体路径
	Service service = new Service();//创建service实例
	
	public LoginResponse login(String userName,String password) throws Exception{
		SOAPHeaderElement cpHeader = new SOAPHeaderElement(endpoint,"MessageHeader");
		cpHeader.setPrefix("cp");
		cpHeader.setMustUnderstand(true);   
		SOAPElement ele = null;
		ele = cpHeader.addChildElement("isLogin");
		ele.addTextNode("true");
		
		//创建call实例
		Call call = (Call) service.createCall();
		//将webservice的服务路径加入到call实例中,并为call设置服务的位置
		URL url = new URL(endpoint);
		call.setTargetEndpointAddress(url);
		//调用webservice 的方法
		call.setOperationName("login");
		//序列化对象
		QName qn1 = new QName("urn:ZNWService","OperatorBean");
		call.registerTypeMapping(OperatorBean.class, qn1, new BeanSerializerFactory(OperatorBean.class,qn1), new BeanDeserializerFactory(OperatorBean.class,qn1));
		
		QName qn2 = new QName("urn:ZNWService","AuthorityBean");
		call.registerTypeMapping(AuthorityBean.class, qn2, new BeanSerializerFactory(AuthorityBean.class,qn2), new BeanDeserializerFactory(AuthorityBean.class,qn2));
	
		QName qn3 = new QName("urn:ZNWService","ArrayOfAuthorityBean");
		call.registerTypeMapping(AuthorityBean[].class, qn3,new ArraySerializerFactory(),new ArrayDeserializerFactory());
		
		QName qn4 = new QName("urn:ZNWService","LoginResponse");
		call.registerTypeMapping(LoginResponse.class, qn4, new BeanSerializerFactory(LoginResponse.class,qn4), new BeanDeserializerFactory(LoginResponse.class,qn4));

		call.addParameter("userName", org.apache.axis.Constants.XSD_STRING,ParameterMode.IN);
		call.addParameter("password", org.apache.axis.Constants.XSD_STRING,ParameterMode.IN);
		call.setReturnType(qn1, LoginResponse.class);
		
		call.addHeader(cpHeader);
		
		LoginResponse loginRes = (LoginResponse) call.invoke(new Object[]{userName,password});
		return loginRes;
	}	
}
分享到:
评论
1 楼 sjz64472418 2018-06-12  
请教下,我按照你的方法发布的webservice中数组对象为何出不来呢,能否帮忙看下是什么问题,谢谢!
<deployment xmlns="http://xml.apache.org/axis/wsdd/" 
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    
  <handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/> 
    <!-- name: 服务名随便写。 --> 
    <service name="CustomerService" provider="java:RPC"> 
    <parameter name="scope" value="Request" />
        <parameter name="className" value="com.sjz.custlabel.service.CustLabelServiceImpl" />
       
        <!-- requestFlow>   
       <handler type="BSHeaderHandler"/>   
  </requestFlow-->
   
        <!-- value表示哪些方法需要发布,*表示全部的public方法。 --> 
        <!-- 如果想指定方法名,方法名与方法名用逗号隔开 --> 
        <parameter name="allowedMethods" value="*" /> 
         
 
        <!-- 这里定义了方法的参数以及返回值 -->  
<operation name="queryCustLabels" returnType="ns1:DataResponse"> 
<parameter name="request" type="ns1:DataRequest"/> 
</operation> 
       
  <!-- 这里定义了自定义对象的映射 --> 
<typeMapping  
      qname="ns1:CustLabelInfo" 
      xmlns:ns1="CustomerService" 
      type="java:com.sjz.custlabel.demo.CustLabelInfo" 
      deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"    
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" 
/> 

<arrayMapping  
      qname="ns1:custInfos" 
      xmlns:ns1="CustomerService" 
      type="java:com.sjz.custlabel.demo.CustLabelInfo[]" 
      innerType="ns1:CustLabelInfo" 
      xmlns:ns2="CustomerService" 
      deserializer="org.apache.axis.encoding.ser.ArrayDeserializerFactory"    
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      serializer="org.apache.axis.encoding.ser.ArraySerializerFactory" 
       
/>

<typeMapping  
      qname="ns1:DataResponse" 
      xmlns:ns1="CustomerService" 
      type="java:com.sjz.custlabel.demo.DataResponse" 
      deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"    
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" 
/> 

<typeMapping  
      qname="ns1:DataRequest" 
      xmlns:ns1="CustomerService" 
      type="java:com.sjz.custlabel.demo.DataRequest" 
      deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"    
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
      serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" 
/> 

        <!-- 指定命名空间 --> 
        <namespace>http://192.168.1.3:8080/MyWS/CustomerService</namespace> 
    </service> 
    <transport name="http">       
    <requestFlow>       
        <handler type="URLMapper"/>       
    </requestFlow>       
  </transport>  
</deployment>

package com.sjz.query.custlabel.demo;

import java.io.Serializable;
import java.util.List;

/**
* 接口响应对象
* @author Administrator
*
*/
public class DataResponse implements Serializable{
/**
*
*/
private static final long serialVersionUID = 7775085348016910952L;

/**
* 接口返回码
* 成功:0000
* 鉴权失败:0001
* 参数错误:0002
* 系统内部异常:0003
*/
private String resultCode;

/**
* 接口返回信息
*/
private String resultMessage;

/**
* 客户标签集合列表
*/
private List<CustLabelInfo> custInfos;


public DataResponse(String resultCode, String resultMessage) {
super();
this.resultCode = resultCode;
this.resultMessage = resultMessage;
}

public String getResultCode() {
return resultCode;
}

public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}

public String getResultMessage() {
return resultMessage;
}

public void setResultMessage(String resultMessage) {
this.resultMessage = resultMessage;
}

public List<CustLabelInfo> getCustInfos() {
return custInfos;
}

public void setCustInfos(List<CustLabelInfo> custInfos) {
this.custInfos = custInfos;
}


}

package com.sjz.query.custlabel.demo;

import java.io.Serializable;

/**
* 客户标签对象
* @author Administrator
*
*/
public class CustLabelInfo implements Serializable{
/**
*
*/
private static final long serialVersionUID = -6399532300600644215L;

/**
* 唯一标示符
*/
private String key;

/**
* 属性名称
*/
private String name;

/**
* 属性值
*/
private String value;

public CustLabelInfo(){

}

public CustLabelInfo(String key, String name, String value) {
super();
this.key = key;
this.name = name;
this.value = value;
}


public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

这是生成的server-config.wsdd
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
  <parameter name="sendMultiRefs" value="true"/>
  <parameter name="disablePrettyXML" value="true"/>
  <parameter name="adminPassword" value="admin"/>
  <parameter name="attachments.Directory" value="D:\java\apache-tomcat-6.0.10\webapps\MyWS\WEB-INF\attachments"/>
  <parameter name="dotNetSoapEncFix" value="true"/>
  <parameter name="enableNamespacePrefixOptimization" value="false"/>
  <parameter name="sendXMLDeclaration" value="true"/>
  <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
  <parameter name="sendXsiTypes" value="true"/>
  <requestFlow>
   <handler type="java:org.apache.axis.handlers.JWSHandler">
    <parameter name="scope" value="session"/>
   </handler>
   <handler type="java:org.apache.axis.handlers.JWSHandler">
    <parameter name="scope" value="request"/>
    <parameter name="extension" value=".jwr"/>
   </handler>
  </requestFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<service name="AdminService" provider="java:MSG">
  <parameter name="allowedMethods" value="AdminService"/>
  <parameter name="enableRemoteAdmin" value="false"/>
  <parameter name="className" value="org.apache.axis.utils.Admin"/>
  <namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="Version" provider="java:RPC">
  <parameter name="allowedMethods" value="getVersion"/>
  <parameter name="className" value="org.apache.axis.Version"/>
</service>
<service name="CustomerService" provider="java:RPC">
  <operation name="queryCustLabels" returnType="DataResponse" soapAction="">
   <parameter name="request" type="DataRequest"/>
  </operation>
  <parameter name="allowedMethods" value="*"/>
  <parameter name="className" value="com.sjz.query.custlabel.service.CustLabelServiceImpl"/>
  <parameter name="scope" value="Request"/>
  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns1:CustLabelInfo" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:com.sjz.query.custlabel.demo.CustLabelInfo" xmlns:ns1="CustomerService"/>
  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns2:DataResponse" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:com.sjz.query.custlabel.demo.DataResponse" xmlns:ns2="CustomerService"/>
  <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" qname="ns3:DataRequest" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:com.sjz.query.custlabel.demo.DataRequest" xmlns:ns3="CustomerService"/>
  <arrayMapping innerType="ns4:CustLabelInfo" languageSpecificType="java:com.sjz.query.custlabel.demo.CustLabelInfo[]" qname="ns4:custInfos" xmlns:ns4="CustomerService"/>
  <namespace>http://192.168.1.3:8080/MyWS/CustomerService</namespace>
</service>
<transport name="http">
  <requestFlow>
   <handler type="URLMapper"/>
  </requestFlow>
</transport>
<transport name="local">
  <responseFlow>
   <handler type="LocalResponder"/>
  </responseFlow>
</transport>
</deployment>

相关推荐

Global site tag (gtag.js) - Google Analytics