【现象】
在ajax通过web代理跨域访问时,http第一次登陆时正常,但是第二次再下发其他命令的时候总是返回 java.net.SocketTimeoutException: Read timed out 。
【定位思路】
第一次登陆正常,第二次再访问就不行,说明大多数是和cookie相关。页面在登陆的时候设置cookie是成功的,那么大部分的原因应该是在web代理部分cookie的传输有问题了。仔细看了代理部分的代码,发现web代理部分建立新的http请求的时候,并没有添加cookie。然后上网查找cookie的获得和添加方式。添加上就可以了。
【前台页面代码】
登陆代码:
function DoLogin() { m_szUserPwdValue = Base64.encode("admin" + ":" + "12345"); $.ajax({ type: "GET", url: m_lHttp + m_szHostName + ":" + m_lHttpPort + "/onlineObservationSystem/PSIA/Custom/SelfExt/userCheck", async: true, timeout: 15000, beforeSend: function(xhr) { xhr.setRequestHeader("If-Modified-Since", "0"); xhr.setRequestHeader("Authorization", "Basic " + m_szUserPwdValue); }, success: function(xmlDoc, textStatus, xhr) { alert("login success"); if("200" == xhr.status) { var szUrl = decodeURI(document.URL); if(szUrl.indexOf("?page=") != -1) { var szPage = szUrl.substring(szUrl.indexOf("page=") + 5, szUrl.indexOf("¶ms=")); if(szPage.indexOf(".asp") == -1) { szPage = szPage.concat(".asp"); } var szParam = szUrl.substring(szUrl.indexOf("¶ms=") + 8, szUrl.length); $.cookie('page',szPage+"?"+szParam+"%1"); } else { $.cookie('page',null); } //登陆的时候在这里添加cookie $.cookie('userInfo'+'80',m_szUserPwdValue==""?Base64.encode("anonymous:177177177177177177"):m_szUserPwdValue); //window.location.href = "IEfile/doc/page/main.asp"; } else { if(!$('#UserName').prop("disabled")) { $('#UserName').focus(); } $('#UserName').val(''); $('#Password').val(''); alert(translator.translateNode(g_lxdLogin, 'LoginTips4')); } }, error: function(xhr, textStatus, errorThrown) { alert("login error = " + textStatus); if("timeout" == textStatus) { alert(translator.translateNode(g_lxdLogin, 'ConnectTimeoutTips')); } else { alert(translator.translateNode(g_lxdLogin, 'NetworkErrorTips')); } } }); }
第二次访问的代码:
function GetPatrolsCab() { $.ajax({ type: "GET", url: m_lHttp + m_szHostName + ":" + m_lHttpPort + "/onlineObservationSystem/PSIA/PTZ/channels/1/patrols", async: true, timeout: 15000, beforeSend: function(xhr) { xhr.setRequestHeader("If-Modified-Since", "0"); xhr.setRequestHeader("Authorization", "Basic " + m_szUserPwdValue); }, success: function(xmlDoc, textStatus, xhr) { var iLen = $(xmlDoc).find('PTZPatrol').length; if(0 == iLen) { alert("get path success,but iLen=0"); //m_oPtzTabs.hideTab(1); return; } $("#selectPatrol").empty(); var szName = parent.translator.translateNode(g_lxdPreview, 'laTrack'); for(var i = 0; i < iLen; i++) { if (i < 9) { $("<option value='"+ (i+1) +"'>"+szName+" 0"+(i+1)+"</option>").appendTo("#selectPatrol"); } else { $("<option value='"+ (i+1) +"'>"+szName+" "+(i+1)+"</option>").appendTo("#selectPatrol"); } } $("#selectPatrol").unbind().bind("change",function() { GetPatrol(this.value); }); GetPatrolsDelayCab(); }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert("get path error"); //m_oPtzTabs.hideTab(1); } }); }
【web代理代码,就是servlet端代码】
package com.boomdts.weather_monitor.servlet.video; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.util.List; import javax.servlet.*; import javax.servlet.http.*; public class psiaFilter implements javax.servlet.Filter { public void destroy() { } //char数组转换成byte数组 private byte[] getBytes (char[] chars) { Charset cs = Charset.forName ("UTF-8"); CharBuffer cb = CharBuffer.allocate (chars.length); cb.put (chars); cb.flip (); ByteBuffer bb = cs.encode (cb); return bb.array(); } //byte数组转换成char数组 private char[] getChars (byte[] bytes) { Charset cs = Charset.forName ("UTF-8"); ByteBuffer bb = ByteBuffer.allocate (bytes.length); bb.put (bytes); bb.flip (); CharBuffer cb = cs.decode (bb); System.out.println("in size=" + bytes.length + "out size = " + cb.array().length); return cb.array(); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //根据当前请求内容获得请求的各个参数 HttpServletRequest req = (HttpServletRequest)(request); String uri = req.getRequestURI(); uri = uri.substring(24);//删除当前项目名称的字符串 String Auth = req.getHeader("Authorization"); String method = req.getMethod(); Cookie[] cookies = req.getCookies();//取得cookie,这个原来是没有添加的 HttpServletResponse res = (HttpServletResponse)(response); //发起一个新的http连接,设置新建连接的参数(就是把刚才请求的参数设置成新的连接的参数)。 String url= "http://172.16.8.178" + uri; //System.out.println("url = " + url); URL theURL = new URL(url); HttpURLConnection urlConnection = (HttpURLConnection)theURL.openConnection(); urlConnection.setReadTimeout(500000); System.out.println("method = " + method); urlConnection.setRequestMethod(method); urlConnection.setRequestProperty("If-Modified-Since", "0"); urlConnection.setRequestProperty("Authorization", Auth); for(Cookie c:cookies){ urlConnection.addRequestProperty("Cookie", c.getName() + "=" + c.getValue());//添加cookie,这个原来是没有添加的 //System.out.println("cookie name=" + c.getName() +"; value=" + c.getValue()); } urlConnection.connect(); PrintWriter out = res.getWriter(); //取得http连接响应数据,并把响应数据返回前台页面 if (urlConnection.getResponseCode() == 200) { System.out.println("urlConnection return success"); //解析返回信息 InputStream in = urlConnection.getInputStream(); int c; while((c = in.read()) != -1) out.write(c); } else { System.out.println("error! urlConnection.getResponseCode() = " + urlConnection.getResponseCode()); } } public void init(FilterConfig arg0) throws ServletException { } }
相关内容请参考我的另外两篇博客: