[Android实例] 同一个session通信的解决方案

来源:互联网 发布:淘宝卖家帐号被冻结 编辑:程序博客网 时间:2024/06/02 05:44
如果你的应用需要与服务器端的Web程序进行交互,肯定与遇到我下面说的这个问题。
       有天开发Web应用的小孙告诉我,他的Web应用从tomcat控制台查看,连接数上百了,这对于正常的应用没什么,但是我们是测试环境啊,只有我们三个Android开发人员,哪有那么多的链接数呢,最后发现,只要我点击手机上的关于服务器交互的应用,就会产生一个连接数,这可要人命,以前没开发过android的正式产品。最后发现原来是如果浏览器访问Web端,一个用户产生一个Session连接,由于手机上开发时session需要自己的程序管理,我们又不知道还要这么搞才出现这种情况。搜索各大帖子,大家的普遍做法是:获取服务器端的一个sessionId,然后保存到一个变量里,每次请求的时候将SessionId传递过去,这样服务器端接到请求以后,发现系统中这个session是存在的,就不会生成新的了。
代码如下:
  1. public static String httpPost(Map<String, Object> map) {
  2.                 String result = ""; // 获取服务器返回数据
  3.                 String param = JSON.toJSONString(map);

  4.                 // Log.i(App.Log.app_name,"加密前的数据:"+param);

  5.                 String method = map.get("method").toString();
  6.                  
  7.                 // 加密
  8.                 BASE64Encoder base64encoder = new BASE64Encoder();
  9.                 String sendMsg = null;
  10.                 HttpURLConnection urlConn=null;
  11.                 try {
  12.                         sendMsg = base64encoder.encode(param.getBytes("utf-8"));
  13.                         // Log.i(App.Log.app_name,"加密后的数据:"+sendMsg);

  14.                         if (sendMsg != null) {
  15.                                 URL _url = new URL(SERVICEURL);
  16.                                 //_url.openConnection(proxy);
  17.                                 urlConn= (HttpURLConnection) _url.openConnection();
  18.                                 createSession();
  19.                                 if(null!=App.sessionId || !"".equals(App.sessionId)){
  20.                                         Log.e(App.Log.app_name,"App.sessionId="+App.sessionId);
  21.                                         urlConn.setRequestProperty("Cookie", App.sessionId);
  22.                                 }
  23.                                  
  24.                                 urlConn.setDoInput(true); // 设置输入流采用字节流
  25.                                 urlConn.setDoOutput(true); // 设置输出流采用字节流
  26.                                 urlConn.setRequestMethod("POST");
  27.                                 urlConn.setUseCaches(false); // 设置缓存
  28.                                 urlConn.setRequestProperty("Charset", "utf-8");
  29.                                 urlConn.setConnectTimeout(CONNECTION_TIMEOUT_INT);
  30.                                 urlConn.setReadTimeout(READ_TIMEOUT_INT);
  31.                                 urlConn.setRequestProperty("Content-Type", "application/json");
  32.                                 urlConn.setRequestProperty("Accept", "application/json");
  33.                                  
  34.                                 //urlConn.getAllowUserInteraction();
  35.                                 urlConn.getPermission();
  36.                                 urlConn.connect(); // 连接既往服务端发送消息

  37.                                 BufferedOutputStream dop = new BufferedOutputStream(
  38.                                                 urlConn.getOutputStream());

  39.                                 dop.write(sendMsg.getBytes("utf-8")); // 发送参数
  40.                                 dop.flush(); // 发送,清空缓存
  41.                                 dop.close(); // 关闭
  42.                                 int status = urlConn.getResponseCode();
  43.                                 Log.e(App.Log.app_name,urlConn.getResponseMessage());
  44.                                 if (status != 200) {

  45.                                 } else {
  46.                                         // 下面开始做接收工作
  47.                                         BufferedReader bufferReader = new BufferedReader(
  48.                                                         new InputStreamReader(urlConn.getInputStream()));

  49.                                         String readLine = null;
  50.                                         while ((readLine = bufferReader.readLine()) != null) {
  51.                                                 result += readLine;
  52.                                         }
  53.                                         bufferReader.close();
  54.                                         urlConn.disconnect();
  55.                                 }
  56.                                 return result;
  57.                         } else {
  58.                                 System.out.println("param is null");
  59.                         }

  60.                 } catch (Exception e) {

  61.                         if ("sendCallinLog".equals(method)) {
  62.                                 Log.i(App.Log.app_name, "来电信息传递发生异常");
  63.                                 result = "false";
  64.                                 e.printStackTrace();
  65.                         } else {
  66.                                 e.printStackTrace();
  67.                         }

  68.                 }
  69.                 return result;
  70.         }
复制代码
特别是这几句话是我刚修改的:
  1. if(null!=App.sessionId || !"".equals(App.sessionId)){
  2. Log.e(App.Log.app_name,"App.sessionId="+App.sessionId);
  3. urlConn.setRequestProperty("Cookie", App.sessionId);
  4. }
复制代码
添加一个Cookie的属性,传递过去。
接着就是如何获取sessionId,以及何时生成了。
其实获取很容易:
我单独写了一个方法:
  1. public static String getSessionId(){
  2.                  
  3.                 URL _url;
  4.                 String sessionid=null;
  5.                 try {
  6.                         _url = new URL(SERVICEURL);
  7.                         
  8.                         HttpURLConnection con= (HttpURLConnection) _url.openConnection();
  9.                         
  10.                         // 取得sessionid.
  11.                         String cookieval = con.getHeaderField("Set-Cookie");
  12.                         
  13.                         if(cookieval != null) {
  14.                             sessionid = cookieval.substring(0, cookieval.indexOf(";"));
  15.                         }
  16.                         
  17.                         
  18.                    //App.sessionId=sessionid;
  19.                         
  20.                         con.disconnect();
  21.                 } catch (Exception e) {
  22.                         // TODO Auto-generated catch block
  23.                         e.printStackTrace();
  24.                 }
  25.                  
  26.                 return sessionid;
  27.         }

复制代码
说到这个方法,大家会想,多次一举,为什么创建一个URL,又openConnection()。在httpPost方法里获取不就可以了吗?我尝试了很多次了,会报错的。查阅了一下,大概的意思是
String cookieval = con.getHeaderField("Set-Cookie");
这句代码不能放在 urlConn.setRequestProperty("Cookie", App.sessionId); 前面执行,也就是没办法同时用一个connection对象即获得sessionId又将sessionID传递到服务器端。只好又生成一个,而且每次调用openConnection(),服务器端都会生成一个新的session。
以上是一个插曲。小弟才疏学浅,不明白其中缘由,哪位大哥知道的话可以留言啊。
接着说,有生成sessionId的方法,有传递的载体了,我们需要考虑何时生成sessionId,因为每调用一次生成SessionId的方法就会生成一个连接的。
时机是:当我们的全局变量为空的时候生成。但是问题来了,如果用户长时间不操作,呆在一个界面,一会服务器端的session失效了,他又开始操作界面的时候,服务器端又会不断生成链接,为什么呢?因为我们每次传递给他的sessionId都是过期的啊。
完美的解决方法是:我们能通过一种途径去获取到服务器对应的session已失效,但是,我没有找到。
最后用了一个折中的办法,让客户端生成一个时间戳,开始计时,如果超过15分钟不操作界面,那么我们就获取一个新的sessionId(服务器端定的session有效期为20分钟,也就是在它没有失效之前就已经生成新的sessionId了,这样session就永远不会失效了)。代码如下:
  1. public synchronized static void createSession() {
  2.                   

  3.                         if(null==App.sessionId || "".equals(App.sessionId)){
  4.                                 App.sessionId=getSessionId();
  5.                                 System.out.println("session创建!");
  6.                                 sessionCreateTime=new Date().getTime();
  7.                         }
  8.                         
  9.                         //20分钟后更换session
  10.                                 long nowTime=new Date().getTime();
  11.                                 int min=(int)((nowTime-sessionCreateTime)/(1000*60));
  12.                         if(min>=15){
  13.                                 App.sessionId=getSessionId();
  14.                                 System.out.println("session重新创建!");
  15.                                 sessionCreateTime=new Date().getTime();
  16.                         }else{
  17.                                 sessionCreateTime=new Date().getTime();
  18.                         }
  19.                
  20.             }
复制代码
这样,已登录成功就会只有一个或者两个session了。
貌似解决了问题,但是,如果客户端没有退出,这时服务器端重启了,那么情况就又回到了原来的情况,不过正是的应用,服务器端重启都是在用户都不太使用的时间段。但是如果能获取到服务器端的session已失效这种状态就彻底可以解决这个问题了。
以上就是我的一个思路与解决方案,我把它写了下来,你呢?说说你的看法吧。
0 0
原创粉丝点击