- 浏览: 642794 次
文章分类
最新评论
-
_____bEn-beN:
感谢楼主,太全面了
字符编码详解 -
lyl_pages:
拜托,加个密就国家就安全了?那世界上那么多国家都没加密,也没见 ...
Android 移动开发 关于LBS的一些认知 经纬度纠偏问题的研究
Ajax应用中session超时的解决方案
在程序开发过程中,碰到了一个问题,就是Ajax中Session超时后如何跳转的问题,如果
返回的是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有权操作Request和Response,所以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
相关推荐
8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。 9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。 10. 自动处理Set-Cookie中的Cookie。 11....
在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...
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 智能感知和大纲显示 ...
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 ...
15.5 常见问题与解决方案 259 15.6 小结 261 第16章 数据库中的程序逻辑 262 16.1 数据库程序逻辑与PHP程序逻辑的分体 16.1 设计原则 262 16.2 数据库中的程序逻辑与数据的关系 262 16.3 存储过程的设计 263 16.3.1 ...
42 4.8.2 解决方案 42 <br/>第5章. DWR中的JavaScript简介 44 5.1 简单的回调函数 44 5.2 调用元数据对象 45 5.3 查找回调函数 45 5.4 创造一个与Java对象匹配的Javascript对象 46 <br/...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...