当前位置: 代码迷 >> Web前端 >> Axis2-04 WebService中Session的治理
  详细解决方案

Axis2-04 WebService中Session的治理

热度:758   发布时间:2013-05-02 09:39:29.0
Axis2-04 WebService中Session的管理

?

一、Axis2 WebService会话Session的管理

?

1、新建SessionWebService测试代码

代码很简单。就是记录用户登录的状态信息,放在MessageContextServiceContext中:

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,它还有另外三个值,分别是:applicationsoapsessiontransportsession;我们可以选择使用transportsessionapplication分别实现同一个WebService类和跨WebService类的会话管理。

?

2、使用axis2的工具生成aar文件,并发布LoginService服务

????? 关于这里发布LoginService的步骤就不一一介绍,上篇博客已经有说过了。当你用这个步骤发布WebService的时候,你可以打开压缩文件的方式aar文件(其实不一定要用aar文件,只是官方推荐的aarjar文件也是可以的),在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、首先多个WebServicesession管理

?

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中的内容

  相关解决方案