项目需要,发布webservice服务端,向客户端传递复杂对象。对象包含了list<>,反复研究了一下,发现webservice不能够直接传递list对象,必须转换成对象数组才能传递。javaBean:
1.package com.wensi.service.server;
2.
3.import java.io.Serializable;
4.
5.public class LoginResponse implements Serializable{
6. private boolean flag;//操作员登录验证是否通过:true 验证通过 false 验证失败
7. private OperatorBean operator;//登录成功后返回的操作员信息,登录失败返回null
8. private AuthorityBean[] authorityArray;//登录成功后返回操作员的权限,登录失败返回null
9. private String checkNum;//校验码
10.
11. public boolean isFlag() {
12. return flag;
13. }
14. public void setFlag(boolean flag) {
15. this.flag = flag;
16. }
17. public OperatorBean getOperator() {
18. return operator;
19. }
20. public void setOperator(OperatorBean operator) {
21. this.operator = operator;
22. }
23. public AuthorityBean[] getAuthorityArray() {
24. return authorityArray;
25. }
26. public void setAuthorityArray(AuthorityBean[] authorityArray) {
27. this.authorityArray = authorityArray;
28. }
29. public String getCheckNum() {
30. return checkNum;
31. }
32. public void setCheckNum(String checkNum) {
33. this.checkNum = checkNum;
34. }
35.}
这是一个复杂的自定义对象,该对象嵌套了基本类型、自定义对象以及自定义对象数组。其余的对象我就不细说了,来看一下,axis1.4用来发布服务的wsdd文件:
1.<?xml version="1.0" encoding="UTF-8"?>
2.<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
3. <handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>
4. <handler type="java:com.wensi.service.server.BSHeaderHandler" name="BSHeaderHandler"/>
5. <service name="ZNWService" provider="java:RPC">
6.
7. <requestFlow>
8. <handler type="BSHeaderHandler"/>
9. </requestFlow>
10.
11. <parameter name="className" value="com.wensi.service.server.ZNWService"/>
12. <parameter name="allowedMethods" value="*"/>
13. <parameter name="scope" value="session"/>
14.
15.<!-- 这里定义了方法的参数以及返回值 -->
16. <operation name="login" returnType="ns:LoginResponse">
17. <parameter name="userName" type="tns:string"/>
18. <parameter name="password" type="tns:string"/>
19. </operation>
20.
21.<!-- 这里定义了自定义对象的映射 -->
22. <typeMapping
23. qname="ns:OperatorBean"
24. xmlns:ns="ZNWService"
25. type="java:com.wensi.service.server.OperatorBean"
26. deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
27. encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
28. serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
29. />
30.
31. <typeMapping
32. qname="ns:AuthorityBean"
33. xmlns:ns="ZNWService"
34. type="java:com.wensi.service.server.AuthorityBean"
35. deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
36. encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
37. serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
38. />
39.
40. <arrayMapping
41. qname="ns:ArrayOfAuthorityBean"
42. xmlns:ns="ZNWService"
43. type="java:com.wensi.service.server.AuthorityBean[]"
44. innerType="ns:AuthorityBean"
45. xmlns:ns2="ZNWService"
46. deserializer="org.apache.axis.encoding.ser.ArrayDeserializerFactory"
47. encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
48. serializer="org.apache.axis.encoding.ser.ArraySerializerFactory"
49.
50. />
51.
52. <typeMapping
53. qname="ns:LoginResponse"
54. xmlns:ns="ZNWService"
55. type="java:com.wensi.service.server.LoginResponse"
56. deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
57. encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
58. serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
59. />
60.
61. </service>
62. <transport name="http">
63. <requestFlow>
64. <handler type="URLMapper"/>
65. </requestFlow>
66. </transport>
67.</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>
是实现一个相当于拦截器的功能,客户端在调用服务端的接口之前,必须经过这个方法的处理。
在这里,我写了一个权限验证的拦截器,代码如下:
1.package com.wensi.service.server;
2.
3.import org.apache.axis.AxisFault;
4.import org.apache.axis.Message;
5.import org.apache.axis.MessageContext;
6.import org.apache.axis.handlers.BasicHandler;
7.import javax.xml.soap.SOAPException;
8.import javax.xml.soap.SOAPHeader;
9.import org.apache.axis.message.SOAPHeaderElement;
10.import org.apache.axis.message.SOAPEnvelope;
11.import org.apache.axis.message.MessageElement;
12.
13.import com.wensi.common.Util;
14.
15.import javax.xml.namespace.QName;
16.
17.import java.text.ParseException;
18.import java.text.SimpleDateFormat;
19.import java.util.Date;
20.import java.util.Iterator;
21.import java.util.Map;
22.
23.@SuppressWarnings("unchecked")
24.public class BSHeaderHandler extends BasicHandler {
25. private static final long serialVersionUID = 1L;
26. private String operNum;//操作员编号
27. private String checkNum;//校验码
28. private String time;//访问接口的时间
29. String endpoint = ServiceConstant.endpoint;//webservice的具体路径
30. Map map = ServiceConstant.checkMap;//包含校验码信息的map
31.
32. // 在执行service前先处理handler
33. // invoke()会被自动调用,而且 SOAP 信息可以由 msgContext 取得
34. public void invoke(MessageContext msgContext) throws AxisFault {
35. boolean processedHeader = false;
36. try {
37. // 取得 Request 的 SOAP 信息
38. Message msg = msgContext.getRequestMessage();
39. SOAPEnvelope envelope = msg.getSOAPEnvelope();
40. SOAPHeader header = envelope.getHeader();
41. Iterator it = header.examineAllHeaderElements();
42. SOAPHeaderElement hel;
43. while (it.hasNext()) {
44. hel = (SOAPHeaderElement) it.next();
45. String headerName = hel.getNodeName();
46. if (headerName.equals("cp:MessageHeader")) {
47. // 对于 mustUnderstand 设为 true 的 Header,必须
48. // 利用下列的方式把它设为"已经处理",否则 service
49. // 会回传 Did not understand "MustUnderstand"
50. hel.setProcessed(true);
51. checkUser(hel);
52. processedHeader = true;
53. }
54. }
55. } catch (SOAPException e) {
56. throw new AxisFault("无法处理 SOAP Header.", e);
57. }
58. if (!processedHeader) {
59. throw new AxisFault("接收 SOAP Header 失败");
60. }
61. }
62. private void checkUser(SOAPHeaderElement hel) throws AxisFault {
63. String current = Util.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss");//当前时间字符串
64. MessageElement element1 = hel.getChildElement(new QName(
65. endpoint, "isLogin"));
66.
67. MessageElement element2 = hel.getChildElement(new QName(
68. endpoint, "operNum"));
69.
70. MessageElement element3 = hel.getChildElement(new QName(
71. endpoint, "checkNum"));
72.
73. MessageElement element4 = hel.getChildElement(new QName(
74. endpoint, "time"));
75.
76.
77. //用户访问的不是登录接口,则进行校验码验证
78. if(null == element1 && null != element2 && null != element3 && null != element4){
79. operNum = element2.getValue();
80. checkNum = element3.getValue();
81. time = element4.getValue();
82. Boolean flag1 = false;
83. if(map.keySet().contains(operNum)){
84. CheckNumBean check = (CheckNumBean) map.get(operNum);
85. System.out.println(check.getCheckNum());
86. if(check.getCheckNum().equals(checkNum)){
87. flag1 = true;
88. }
89. }
90.
91. Boolean flag2 = false;
92. if(flag1){
93. //计算服务器时间与soapHeader时间戳之间的差值
94. Long between = countTime(time,current);
95. //时差在一个小时之内,算正常
96. if(Math.abs(between) < 3600L){
97. flag2 = true;
98. }
99. }
100.
101. if(!(flag1 && flag2)){
102. throw new AxisFault("校验失败");
103. }
104.
105. //更新map内信息
106. CheckNumBean check = (CheckNumBean) map.get(operNum);
107. check.setLastTime(check.getCurrentTime());
108. check.setCurrentTime(current);
109. } else if(null == element1 && (null == element2 || null == element3 || null == element4)){
110. throw new AxisFault("校验失败");
111. }
112. }
113.
114. //计算时间差
115. private Long countTime(String str1, String str2){
116. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
117. Date begin = null;
118. Date end = null;
119. try {
120. begin = df.parse(str1);
121. end = df.parse(str2);
122. } catch (ParseException e) {
123. e.printStackTrace();
124. }
125. long between=(end.getTime()-begin.getTime())/1000;//除以1000是为了转换成秒
126. return between;
127. }
128.}
由于客户端是手持机,而这边的客户端是java ssh架构,所以存储用户信息,正能依靠内存来完成。
客户端调用的时候,需要向soapHeader放验证信息。
客户端代码如下:
1.package com.wensi.service.client;
2.
3.
4.import java.net.MalformedURLException;
5.import java.net.URL;
6.import java.rmi.RemoteException;
7.import java.util.Date;
8.
9.import javax.xml.namespace.QName;
10.import javax.xml.rpc.ParameterMode;
11.import javax.xml.rpc.ServiceException;
12.import javax.xml.rpc.encoding.XMLType;
13.import javax.xml.soap.SOAPElement;
14.import javax.xml.soap.SOAPException;
15.
16.import org.apache.axis.client.Call;
17.import org.apache.axis.client.Service;
18.import org.apache.axis.encoding.ser.ArrayDeserializerFactory;
19.import org.apache.axis.encoding.ser.ArraySerializerFactory;
20.import org.apache.axis.encoding.ser.BeanDeserializerFactory;
21.import org.apache.axis.encoding.ser.BeanSerializerFactory;
22.import org.apache.axis.message.SOAPHeaderElement;
23.
24.import com.wensi.common.Util;
25.import com.wensi.service.server.AccountCustomerBean;
26.import com.wensi.service.server.AccountFlag;
27.import com.wensi.service.server.AccountResponse;
28.import com.wensi.service.server.AuthorityBean;
29.import com.wensi.service.server.LoginResponse;
30.import com.wensi.service.server.OperatorBean;
31.import com.wensi.service.server.ServiceConstant;
32.
33.
34.public class ZNWServiceClient {
35. String endpoint = ServiceConstant.endpoint;//webservice的具体路径
36. Service service = new Service();//创建service实例
37.
38. public LoginResponse login(String userName,String password) throws Exception{
39. SOAPHeaderElement cpHeader = new SOAPHeaderElement(endpoint,"MessageHeader");
40. cpHeader.setPrefix("cp");
41. cpHeader.setMustUnderstand(true);
42. SOAPElement ele = null;
43. ele = cpHeader.addChildElement("isLogin");
44. ele.addTextNode("true");
45.
46. //创建call实例
47. Call call = (Call) service.createCall();
48. //将webservice的服务路径加入到call实例中,并为call设置服务的位置
49. URL url = new URL(endpoint);
50. call.setTargetEndpointAddress(url);
51. //调用webservice 的方法
52. call.setOperationName("login");
53. //序列化对象
54. QName qn1 = new QName("urn:ZNWService","OperatorBean");
55. call.registerTypeMapping(OperatorBean.class, qn1, new BeanSerializerFactory(OperatorBean.class,qn1), new BeanDeserializerFactory(OperatorBean.class,qn1));
56.
57. QName qn2 = new QName("urn:ZNWService","AuthorityBean");
58. call.registerTypeMapping(AuthorityBean.class, qn2, new BeanSerializerFactory(AuthorityBean.class,qn2), new BeanDeserializerFactory(AuthorityBean.class,qn2));
59.
60. QName qn3 = new QName("urn:ZNWService","ArrayOfAuthorityBean");
61. call.registerTypeMapping(AuthorityBean[].class, qn3,new ArraySerializerFactory(),new ArrayDeserializerFactory());
62.
63. QName qn4 = new QName("urn:ZNWService","LoginResponse");
64. call.registerTypeMapping(LoginResponse.class, qn4, new BeanSerializerFactory(LoginResponse.class,qn4), new BeanDeserializerFactory(LoginResponse.class,qn4));
65.
66. call.addParameter("userName", org.apache.axis.Constants.XSD_STRING,ParameterMode.IN);
67. call.addParameter("password", org.apache.axis.Constants.XSD_STRING,ParameterMode.IN);
68. call.setReturnType(qn1, LoginResponse.class);
69.
70. call.addHeader(cpHeader);
71.
72. LoginResponse loginRes = (LoginResponse) call.invoke(new Object[]{userName,password});
73. return loginRes;
74. }
75.}
【转载地址】
http://wufeng219219.iteye.com/blog/808807