?
一、Axis2 WebService会话Session的管理
?
1、新建Session的WebService测试代码
代码很简单。就是记录用户登录的状态信息,放在MessageContext的ServiceContext中:
package com.iflytek.service; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ServiceContext; /** * @author xdwang * * @create Apr 25, 2013 3:20:12 PM * * @email:xdwangiflytek@gmail.com * * @description WebService Session会话消息 * * */ public class LoginService { public boolean login(String userName, String password) { MessageContext context = MessageContext.getCurrentMessageContext(); ServiceContext ctx = context.getServiceContext(); if ("admin".equals(userName) && "123456".equals(password)) { ctx.setProperty("userName", userName); ctx.setProperty("password", password); ctx.setProperty("msg", "登陆成功"); return true; } ctx.setProperty("msg", "登陆失败"); return false; } public String getLoginMessage() { MessageContext context = MessageContext.getCurrentMessageContext(); ServiceContext ctx = context.getServiceContext(); return ctx.getProperty("userName") + "#" + ctx.getProperty("msg"); } }
? ???? 这里保存Session信息的主要是通过MessageContext这个上下文来获取ServiceContext的上下文,然后通过setProperty来保存session的信息,通过getProperty来获取session信息。
Session的作用可以在使用WebService登录的时候,保存用户的登录状态或是会话消息。但是使用session需要设置发布Service的时候,设置WebService的作用域。作用域默认是request,它还有另外三个值,分别是:application、soapsession、transportsession;我们可以选择使用transportsession和application分别实现同一个WebService类和跨WebService类的会话管理。
?
2、使用axis2的工具生成aar文件,并发布LoginService服务
????? 关于这里发布LoginService的步骤就不一一介绍,上篇博客已经有说过了。当你用这个步骤发布WebService的时候,你可以打开压缩文件的方式aar文件(其实不一定要用aar文件,只是官方推荐的aar,jar文件也是可以的),在META-INF目录下有一个services.xml文件,看到它的<service>这个标签,没有设置scope属性。
?????? scope默认的是request,我们得修改services.xml的内容。修改后services.xml内容如下:
<service name="SessionAxisWB" scope="transportsession"> <description> Please Type your service description here </description> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </messageReceivers> <parameter name="ServiceClass">com.iflytek.service.LoginService</parameter> </service>
?
?
??? 这个地方的scope是关键,如果这里不设置的话session是无法存放信息。
到此,一个服务的arr文件已经生成,将此文件移至之前部署的axis2。即apache-tomcat\webapps\axis2\WEB-INF\services下重启tomcat,然后可以通过:http://localhost:8080/axis2/services/listServices就可以查看刚才发布的服务了。
?
3、编写WebService客户端的请求代码
?
package com.iflytek.service; import javax.xml.namespace.QName; import org.apache.axis2.AxisFault; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.client.Options; import org.apache.axis2.rpc.client.RPCServiceClient; /** * @author xdwang * * @create Apr 25, 2013 3:34:09 PM * * @email:xdwangiflytek@gmail.com * * @description LoginService Session客户端代码 * */ public class LoginServiceClient { public static void main(String[] args) throws AxisFault { String target = "http://localhost:8080/axis2/services/SessionAxisWB"; RPCServiceClient client = new RPCServiceClient(); Options options = client.getOptions(); options.setManageSession(true);// 开启对Session管理的支持 EndpointReference epr = new EndpointReference(target); options.setTo(epr); //targetNamespace QName qname = new QName("http://service.iflytek.com", "login"); // 指定调用的方法和传递参数数据,及设置返回值的类型 Object[] result = client.invokeBlocking(qname, new Object[] { "admin", "123456" }, new Class[] { boolean.class }); System.out.println(result[0]); qname = new QName("http://service.iflytek.com", "getLoginMessage"); result = client.invokeBlocking(qname, new Object[] { null }, new Class[] { String.class }); System.out.println(result[0]); } }
?运行结果:
true admin#登陆成功
?上面要说明的是options.setManageSession(true);是开启对Session管理的支持
?
二、Axis2跨多个WebService管理Session
??????? 当多个WebService的时候,我们要管理它的Session。这个时候我们得依靠ServiceGroupContext保存session信息;然后在发布WebService的时候,services.xml文件的的service表情的scope就不再说request或是transportsession了,而是application;最后同样要开启对session的管理,即options.setManageSession(true);
?
1、首先多个WebService的session管理
?
package com.iflytek.service; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ServiceGroupContext; /** * @author xdwang * * @create Apr 25, 2013 3:46:54 PM * * @email:xdwangiflytek@gmail.com * * @description 管理多个会话Session信息 * */ public class LoginSessionService { public boolean login(String userName, String password) { MessageContext context = MessageContext.getCurrentMessageContext(); ServiceGroupContext ctx = context.getServiceGroupContext(); if ("admin".equals(userName) && "123456".equals(password)) { ctx.setProperty("userName", userName); ctx.setProperty("password", password); ctx.setProperty("msg", "登陆成功"); return true; } ctx.setProperty("msg", "登陆失败"); return false; } public String getLoginMessage() { MessageContext context = MessageContext.getCurrentMessageContext(); ServiceGroupContext ctx = context.getServiceGroupContext(); return ctx.getProperty("userName") + "#" + ctx.getProperty("msg"); } }
? ? 和上面的Session一样的操作,只不过是用ServiceGroupContext上下文来存取session信息
?? 另外还需要用一个Service来查询session的信息,SearchService的代码如下:
package com.iflytek.service; import org.apache.axis2.context.MessageContext; import org.apache.axis2.context.ServiceGroupContext; /** * @author xdwang * * @create Apr 25, 2013 3:48:20 PM * * @email:xdwangiflytek@gmail.com * * @description 查找多服务Session会话中的消息 * */ public class SearchSessionServcie { public String findSessionMessage(String key) { MessageContext mc = MessageContext.getCurrentMessageContext(); ServiceGroupContext ctx = mc.getServiceGroupContext(); if (ctx.getProperty(key) != null) { return "找到的数据<" + key + ", " + ctx.getProperty(key) + ">"; } else { return "没有找到<" + key + ">的数据"; } } }
?
2、发布WebService
通过Eclipse生成.aar文件,然后手动修改里面的services.xml为(这里还没有找到如何直接在Eclipse中添加):
<serviceGroup> <service name="LoginSessionService" scope="application"> <description> Please Type your service description here </description> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </messageReceivers> <parameter name="ServiceClass">com.iflytek.service.LoginSessionService</parameter> </service> <service name="SearchSessionServcie " scope="application"> <description> Please Type your service description here </description> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" /> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </messageReceivers> <parameter name="ServiceClass">com.iflytek.service.SearchSessionServcie</parameter> </service> </serviceGroup>
? 说明:
1、? 如果只有一个service,则不需要serviceGroup;
2、? Service节点下的name是当前发布WebService的名称,scope是会话作用域。保存在Session中就要用这个transportsession这个作用域;
3、? Parameter表示这个是当前Service的类路径,包名+类名;
4、? messageReceivers应该是参数和返回值信息的解析类,in-only是输入也就是参数,in-out是输出也就是返回值。
?
3、编写客户端的测试代码
发布完成后,可以通过http://localhost:8080/axis2/services/listServices查看发布的WebService服务,ok,编写客户端代码:
?
package com.iflytek.service; import javax.xml.namespace.QName; import org.apache.axis2.AxisFault; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.client.Options; import org.apache.axis2.rpc.client.RPCServiceClient; /** * @author xdwang * * @create Apr 25, 2013 4:10:50 PM * * @email:xdwangiflytek@gmail.com * * @description 多会话Session管理,WebService客户端请求代码 * */ public class LoginSessionServiceClient { public static void main(String[] args) throws AxisFault { String target = "http://localhost:8080/axis2/services/LoginSessionService"; RPCServiceClient client = new RPCServiceClient(); Options options = client.getOptions(); options.setManageSession(true); EndpointReference epr = new EndpointReference(target); options.setTo(epr); QName qname = new QName("http://service.iflytek.com", "login"); // 指定调用的方法和传递参数数据,及设置返回值的类型 Object[] result = client.invokeBlocking(qname, new Object[] { "admin", "123456" }, new Class[] { boolean.class }); System.out.println(result[0]); qname = new QName("http://service.iflytek.com", "getLoginMessage"); result = client.invokeBlocking(qname, new Object[] { null }, new Class[] { String.class }); System.out.println(result[0]); target = "http://localhost:8080/axis2/services/SearchSessionServcie"; epr = new EndpointReference(target); options.setTo(epr); qname = new QName("http://service.iflytek.com", "findSessionMessage"); result = client.invokeBlocking(qname, new Object[] { "userName" }, new Class[] { String.class }); System.out.println(result[0]); qname = new QName("http://service.iflytek.com", "findSessionMessage"); result = client.invokeBlocking(qname, new Object[] { "msg" }, new Class[] { String.class }); System.out.println(result[0]); qname = new QName("http://service.iflytek.com", "findSessionMessage"); result = client.invokeBlocking(qname, new Object[] { "password" }, new Class[] { String.class }); System.out.println(result[0]); } }
?运行结果:
true admin#登陆成功 找到的数据<userName, admin> 找到的数据<msg, 登陆成功> 找到的数据<password, 123456>
?
4、如果将services.xml文件<service name="SearchSessionService" scope="application">的内容改成scope=transportsession,那么是找不到session中的内容