摘要:本节主要介绍以下两点,1.带javabean的webservice的开发和调用 2.handler的简单介绍及使用
1.引言
在之前的一篇博客
webservice系列1---基于web工程上写一个基本数据类型的webservice
中介绍了如何采用axis1.4来完成一个简单的webservice的开发流程(入参和出参都是基本类型),但是在实际的开发中,方法的入参和出参基本类型已经无法满足我们日常的需求,如果方法的入参和出参中有对象的时候,我们要怎么处理呢?通过本节的介绍我会一一道来。
同时,我会引入对handler的介绍以及简单的使用,写了一个统计webservice调用次数的handler。
2.项目环境
system:win7
myeclipse:6.5
tomcat:5.0
JDK:开发环境采用JDK1.5;编译环境采用JDK1.4
axis:仍然采用1.4的版本。采用版本1是axis1比axis2稳定,实际项目中我们项目中也只用axis1,axis1.4是目前axis1最新版本。
这里测试客户端和服务端放在同一个工程的不同package中;
web.xml---web项目的配置文件;这里我们只用来配置了webservice的处理类AxisServlet;
server-config.wsdd---axis1.4定制发布的配置文件,这里不再需要用AdminClient来生成,直接拷贝之前工程的配置文件然后修改;
WebServiceClientUtil.java---调用webservice服务的客户端,采用动态调用,并且这里的客户端更加灵活;
IGroupInfoService.java和IGroupInfoServiceImpl.java---一个入参和出参包含对象的webservice服务对应的接口和实现类;
GroupInfo.java和UserInfo.java---服务需要用的两个标准的javabean;
GroupServiceHandler.java---一个handler处理类(什么是handler?请见下面的介绍),用来统计webservice的调用次数;
3.Handler介绍
什么是handler?J2EE Web 服务中的Handler技术特点非常像Servlet技术中的Filter。我们知道,在Servlet中,当一个HTTP到达服务端时,往往要经过多个Filter对请求进行过滤,然后才到达提供服务的Servlet,这些Filter的功能往往是对请求进行统一编码,对用户进行认证,把用户的访问写入系统日志等。在我的理解看来,handler就是为了在不污染原有的代码的前提下,通过配置文件,我们可以增加我们需要的功能,相应的,Web服务中的Handler通常也提供一下的功能:比如:
(1)可以记录某一个webservice的访问次数和访问时间(本节有这个小例子来简单介绍handler)
(2)调用webservice之前根据我们的需求做检验(关于使用handler做IP和用户的校验后面会有介绍);
(3)对请求的SOAP消息进行加密,解密
(4)为webservice对象做缓存
handler的处理过程可以表示如下:
图中多个handler在一起,其实这就组成了chain,后面我会对这个做个简单的介绍;
图中有handler有request和response;
那么,到底我们要怎么实现一个handler?
(1)新建一个classs,并且使该类继承BasicHandler类
(2)实现invoke方法
(3)在wsdd文件配置handler处理类,采用<handler></handler>标签
(4)在需要使用handler的webservice中引入handler类,采用<requestFlow><requestFlow/>或者<responseFlow></responseFlow>
以上是实现一个handler的步骤,具体的看下面的实例。
4.项目代码
先看看jar包吧
配置文件
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.4" 3 xmlns="http://java.sun.com/xml/ns/j2ee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 6 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 7 8 <servlet> 9 <servlet-name>AxisServlet</servlet-name> 10 <servlet-class> 11 org.apache.axis.transport.http.AxisServlet 12 </servlet-class> 13 </servlet> 14 <servlet-mapping> 15 <servlet-name>AxisServlet</servlet-name> 16 <url-pattern>/services/*</url-pattern> 17 </servlet-mapping> 18 19 </web-app>
server-config.wsdd
1 <?xml version="1.0" encoding="UTF-8"?> 2 <deployment xmlns="http://xml.apache.org/axis/wsdd/" 3 xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> 4 <globalConfiguration> 5 <parameter name="sendMultiRefs" value="true" /> 6 <parameter name="disablePrettyXML" value="true" /> 7 <parameter name="adminPassword" value="admin" /> 8 <parameter name="attachments.Directory" 9 value="D:\tomcat5\webapps\WebService\WEB-INF\attachments" /> 10 <parameter name="dotNetSoapEncFix" value="true" /> 11 <parameter name="enableNamespacePrefixOptimization" 12 value="false" /> 13 <parameter name="sendXMLDeclaration" value="true" /> 14 <parameter name="sendXsiTypes" value="true" /> 15 <parameter name="attachments.implementation" 16 value="org.apache.axis.attachments.AttachmentsImpl" /> 17 <requestFlow> 18 <handler type="java:org.apache.axis.handlers.JWSHandler"> 19 <parameter name="scope" value="session" /> 20 </handler> 21 <handler type="java:org.apache.axis.handlers.JWSHandler"> 22 <parameter name="scope" value="request" /> 23 <parameter name="extension" value=".jwr" /> 24 </handler> 25 </requestFlow> 26 </globalConfiguration> 27 <handler name="LocalResponder" 28 type="java:org.apache.axis.transport.local.LocalResponder" /> 29 <handler name="URLMapper" 30 type="java:org.apache.axis.handlers.http.URLMapper" /> 31 <handler name="Authenticate" 32 type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" /> 33 <service name="AdminService" provider="java:MSG"> 34 <parameter name="allowedMethods" value="AdminService" /> 35 <parameter name="enableRemoteAdmin" value="false" /> 36 <parameter name="className" value="org.apache.axis.utils.Admin" /> 37 <namespace>http://xml.apache.org/axis/wsdd/</namespace> 38 </service> 39 <service name="Version" provider="java:RPC"> 40 <parameter name="allowedMethods" value="getVersion" /> 41 <parameter name="className" value="org.apache.axis.Version" /> 42 </service> 43 44 <transport name="http"> 45 <requestFlow> 46 <handler type="URLMapper" /> 47 <handler 48 type="java:org.apache.axis.handlers.http.HTTPAuthHandler" /> 49 </requestFlow> 50 <parameter name="qs:list" 51 value="org.apache.axis.transport.http.QSListHandler" /> 52 <parameter name="qs:wsdl" 53 value="org.apache.axis.transport.http.QSWSDLHandler" /> 54 <parameter name="qs.list" 55 value="org.apache.axis.transport.http.QSListHandler" /> 56 <parameter name="qs.method" 57 value="org.apache.axis.transport.http.QSMethodHandler" /> 58 <parameter name="qs:method" 59 value="org.apache.axis.transport.http.QSMethodHandler" /> 60 <parameter name="qs.wsdl" 61 value="org.apache.axis.transport.http.QSWSDLHandler" /> 62 </transport> 63 <transport name="local"> 64 <responseFlow> 65 <handler type="LocalResponder" /> 66 </responseFlow> 67 </transport> 68 69 <!-- 配置一个handler,用来统计webservice的访问次数 --> 70 <handler name="GroupServiceHandler1" 71 type="java:com.server.wsddhandler.GroupServiceHandler"> 72 <parameter name="status" value="success" /> 73 </handler> 74 75 <!-- 配置自己的服务 --> 76 <service name="GroupService" provider="java:RPC"> 77 <parameter name="allowedMethods" value="*" /> 78 <parameter name="className" 79 value="com.server.impl.IGroupInfoServiceImpl" /> 80 <!-- 配置javabean --> 81 <beanMapping 82 languageSpecificType="java:com.server.bean.GroupInfo" 83 qname="ns:GroupInfo" xmlns:ns="urn:BeanService"> 84 </beanMapping> 85 86 <beanMapping 87 languageSpecificType="java:com.server.bean.UserInfo" 88 qname="ns:UserInfo" xmlns:ns="urn:BeanService"> 89 </beanMapping> 90 91 92 <!-- 引入一个用来统计webservice的访问次数的handler --> 93 <responseFlow> 94 <handler type="GroupServiceHandler1" /> 95 </responseFlow> 96 97 </service> 98 </deployment>
服务端代码
(1)javabean
GroupInfo.java
1 package com.server.bean; 2 3 import java.util.List; 4 5 public class GroupInfo { 6 7 private List colNames = null; // 数据库表的列名组成的List 8 9 private String[] colValues; // 数据库表一条记录的各个列的值组成的数组,即一条数据库表记录值 10 11 private int colCount = 0; // 数据库表记录的列数 12 13 private UserInfo userInfo = null; 14 15 public List getColNames() { 16 return colNames; 17 } 18 19 public void setColNames(List colNames) { 20 this.colNames = colNames; 21 } 22 23 public String[] getColValues() { 24 return colValues; 25 } 26 27 public void setColValues(String[] colValues) { 28 this.colValues = colValues; 29 } 30 31 public int getColCount() { 32 return colCount; 33 } 34 35 public void setColCount(int colCount) { 36 this.colCount = colCount; 37 } 38 39 public UserInfo getUserInfo() { 40 return userInfo; 41 } 42 43 public void setUserInfo(UserInfo userInfo) { 44 this.userInfo = userInfo; 45 } 46 47 }
UserInfo.java
1 package com.server.bean; 2 3 public class UserInfo { 4 5 private String serverIp = ""; 6 private String localIp = ""; 7 private long opId = 0; 8 9 public String getServerIp() { 10 return serverIp; 11 } 12 13 public void setServerIp(String serverIp) { 14 this.serverIp = serverIp; 15 } 16 17 public String getLocalIp() { 18 return localIp; 19 } 20 21 public void setLocalIp(String localIp) { 22 this.localIp = localIp; 23 } 24 25 public long getOpId() { 26 return opId; 27 } 28 29 public void setOpId(long opId) { 30 this.opId = opId; 31 } 32 33 }
(2)服务类
IGroupInfoService.java
1 package com.server.interfaces; 2 3 import com.server.bean.GroupInfo; 4 import com.server.bean.UserInfo; 5 6 /** 7 * 8 *Module: IGroupInfoService.java 9 *Description: 带javabean的webservice的服务 10 *Company: 11 *Version: 1.0.0 12 *Author: pantp 13 *Date: Aug 21, 2012 14 */ 15 public interface IGroupInfoService { 16 17 public abstract GroupInfo getGroupInfo(UserInfo userInfo,long groupId); 18 19 }
IGroupInfoServiceImpl.java
1 package com.server.impl; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import com.server.bean.GroupInfo; 7 import com.server.bean.UserInfo; 8 import com.server.interfaces.IGroupInfoService; 9 10 public class IGroupInfoServiceImpl implements IGroupInfoService { 11 12 public GroupInfo getGroupInfo(UserInfo userInfo, long groupId) { 13 System.out.println("开始打印入参值..."); 14 System.out.println("groupId:" + groupId); 15 System.out.println("serInfo.getOpId():" + userInfo.getOpId()); 16 System.out.println("serInfo.getServerIp():" + userInfo.getServerIp()); 17 System.out.println("serInfo.getLocalIp():" + userInfo.getLocalIp()); 18 System.out.println("结束打印入参值..."); 19 20 // 这里是为了学习webservice调用时带javabean,所以方法的返回值就直接手动的构造了 21 GroupInfo group = new GroupInfo(); 22 group.setColCount(1); 23 24 List colNames = new ArrayList(); 25 colNames.add("group_id"); 26 colNames.add("group_name"); 27 colNames.add("state"); 28 group.setColNames(colNames); 29 30 String colValues[] = { "2100014", "中国移动通信", "1" }; 31 group.setColValues(colValues); 32 33 group.setUserInfo(userInfo); 34 return group; 35 } 36 37 }
(3)handler处理类
GroupServiceHandler.java
1 package com.server.wsddhandler; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 6 import org.apache.axis.AxisFault; 7 import org.apache.axis.MessageContext; 8 import org.apache.axis.handlers.BasicHandler; 9 10 /* 11 * 采用handler统计webservice的访问次数 12 */ 13 public class GroupServiceHandler extends BasicHandler { 14 15 private static final long serialVersionUID = 1L; 16 17 private static long COUNT = 0L; 18 19 private int requestCount = 0; 20 21 public void invoke(MessageContext arg0) throws AxisFault { 22 requestCount++; 23 COUNT++; 24 //拿到配置文件中配置的属性名称status对应的属性值 25 String status = (String) this.getOption("status"); 26 System.out.println("GroupServiceHandler's status is:" + status 27 + ",COUNT=" + COUNT + ",HandlerRequestCount=" + requestCount); 28 Date date=new Date(); 29 SimpleDateFormat df=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:SS E"); 30 System.out.println("access time:"+df.format(date)); 31 32 } 33 34 };
客户端代码
WebServiceClientUtil.java
1 package com.client; 2 3 import javax.xml.namespace.QName; 4 import org.apache.axis.client.Call; 5 import org.apache.axis.client.Service; 6 import org.apache.axis.description.OperationDesc; 7 import org.apache.axis.description.ParameterDesc; 8 import org.apache.axis.encoding.ser.BeanDeserializerFactory; 9 import org.apache.axis.encoding.ser.BeanSerializerFactory; 10 import java.net.URL; 11 import org.apache.axis.constants.Style; 12 import org.apache.axis.constants.Use; 13 import org.apache.axis.soap.SOAPConstants; 14 15 /*实际开发中, 16 *服务端和客户端不在同一工程,客户端需要新建自己的javabean,这里我直接用服务端的类了 17 *至于怎么新建可以采用上一节博客中的genClient.bat文件 18 */ 19 import com.server.bean.GroupInfo; 20 import com.server.bean.UserInfo; 21 22 public class WebServiceClientUtil { 23 public static void main(String args[]) throws Exception { 24 //准备参数 25 String methodName = "getGroupInfo"; 26 27 String key[] = { "userInfo", "groupId" }; 28 29 UserInfo userInfo = new UserInfo(); 30 userInfo.setLocalIp("127.0.0.1"); 31 userInfo.setOpId(1234); 32 userInfo.setServerIp("127.0.0.1"); 33 34 Long groupId = new Long(2100000014); 35 Object value[] = { userInfo, groupId }; 36 37 //调用webservice服务 38 GroupInfo result = (GroupInfo) getGroupInfo(methodName, key, value); 39 40 //打印返回的信息 41 System.out.println(result.getColCount()); 42 43 for (int i = 0; i < result.getColNames().size(); i++) 44 System.out.print(result.getColNames().get(i) + "\t \t"); 45 System.out.println(); 46 for (int i = 0; i < result.getColValues().length; i++) 47 System.out.print(result.getColValues()[i] + "\t \t"); 48 System.out.println(); 49 System.out.println(result.getUserInfo().getServerIp()); 50 } 51 52 /** 53 *<p> 54 *@param methodName 调用webservice的方法名称 55 *@param key 调用webservice的该方法所有的参数名称组成的数组 56 *@param value 调用webservice的该方法所有的参数对应的实际入参值 57 *@return 58 *@Description:动态调用webservice的客户端代码 59 */ 60 public static Object getGroupInfo(String methodName, String key[], 61 Object value[]) throws Exception { 62 63 Service service = new Service(); 64 Call call = (Call) service.createCall(); 65 66 // 注册SimpleObject的序列化类型 67 QName qn = new QName("urn:BeanService", "GroupInfo"); 68 call.registerTypeMapping(GroupInfo.class, qn, 69 new BeanSerializerFactory(GroupInfo.class, qn), 70 new BeanDeserializerFactory(GroupInfo.class, qn)); 71 72 QName qn2 = new QName("urn:BeanService", "UserInfo"); 73 call.registerTypeMapping(UserInfo.class, qn2, 74 new BeanSerializerFactory(UserInfo.class, qn2), 75 new BeanDeserializerFactory(UserInfo.class, qn2)); 76 77 String wsdl_url = "http://localhost:8080/WebService02/services/GroupService?wsdl"; 78 String qname_url = "http://localhost:8080/WebService02/services/GroupService"; 79 80 call.setTargetEndpointAddress(new URL(wsdl_url)); // Web服务调用 81 82 OperationDesc oper = new OperationDesc(); 83 84 for (int i = 0; i < key.length; i++) { 85 ParameterDesc param = new ParameterDesc(new QName("", key[i]),ParameterDesc.IN, null); 86 oper.addParameter(param); 87 } 88 oper.setReturnType(new QName("urn:BeanService", "GroupInfo")); 89 oper.setReturnClass(GroupInfo.class); 90 oper.setReturnQName(new QName("", methodName)); 91 oper.setStyle(Style.RPC); 92 oper.setUse(Use.ENCODED); 93 call.setOperation(oper); 94 call.setUseSOAPAction(true); 95 call.setSOAPActionURI(""); 96 call.setSOAPVersion(SOAPConstants.SOAP11_CONSTANTS); 97 call.setOperationName(new QName(qname_url, methodName)); 98 99 java.lang.Object _resp = null; 100 _resp = call.invoke(value); 101 return _resp; 102 } 103 104 }
5.运行效果
发布项目,启动tomcat服务器;
(1)在浏览器输入wsdl地址
http://localhost:8080/WebService02/services/GroupService?wsdl
(2)采用webservice客户端调用,查看返回结果
客户端后台日志:
服务端后台日志: