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;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值