`
luotuoass
  • 浏览: 642794 次
文章分类
社区版块
存档分类
最新评论

Ajax应用中session超时的解决方案

 
阅读更多
Ajax应用中session超时的解决方案

在程序开发过程中,碰到了一个问题,就是AjaxSession超时后如何跳转的问题,如果

返回的是javaScript,根本无法执行。解决办法如下:

eval函数执行javascript,但是又碰到一个问题,如果Session未超时,应该返回正常的数据,怎么办呢?google了一下,下面这篇文章给出了解决方案。

不过我用的是Struts2,用的是Interceptor实现的权限认证。(Interceptor介绍参考:http://www.blogjava.net/max/archive/2006/12/06/85925.html

景:一个基于Ajax技术Web用,采用的是多面方式,每面内部使用Ajax实现复杂业务逻辑的无刷新切,使用了Struts来实现MVC

问题
Ajax求,只有在通户验证之后才能对请求作出响。如果用户长时间不做操作Session过时之后才求,时应该到出错页面,提示用重新登于非Ajax求,可以自定异常并针对此异常置相的出错页面。在用信息验证候直接抛出此异常即可,web容器会自动捕捉到此异常并且示出错页面;但是,Ajax求,不会如期待的那到出错页面。若不特殊理,Ajax求的回函数会得到意想不到的数据而致程序出

分析:对于一个Ajax的应用,一次客和服务器的数据交互,可以看成是在一个由客端的XMLHttpRequest和服务器端的Servlet(里假Servlet响应Ajax)成的合管道(如1)中进行的:

<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="" style='width:299.25pt; height:86.25pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:href="http://p.blog.csdn.net/images/p_blog_csdn_net/rikuseiha/1.bmp"/> </v:shape><![endif]-->

1

所有从服务器端得到的数据流都会被XMLHttpRqeuest对象获得,然后由回调函数做出相应处理。
一般而言,用户登录之后,将用户信息是存放在Session中。做用户验证,其实就是检查此时Session中用户信息是否存在或者是否正确。如果在每次逻辑处理之前都去做这样的重复检查,并且检查的方法会发生改变,这样的程序既不精简还缺少可维护性。相信很少有人这么做。
比较好的做法是使用Filter
Servlet2.3之后才行)来做这样的通用检查,简单而且修改规则也很容易。Filter在应用中的作用之处如图2所示:

<!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" alt="" style='width:299.25pt;height:86.25pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image003.png" o:href="http://p.blog.csdn.net/images/p_blog_csdn_net/rikuseiha/2.bmp"/> </v:shape><![endif]-->
2

另外,还可以添加具有不同功能的Filter,形成一个Filter链。
可以看到,在请求还没有到达Servlet之前,可以对请求作一些处理之后再提交给Servlet;在Servlet发出响应但还没有到达客户端之前,还可以对响应作处理。因此,作用户检查之类的工作由Filter来完成是比较合理的。
并不是说经过Filter的请求最终一定会到达Servlet。因为Filter有权操作RequestResponse,所以Filter完全可以自己向客户端直接返回响应,从而中止此次交互:

<!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" alt="" style='width:299.25pt;height:86.25pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image005.png" o:href="http://p.blog.csdn.net/images/p_blog_csdn_net/rikuseiha/3.bmp"/> </v:shape><![endif]-->
3

如图3所示,若是检查用户信息失败,Filter可以直接返回响应。
到这里,应该比较清楚了,在用户信息验证出错情况下,若要使得客户端能自动显示出错提示页面,应该让Ajax请求所对应的回调函数去做。
如果只是很简单的少数请求,则可以在Filter中返回出错标志,然后在回调函数中作判断进行相应的页面跳转处理。但是,对于一个复杂的应用,如果每个回调函数中都要添加这样的判断,或者服务器端定义的出错标志发生改变,则会大大降低程序的可维护性。
对于稍稍复杂的Ajax应用,一般都会使用一个共通的模块来操作Ajax的请求(比如创建跨浏览器的XMLHttpRequest对象等等)。如果能在这样的通用模块中具有可以在回调函数被调用之前获得服务器返回数据的能力,则可以做通用的出错判断,而不必修改每一个回调函数。
比如下面的这个通用模块:

<!--[if gte vml 1]><v:shape id="_x0000_i1028" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image007.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104022542.gif"/> </v:shape><![endif]-->functionsendRequest(callback,data,method,url,async,sload,user,password)
<!--[if gte vml 1]><v:shape id="_73_537_Open_Image" o:spid="_x0000_i1029" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image008.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104022768.gif"/> </v:shape><![endif]-->{
<!--[if gte vml 1]><v:shape id="_x0000_i1030" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
//创建XMLHttpRequest对象
<!--[if gte vml 1]><v:shape id="_x0000_i1031" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
varoj=createHttpRequest();
<!--[if gte vml 1]><v:shape id="_x0000_i1032" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
if(oj==null)returnnull;
<!--[if gte vml 1]><v:shape id="_x0000_i1033" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->...
<!--[if gte vml 1]><v:shape id="_201_309_Open_Image" o:spid="_x0000_i1034" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023928.gif"/> </v:shape><![endif]-->
if(typeofcallback=='object'){
<!--[if gte vml 1]><v:shape id="_x0000_i1035" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
varcallback_onload=callback.onload;
<!--[if gte vml 1]><v:shape id="_x0000_i1036" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
varcallback_onbeforsetheader=callback.onbeforsetheader;
<!--[if gte vml 1]><v:shape id="_316_396_Open_Image" o:spid="_x0000_i1037" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023928.gif"/> </v:shape><![endif]-->}
else{
<!--[if gte vml 1]><v:shape id="_x0000_i1038" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
varcallback_onload=callback;
<!--[if gte vml 1]><v:shape id="_x0000_i1039" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
varcallback_onbeforsetheader=null;
<!--[if gte vml 1]><v:shape id="_x0000_i1040" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image011.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023453.gif"/> </v:shape><![endif]-->}
<!--[if gte vml 1]><v:shape id="_x0000_i1041" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
<!--[if gte vml 1]><v:shape id="_425_459_Open_Image" o:spid="_x0000_i1042" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023928.gif"/> </v:shape><![endif]-->oj.onload=
function(){
<!--[if gte vml 1]><v:shape id="_x0000_i1043" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->callback_onload(oj);
<!--[if gte vml 1]><v:shape id="_x0000_i1044" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image011.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023453.gif"/> </v:shape><![endif]-->}
<!--[if gte vml 1]><v:shape id="_x0000_i1045" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->...
<!--[if gte vml 1]><v:shape id="_x0000_i1046" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->oj.open(method,url,async,user,password);
<!--[if gte vml 1]><v:shape id="_x0000_i1047" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->...
<!--[if gte vml 1]><v:shape id="_x0000_i1048" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->oj.send(data);
<!--[if gte vml 1]><v:shape id="_x0000_i1049" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image012.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023625.gif"/> </v:shape><![endif]-->}

可以在callback_onload(oj);之前添加对出错标志的判断。到此处,问题已经得到解决。
如果以后要更改出错标志或者是出错页面,则此处也要做相应的更改才行。如何能更智能一点呢?
既然Filter可以返回出错标志,那当然也可以返回javascript代码了!如果能在此处动态地执行一段代码,不就解决问题了吗?想到javascript
eval函数了吧!对,就是它!代码很简单:

<!--[if gte vml 1]><v:shape id="_24_103_Open_Image" o:spid="_x0000_i1050" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image008.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104022768.gif"/> </v:shape><![endif]-->oj.onload=function(){
<!--[if gte vml 1]><v:shape id="_32_61_Open_Image" o:spid="_x0000_i1051" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023928.gif"/> </v:shape><![endif]-->
try{
<!--[if gte vml 1]><v:shape id="_x0000_i1052" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
eval(oj.responseText);
<!--[if gte vml 1]><v:shape id="_73_74_Open_Image" o:spid="_x0000_i1053" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023928.gif"/> </v:shape><![endif]-->}
catch(e){}
<!--[if gte vml 1]><v:shape id="_x0000_i1054" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->
<!--[if gte vml 1]><v:shape id="_x0000_i1055" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023300.gif"/> </v:shape><![endif]-->callback_onload(oj);
<!--[if gte vml 1]><v:shape id="_x0000_i1056" type="#_x0000_t75" alt="" style='width:8.25pt;height:12pt'> <v:imagedata src="file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image012.gif" o:href="http://www.xrss.cn/XrssFile/2007-11/23/20071123104023625.gif"/> </v:shape><![endif]-->}

如果是正常情况下返回的数据,eval函数执行后不会引起程序异常;如果是一段javascript代码,则会得到执行,客户端的Ajax调用也不要做任何修改。

返回到Filter,若是用户验证失败,并且是Ajax请求可以返回一段让页面自动跳转的javascript代码;若是普通的非Ajax请求,则可以放心地抛出异常。经过验证,在Ajax请求和非Ajax请求的情况下,二者的客户体验是相同的。对于页面跳转,其实方法很多,这里就省略代码了。
同理,如果继续添加用户权限检查等等的Filter,则可以地向客户端发出各种不同的javascript代码,很轻松实现相应的功能而客户端无需作修改。

总结:对于Ajax的请求,其数据流是封闭的,服务器发送给在客户端的数据都被XMLHttpRequest对象所获得。本文通过从Filter中发出javascript代码让其在客户端得到执行,从而可以在session过时验证用户信息失败之后,让客户端自动显示出错页面,与非Ajax请求时的客户体验相一致。对于Ajax请求,此方法进一步推广,可以直接在服务器端发出javascript让其在客户端得到执行。

原文来源:http://www.xrss.cn/Dev/AJAX/2007112317765.Html

分享到:
评论

相关推荐

    HttpClient以及获取页面内容应用

    8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。 9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。 10. 自动处理Set-Cookie中的Cookie。 11....

    JAVA上百实例源码以及开源项目

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

    ASP.NET4高级程序设计(第4版) 3/3

    2.2.1 解决方案资源管理器 28 2.2.2 文档窗口 29 2.2.3 工具箱 29 2.2.4 错误列表和任务列表 30 2.2.5 服务器资源管理器 31 2.3 代码编辑器 32 2.3.1 添加程序集引用 33 2.3.2 智能感知和大纲显示 ...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    2.2.1 解决方案资源管理器 2.2.2 文档窗口 2.2.3 工具箱 2.2.4 错误列表和任务列表 2.2.5 服务器资源管理器 2.3 代码编辑器 2.3.1 添加程序集引用 2.3.2 智能感知和大纲显示 2.3.3 Visual Studio ...

    php网络开发完全手册

    15.5 常见问题与解决方案 259 15.6 小结 261 第16章 数据库中的程序逻辑 262 16.1 数据库程序逻辑与PHP程序逻辑的分体 16.1 设计原则 262 16.2 数据库中的程序逻辑与数据的关系 262 16.3 存储过程的设计 263 16.3.1 ...

    DWR中文文档.pdf

    42 4.8.2 解决方案 42 &lt;br/&gt;第5章. DWR中的JavaScript简介 44 5.1 简单的回调函数 44 5.2 调用元数据对象 45 5.3 查找回调函数 45 5.4 创造一个与Java对象匹配的Javascript对象 46 &lt;br/...

    java开源包1

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包11

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包2

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包3

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包6

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包5

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包10

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包4

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包8

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包7

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包9

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包101

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    Java资源包01

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

Global site tag (gtag.js) - Google Analytics