随笔 - 312, 文章 - 14, 评论 - 1393, 引用 - 0
数据加载中……

WebService大讲堂之Axis2(5):会话(Session)管理

本文为原创,如需转载,请注明作者和出处,谢谢!


上一篇:WebService大讲堂之Axis2(4):二进制文件传输

WebService给人最直观的感觉就是由一个个方法组成,并在客户端通过SOAP协议调用这些方法。这些方法可能有返回值,也可能没有返回值。虽然这样可以完成一些工具,但这些被调用的方法是孤立的,当一个方法被调用后,在其他的方法中无法获得这个方法调用后的状态,也就是说无法保留状态。

读者可以想象,这对于一个完整的应用程序,无法保留状态,就意味着只依靠WebService很难完成全部的工作。例如,一个完整的应用系统都需要进行登录,这在Web应用中使用Session来保存用户登录状态,而如果用WebService的方法来进行登录处理,无法保存登录状态是非常令人尴尬的。当然,这也可以通过其他的方法来解决,如在服务端使用static变量来保存用户状态,并发送一个id到客户端,通过在服务端和客户端传递这个id来取得相应的用户状态。这非常类似于Web应用中通过SessionCookie来管理用户状态。但这就需要由开发人员做很多工作,不过幸好Axis2为我们提供了WebService状态管理的功能。

使用Axis2来管理WebService的状态基本上对于开发人员是透明的。在WebService类需要使用org.apache.axis2.context.MessageContextorg.apache.axis2.context.ServiceContext类来保存与获得保存在服务端的状态信息,这有些象使用HttpSession接口的getAttributesetAttribute方法获得与设置Session域属性。

除此之外,还需要修改services.xml文件的内容,为<service>元素加一个scope属性,该属性有四个可取的值:Application, SOAPSession, TransportSession, Request,不过要注意一下,虽然Axis2的官方文档将这四个值的单词首字母和缩写字母都写成了大写,但经笔者测试,必须全部小写才有效,也就是这四个值应为:applicationsoapsessiontransportsessionrequest,其中requestscope属性的默认值。读者可以选择使用transportsessionapplication分别实现同一个WebService类和跨WebService类的会话管理。

在客户端需要使用setManageSession(true)打开Session管理功能。

综上所述,实现同一个WebServiceSession管理需要如下三步:

1. 使用MessageContextServiceContext获得与设置key-value对。

2. 为要进行Session管理的WebService类所对应的<service>元素添加一个scope属性,并将该属性值设为transportsession

3. 在客户端使用setManageSession(true)打开Session管理功能。

下面是一个在同一个WebService类中管理Session的例子。

先建立一个WebService类,代码如下:


package service;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.MessageContext;
public class LoginService
{
    
public boolean login(String username, String password)
    {
        
if("bill".equals(username) && "1234".equals(password))
        {
            
//  第1步:设置key-value对
            MessageContext mc = MessageContext.getCurrentMessageContext();
            ServiceContext sc 
= mc.getServiceContext();
            sc.setProperty(
"login""成功登录");    
            
return true;
        }
        
else
        {
            
return false;
        }
    }
    
public String getLoginMsg()
    {
        
//  第1步:获得key-value对中的value
        MessageContext mc = MessageContext.getCurrentMessageContext();
        ServiceContext sc 
= mc.getServiceContext();
        
return (String)sc.getProperty("login");    
    }
}

LoginService类中有两个方法:logingetLoginMsg,如果login方法登录成功,会将“成功登录”字符串保存在ServiceContext对象中。如果在login方法返回true后调用getLoginMsg方法,就会返回“成功登录”。

下面是LoginService类的配置代码(services.xml):

<!--  第2步:添加scope属性  -->
<service name="loginService" scope="transportsession">
    
<description>
        登录服务
        
</description>
    
<parameter name="ServiceClass">
        service.LoginService
        
</parameter>
    
<messageReceivers>
        
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
            class
="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
    
</messageReceivers>
</service>

使用如下的命令生成客户端使用的stub类:

%AXIS2_HOME%\bin\wsdl2java -uri http://localhost:8080/axis2/services/loginService?wsdl -p client -s -o stub

stub\src\client目录中生成了一个LoginServiceStub.java类,在该类中找到如下的构造句方法:

public LoginServiceStub(org.apache.axis2.context.ConfigurationContext configurationContext,
        java.lang.String targetEndpoint, 
boolean useSeparateListener)
        
throws org.apache.axis2.AxisFault 
{
     
    _serviceClient.getOptions().setSoapVersionURI(
                                 org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
}

在该方法中最后添加如下的代码:

//  第3步:打开客户端的Session管理功能
_serviceClient.getOptions().setManageSession(true);

下面的客户端代码使用LoginServiceStub对象访问了刚才建立的WebService

LoginServiceStub stub = new LoginServiceStub();
LoginServiceStub.Login login 
= new LoginServiceStub.Login();
login.setUsername(
"bill");
login.setPassword(
"1234");
if(stub.login(login).local_return)
{
    System.out.println(stub.getLoginMsg().local_return);
}

运行上面的代码后,会输出“成功登录”信息。

下一篇:
WebService大讲堂之Axis2(6):跨服务会话(Session)管理





Android开发完全讲义(第2版)(本书版权已输出到台湾)

http://product.dangdang.com/product.aspx?product_id=22741502



Android高薪之路:Android程序员面试宝典 http://book.360buy.com/10970314.html


新浪微博:http://t.sina.com.cn/androidguy   昵称:李宁_Lining

posted on 2009-01-26 00:00 银河使者 阅读(18460) 评论(31)  编辑  收藏 所属分类: java 原创webservice

评论

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我按照楼主的方法,可是为什么System.out.println(stub.getLoginMsg().local_return);得到的为null?
2009-04-28 18:16 | Sophie

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

看看services.xml文件设置是否正确
2009-04-28 19:42 | 银河使者

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我就是把你的例子复制粘贴的。
同时,我看网上其他人的帖子说,要修改axis2.xml,增加<parameter name="manageTransportSession" locked="false">true</parameter>。
我试了以后还是不好使。我按照您在“WebService大讲堂之Axis2(6):跨服务会话(Session)管理”中的讲解,跨服务会话管理是好使的。
2009-04-29 10:49 | Sophie

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

老大,我这边没有local_return啊,
System.out.println(stub.getLoginMsg().local_return);
只有
System.out.println(stub.getLoginMsg().get_return());
那个LoginServiceStub也是我wsdl2java自动生成的,我那个syso能够成功运行。
2009-05-18 21:27 | Harold.Zhang

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

@Harold.Zhang
我的有啊,不知你是怎么生成的,编写和我的一样吗?
你的get_return可以返回值吗?
2009-05-18 22:25 | 银河使者

# re: WebService大讲堂之Axis2(5):会话(Session)管理[未登录]  回复  更多评论   

您好,再请教一下,我按照上面的内容,写好了webservice代码、service.xml 然后把它们打包为ws.aar,也放入到了tomcat下,接下来的调用,我没有按照上面的自动生成的代码,而是用前面的例子改了一下
public static void main(String[] args) throws Exception
{

RPCServiceClient serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
options.setManageSession(true);
String url=" http://localhost:8080/axis2/services/loginService";
EndpointReference targetEPR = new EndpointReference(url);
options.setTo(targetEPR);
Object[] opAddEntryArgs = new Object[] {"bill","1234"};
Class[] classes = new Class[] {String.class};
QName opAddEntry = new QName("http://service", "login");
System.out.println(serviceClient.invokeBlocking(opAddEntry, opAddEntryArgs, classes)[0]);

}
我这里把login的返回值稍做了修改。
但是运行这段代码,报Exception in thread "main" org.apache.axis2.AxisFault: Transport out has not been set异常,在google里搜了半天也没有好的解释……
2009-05-21 14:47 | 菜鸟

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

不使用stub有时很麻烦。我一般很少使用其他方式调用。你的那段代码就算调试成功,以后用时也会很麻烦,只是调用了一个方法,弄这么一大堆代码。关于RPC还有有其他方式,只需要了解一下原理就可以。至于真正开发时,一般都用stub。你见用过.net调用webservice用这么多代码吗?哈哈
2009-05-21 14:52 | 银河使者

# re: WebService大讲堂之Axis2(5):会话(Session)管理[未登录]  回复  更多评论   

如果使用stub,我觉得对初学的人比较麻烦的一点是,对于命令生成的代码,共有2000多行,我们应该修改那一个方法呢?自己的代码又该放到什么位置合适呢?这个感觉比较疼痛,请指教,因为我也发现如果自己写代码调用service是比较麻烦一点。另外对于异常org.apache.axis2.AxisFault: Transport out has not been set,你以前在开发时碰到过吗?
2009-05-22 14:08 | 菜鸟

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

stub不是用来修改的,是用来调用了,就将stub当成普通类好了(普通的Java类怎么用,stub类就怎么用)。

你的异常我没遇到过。我使用其他方法只是做测试。实际应用还是用stub的。否则会很麻烦。
2009-05-22 14:20 | 银河使者

# re: WebService大讲堂之Axis2(5):会话(Session)管理[未登录]  回复  更多评论   

终于知道错误原因了,String url=" http://localhost:8080/axis2/services/loginService";把http之前的空格去掉就好了,唉,真是没想到啊。呵呵。继续学习WebService大讲堂之Axis2。
2009-05-22 14:39 | 菜鸟

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

Exception in thread "main" org.apache.axis2.AxisFault: Exception occurred while trying to invoke service method login
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:512)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:370)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:416)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at service.LoginServiceStub.login(LoginServiceStub.java:199)
at service.Client.main(Client.java:16)


我按你的步骤来,总是报这个异常,为什么呢?
2009-08-30 21:05 | 冷风

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

为什么我在setProperty之后发现getProperty出来的中文是乱码?
2009-09-24 15:18 | orangehome

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

请问,我按照整个流程下来,"成功登陆"都可以正常输出,可是这一节的会话管理,重在实现session保存登录信息的功能.
为什么当我发布了WS以后,进行过一次的客户端登录,按道理已经保留了
sc.getProperty("login")的登录信息.

但是,tomcat没停,直接运行System.out.println(stub.getMessage().get_return());,打印却是null,这是什么原因呢?

所以,我觉得session管理的实现,好像没有成功.
2009-09-27 18:05 | zhangx

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

没动手操作过,只是想说一下个人的理解,不知道对不对?
加上scope="transportsession",理解就是那个服务是属于transportsession级别的服务了,也就是说这个变更在transportsession超时前这个实例对象是不会消失的,既然不会消失,就没必要放到ServiceContext中。

另外
2009-10-16 14:25 | china-qd

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

@冷风
我也遇到了这个问题,百思不得其解,还望高人指点一二
2009-11-03 10:25 | Mr.Blue

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

您好,我按照你的步骤,再没有进行第三步的情况下也能得到正确的结果,加上也能得到正确的结果,所以我怀疑是不是第三步可以省略,还是加上第三步才能确保得到正确的结果,没有第三步可能会得到正确的结果,也可能不会?
2009-11-03 11:22 | Mr.Blue

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

@zhangx
个人认为,这位兄弟对同一个WebService的Session管理这里的理解出现了偏差,你说的那个问题我想应该是跨服务会话的管理了。一点愚见
2009-12-31 18:05 | Mr.Blue

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我也按照您的代码操作,输出结果是null
2010-06-15 18:38 | nihao

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

是不是因为services.xml里少写了相应的scope配置?
2010-06-15 18:39 | nihao

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

在<service>上添加 scope="transportsession" 后就正常了. 确实是services.xml少写了这句造成的.
2010-06-15 19:05 | nihao

# re: WebService大讲堂之Axis2(5):会话(Session)管理[未登录]  回复  更多评论   

有个问题:
按照示例写的WebServices,用Java写的客户端调用,能够成功。但是用C#.net 调用时,调用getLoginMsg获取的内容为null。
难道Axis2里面的Session只能被Java写的客户端使用??
2010-09-01 17:34 | jimmy

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

楼主不出来了帮忙了么?
我和楼上同样的问题出现了,谁能指导一下?

另外,我还有二个疑问,我是用的是 scope="application“ :
第一:我 A 客户端 login 后 取值,成功了, B客户端,只做取值,居然把 A客户端设置的值取出来,为什么啊?
第二:session 的失效时间,我该从哪里设定管理呢?
第三:http://blog.csdn.net/tsun7263/archive/2009/10/204705006.aspx 这篇文章翻译了 Axis2的会话管理 。 ” 管理SOAP会话,客户端需要在SOAP头中增加名为“serviceGroupId”的参数。 “ ,我想知道如何给 SOAP头中增加名为“serviceGroupId”的参数。java代码该怎么写?
2010-11-02 17:46 | deadncut

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

您好,服务端是.net开发,客户端是JAVA,我自动生成了代码,但
运行到:
MessageContext mc = MessageContext.getCurrentMessageContext();
ServiceContext sc = mc.getServiceContext();
这两句的时候,总是报:
Exception in thread "main" java.lang.NullPointerException
很想知道为什么.我的QQ:30962620
望能答复!
2011-03-13 00:52 | 半导体

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我也是按照你上面的介绍的做了一个服务,可是客户端调用就会出现异常,
<service name="loginService" scope="transportsession">
只有这种情况调用不了。这是为什么呢。其它的都可以调用。唯有这种不可以。
2011-07-05 18:16 | ytwps

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

@Sophie
我也是啊,我发布后没找到services.xml文件,自己在META-INF下加了一个services.xml好像不起作用,应该放在哪个目录?
2011-09-15 14:43 | hduwengbin

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我在getLoginMsg方法中加了
System.out.println((String)sc.getProperty("login"));
打印出来结果也是null,应该是services.xml没起作用,我用eclipse插件发布的service 应该去哪个目录设置这个services.xml?
2011-09-15 14:50 | hduwengbin

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

LoginService 能够成功发布 但是System.out.println(stub.getLoginMsg().local_return());中getLoginMsg()方法报错 一定要加参数才行加了不知道如何解决
2012-03-27 15:38 | 12

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

下面的代码我测试过,能正常运行:
public static void main(String[] args) {
LoginServiceStub stub = null;
try {
stub = new LoginServiceStub();
} catch (AxisFault e) {
e.printStackTrace();
}

LoginServiceStub.Login login = new LoginServiceStub.Login();
login.setUsername("bill");
login.setPassword("1234");
try {
if(stub.login(login).get_return()) {
LoginServiceStub.GetLoginMsg getLoginMsg = new LoginServiceStub.GetLoginMsg();
System.out.println(stub.getLoginMsg(getLoginMsg).get_return());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}

控制台输出是:
成功登录
2012-05-12 10:49 | xiaoqing2305

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

@xiaoqing2305
用的是axis2-1.6.1
2012-05-12 11:11 | xiaoqing2305

# axis2-1.6.2 session  回复  更多评论   

axis2-1.6.2 :
if(stub.isLogin(method).get_return()){
System.out.println(stub.getLoginMsg(new MswsStub.GetLoginMsg()).get_return());
}
2012-06-24 17:30 | wen12128

# re: WebService大讲堂之Axis2(5):会话(Session)管理  回复  更多评论   

我发现最后的代码调用有一点小问题:现发出来 供大家参考
LoginServiceStub stub = new LoginServiceStub();
LoginServiceStub.Login login = new LoginServiceStub.Login();
login.setArgs0("bill");
login.setArgs1("1234");

if(stub.login(login).local_return)
{
LoginServiceStub.GetLoginMsg getlm = new GetLoginMsg();
System.out.println(stub.getLoginMsg(getlm).local_return);
}
2012-07-12 10:49 | 风云网络

只有注册用户登录后才能发表评论。


网站导航: