有关JNLP中传SESSIONID为参数的问题
2009-06-11 16:55
459 查看
现有项目组用SUN JDK1.5中自带的示例:jnlp-servlet作为WEBSTART版本管理的SERVLET。它可以很好的实现JNLP相关资源(JAR,图片等)的基于版本的管理和增量更新。并有几个类似$$codebase,$$name的可替换关键字。(原来写了一个简单的servlet,可以实现软编码,但没法提供灵活的版本控制)
但现有项目的需求更高一些,即,JNLP中需要传更多的参数,比如,服务端IP,端口,上下文,用户登录的SESSIONID等,由于jnlp-servlet有源代码,我们很快修改了JnlpFileHandler和specializeJnlpTemplate方法,并加入了这几个自定义关键字($$host,$$port,$$newcontext,$$sessionid)。JNLP如下所示:
其中,SESSIONID是用其内部的request得到。
一切好象即简单和明了,工作正常,但很快就发现了严重的问题。
首先说说该应用的使用模式如下:
1、 用户从网页登录系统,然后在里面点击:http://host:port/myapp/swt/index.jnlp链接。
2、 启动应用(因为应用是跟当前登录SESSION直接相关的)
按照设计本意,此时,用户的应用应通过JNLP中的参数得到了该用户登录后的SESSIONID才对,但事实并非如此。这种情况只出现在WEBSTART第一次下载的时候,以后当用户重新打开浏览器登录后(此时当然是一个新的SESSION),在页面中启动WEBSTART后,发现,该SESSIONID还是以前的,并没有想象中的将新SESSIONID传了进来。
后来还是看看JnlpFileHandler中的源代码,发现主要在getJnlpFile(客户端是JRE1.5以下时调用)和getJnlpFileEx(客户端是JDK1.5以上时用)进行了相关实现。原来,它每生成一个JNLP,就将其缓存在HASHMAP中,下一次请求,如果请求的URL相关并且文件的timestamp(就是Web服务器中的jnlp文件的修改时间,可想而知,除了升级,这个文件一般不会变)一样,就从缓存中取,这样一来,我们也可以推测,按照上面的设计,如果有一个用户下载了应用,其它用户从其它机器下载到的JNLP还是第一个用户的JNLP,这是一个更加严重的问题。
由于URL是一样的,现在考虑更改时间戳,即在getJnlpFile中显式的将timesstamp改为当前的时间:
long lastModified = new java.util.Date().getTime();
这样,任何一次请求都不会从缓存中获得,而是重新生成一个,好象这能很好的解决这个问题了吧?
但事实远没有想象的那么简单。这跟WEBSTART与服务端的交互过程有关系。
WEBSTART要通过多次从服务端交互才会真正下载JNLP文件,这主要是验证一些时间等相关的属性(具体我没有看代码)。大至是三次才会真正的把JNLP下载下来(其实服务端会生成三次,真正下载的是第三个),由于我们的SESSIONID是从SERVLET内部的REQUEST中直接得到,这样一来,实际上只有第一个请求的SESSIONID是正确的(因为它是直接从浏览器中进入的),其它两个都是WEBSTART用URLConnection建立的连接,SESSIONID都是新生成的,而下载的恰恰又是第三个,这样一来,又黄了!!!
接下来的想法是自己设法传SESSIONID,而不是从当前REQUEST中取。所以,就刚才启动WEBSTART的链接改为如下形式:
<a href="/myapp/swt/index.jnlp?sessionid=<%=request.getSession().getId()%>">启动客户端程序</a>
这样,生成的URL会是:、
http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78
按照前面的JNLP文件,下载下来的JNLP第一行是:
<jnlp spec="1.0+" codebase="http://127.0.0.1:8899/myapp/swt/" href=” http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78”>
既然有了SESSIONID(这意味着每个请求的URL都不会一样!),我们就用不着将时间戳改为当前时间了,还按原来的做就行了。
到此为止,好像问题解决的很彻底哦!但不要高兴的太早!!!!!
我们同样做实验:
1、 将WEBSTART应用清空
2、 登录系统,下载安装应用并运行,一切OK!
3、 退出该系统
4、 打开新的浏览器并登录
5、 点相应的链接启动WEBSTART应用
6、 怪了:SESSIONID怎么还是前面的一个呢?
查看jnlp-servlet日志,刚才说了,要经过多次握手才会实际的下载JNLP,从流程中发现,客户端发的请求,第一个是对的即是
http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78
SESSION是最新的,但第二个请求,SESSION怎么就是以前的呢?
原来,WEBSTART在经过第一次握手之后,发现本地有该应用,就用该应用JNLP中的href字段发送下面的请求,导致了刚才的问题。
后面的解决办法说起来就没什么了,直接去掉href字段就行了,如下片段:
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="$$codebase">
这样,每次都用新的URL去请求了!!
说来说去,只是过程,其它代码中改得并不多,主要是增加了SESSION参数。
在以后动态更改应用的MAIN类时,思路也差不多。
但现有项目的需求更高一些,即,JNLP中需要传更多的参数,比如,服务端IP,端口,上下文,用户登录的SESSIONID等,由于jnlp-servlet有源代码,我们很快修改了JnlpFileHandler和specializeJnlpTemplate方法,并加入了这几个自定义关键字($$host,$$port,$$newcontext,$$sessionid)。JNLP如下所示:
<?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" codebase="$$codebase" href="”$$name”" mce_href="”$$name”"> <information> <title>My System</title> <vendor>CFR</vendor> <icon href="indexbannerleft.jpg" mce_href="indexbannerleft.jpg" kind="splash" /> <homepage href="index.html" mce_href="index.html"/> <description>My System</description> <description kind="short">CFR Inc..</description> </information> <security><all-permissions/></security> <resources> <j2se version="1.4" initial-heap-size="32m"/> <jar href="myapp.jar" mce_href="myapp.jar" version="1.1"/> <nativelib href="swt-lib.jar" mce_href="swt-lib.jar" version="1.1"/> </resources> <resources os="Windows"><jar href="swt.jar" mce_href="swt.jar" version="1.1"/></resources> <resources os="Windows"><jar href="jface.jar" mce_href="jface.jar" version="1.0"/></resources> <resources os="Windows"><jar href="osgi.jar" mce_href="osgi.jar" version="1.0"/></resources> <resources os="Windows"><jar href="runtime.jar" mce_href="runtime.jar" version="1.0"/></resources> <application-desc main-class="com.cfr.app.main"> <argument>$$session</argument> <argument>$$host</argument> <argument>$$port</argument> <argument>$$newcontext</argument> <argument>0</argument> <argument>aa</argument> </application-desc> </jnlp>
其中,SESSIONID是用其内部的request得到。
一切好象即简单和明了,工作正常,但很快就发现了严重的问题。
首先说说该应用的使用模式如下:
1、 用户从网页登录系统,然后在里面点击:http://host:port/myapp/swt/index.jnlp链接。
2、 启动应用(因为应用是跟当前登录SESSION直接相关的)
按照设计本意,此时,用户的应用应通过JNLP中的参数得到了该用户登录后的SESSIONID才对,但事实并非如此。这种情况只出现在WEBSTART第一次下载的时候,以后当用户重新打开浏览器登录后(此时当然是一个新的SESSION),在页面中启动WEBSTART后,发现,该SESSIONID还是以前的,并没有想象中的将新SESSIONID传了进来。
后来还是看看JnlpFileHandler中的源代码,发现主要在getJnlpFile(客户端是JRE1.5以下时调用)和getJnlpFileEx(客户端是JDK1.5以上时用)进行了相关实现。原来,它每生成一个JNLP,就将其缓存在HASHMAP中,下一次请求,如果请求的URL相关并且文件的timestamp(就是Web服务器中的jnlp文件的修改时间,可想而知,除了升级,这个文件一般不会变)一样,就从缓存中取,这样一来,我们也可以推测,按照上面的设计,如果有一个用户下载了应用,其它用户从其它机器下载到的JNLP还是第一个用户的JNLP,这是一个更加严重的问题。
由于URL是一样的,现在考虑更改时间戳,即在getJnlpFile中显式的将timesstamp改为当前的时间:
long lastModified = new java.util.Date().getTime();
这样,任何一次请求都不会从缓存中获得,而是重新生成一个,好象这能很好的解决这个问题了吧?
但事实远没有想象的那么简单。这跟WEBSTART与服务端的交互过程有关系。
WEBSTART要通过多次从服务端交互才会真正下载JNLP文件,这主要是验证一些时间等相关的属性(具体我没有看代码)。大至是三次才会真正的把JNLP下载下来(其实服务端会生成三次,真正下载的是第三个),由于我们的SESSIONID是从SERVLET内部的REQUEST中直接得到,这样一来,实际上只有第一个请求的SESSIONID是正确的(因为它是直接从浏览器中进入的),其它两个都是WEBSTART用URLConnection建立的连接,SESSIONID都是新生成的,而下载的恰恰又是第三个,这样一来,又黄了!!!
接下来的想法是自己设法传SESSIONID,而不是从当前REQUEST中取。所以,就刚才启动WEBSTART的链接改为如下形式:
<a href="/myapp/swt/index.jnlp?sessionid=<%=request.getSession().getId()%>">启动客户端程序</a>
这样,生成的URL会是:、
http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78
按照前面的JNLP文件,下载下来的JNLP第一行是:
<jnlp spec="1.0+" codebase="http://127.0.0.1:8899/myapp/swt/" href=” http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78”>
既然有了SESSIONID(这意味着每个请求的URL都不会一样!),我们就用不着将时间戳改为当前时间了,还按原来的做就行了。
到此为止,好像问题解决的很彻底哦!但不要高兴的太早!!!!!
我们同样做实验:
1、 将WEBSTART应用清空
2、 登录系统,下载安装应用并运行,一切OK!
3、 退出该系统
4、 打开新的浏览器并登录
5、 点相应的链接启动WEBSTART应用
6、 怪了:SESSIONID怎么还是前面的一个呢?
查看jnlp-servlet日志,刚才说了,要经过多次握手才会实际的下载JNLP,从流程中发现,客户端发的请求,第一个是对的即是
http://localhost:8899/myapp/swt/index.jnlp?sessionid=F8864B2CDF60AE371CD6DFC189E80C78
SESSION是最新的,但第二个请求,SESSION怎么就是以前的呢?
原来,WEBSTART在经过第一次握手之后,发现本地有该应用,就用该应用JNLP中的href字段发送下面的请求,导致了刚才的问题。
后面的解决办法说起来就没什么了,直接去掉href字段就行了,如下片段:
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="$$codebase">
这样,每次都用新的URL去请求了!!
说来说去,只是过程,其它代码中改得并不多,主要是增加了SESSION参数。
在以后动态更改应用的MAIN类时,思路也差不多。
相关文章推荐
- 有关JNLP中传SESSIONID为参数的问题
- 16-使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 有关jsp中的response.sendRedirect()中文参数的问题
- 有关java的函数调用返回值的问题和参数传递问题
- 解决有关flask-socketio中服务端和客户端回调函数callback参数的问题
- Request.QueryString 接受参数时,跟编码有关的一些问题
- lib函数添加功能但是函数名和参数不变,重新封装成DLL有关问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 一个有关JS参数的问题
- 关于delphi调用vc编写的dll中参数类型有关问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 解决SQL中in参数在存储过程中的传递有关问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- struts2重定向中文参数乱码有关问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 使用 Request.QueryString 接受参数时,跟编码有关的一些问题
- 有关va_list和vsnprintf输出函数的问题(可变参数)
- 有关C++参数传值的一个问题探讨