android保持Session会话

在服务端完成实现app在线用户列表的功能,无论是HttpSessionListener还是HttpSessionBindingListener都依赖session机制。但app未退出,服务端的session会话就销毁了,导致无法正确监测到app用户的在线情况。

1.session的生命周期

当服务端接收到请求时,服务端会为其分配一个session会话

这个session会话有一个最大保存时间MaxInactiveInterval,当用户的不活动状态超过这个时间,session会销毁

如果是网页端,当用户注销或者退出浏览器时,session会销毁

2.android无法保持会话的原因

网页端的每次请求都是活动,将重置session会话的时间,实现持久访问

android端就不同了,它的请求头中是不带sessionId的,所以服务端无法识别它访问的是哪个session,也无法识别请求来自于哪个session

3.解决问题

建议大家安装 FireFox浏览器,它的检查功能是真的好用,比谷歌浏览器好用

写个servlet,运行服务端,网页里加个css外链

用FireFox打开网页并检查

注意到高亮的Cookie:JSESSIONID=70943E03B9683A966235579F4D57892F,打印session.getId()验证,发现这个JSESSIONID就是本次session的sessionId

如何查看android访问服务端的请求头呢?在servlet添加以下代码:

Cookie[] Cookies = request.getCookies();

for(int i =0;i

Cookie c = Cookies[i];

System.out.println(c.getName() + "=" + c.getValue());

}

使用android发起一个请求,报错java.lang.NullPointerException,说明android默认的请求是不带Cookie的

给android的请求头加上Cookie,我这里使用的是OkHttp3

Request request = new Request.Builder()

.url(url).addHeader("Cookie", "JSESSIONID=" + session_id)

.post(body)

.build();

至于这个session_id,可以这样做:服务端接收到登录请求,获取会话的sessionID,返回给android端,android端存到SharedPreferences里,发送请求的时候取出

使用带Cookie的方法再次访问服务端,可以看到打印出JSESSIONID,这时候android和网页端一样都能实现session持久了

4.验证Session持久

在服务端工程的web.xml里添加

1

表示设置session的最大保存时间为1分钟,设置为1分钟是为了方便验证

添加在线用户监听器,这里给出一个方案:

//登录处理的Servlet添加,user为用户实体对象

session.setAttribute("onlineUserBindingListener", new OnlineUserBindingListener(user));

//在线用户监听器,使用注解方式

import java.util.ArrayList;

import java.util.List;

import javax.servlet.ServletContext;

import javax.servlet.annotation.WebListener;

import javax.servlet.http.HttpSession;

import javax.servlet.http.HttpSessionBindingEvent;

import javax.servlet.http.HttpSessionBindingListener;

import domain.User;

@WebListener

public class OnlineUserBindingListener implements HttpSessionBindingListener {

private User user;

public OnlineUserBindingListener() {

}

public OnlineUserBindingListener(User user) {

this.user = user;

}

@SuppressWarnings("unchecked")

public void valueBound(HttpSessionBindingEvent event) {

HttpSession session = event.getSession();

ServletContext application = session.getServletContext();

List onlineUserList = (List) application.getAttribute("onlineUserList");

if (onlineUserList == null) {

onlineUserList = new ArrayList();

application.setAttribute("onlineUserList", onlineUserList);

}

onlineUserList.add(this.user);

}

@SuppressWarnings("unchecked")

public void valueUnbound(HttpSessionBindingEvent event) {

HttpSession session = event.getSession();

ServletContext application = session.getServletContext();

List onlineUserList = (List) application.getAttribute("onlineUserList");

onlineUserList.remove(this.user);

}

}

网页端显示用户列表,直接application.getAttribute("onlineUserList"),我不再赘述。网页每30秒自动刷新:

app登录后不操作,1分钟后用户列表数据消失

app登录后连续操作,每次操作间隔在1分钟内,用户列表数据持续存在。验证成功

5.其它

session的getAttribute和setAttribute方法是不会影响它的生命周期的,仍视为无活动状态

根据sessionId获取session的方法已经再Servlet 2.5后弃用,仍然想实现该功能的可以参考https://blog.csdn.net/sihai12345/article/details/81098765,基本原理是自己维护一个HashMap

Jsp中显示实体型列表尽量结合JSTL和EL表达式,简便清楚,用JSTL别忘了导包。示例:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

姓名 密码 部门 等级 注册时间 最近登录时间 最近登录IP 登录次数
${user.name } ${user.password } ${user.department } ${user.grade } ${fn:substring(user.reg_time,0,19) } ${fn:substring(user.log_time,0,19) } ${user.log_ip } ${user.log_count }

转载请注明博文来源,有什么问题欢迎在评论栏留言。 ——Kevin_Lu 2020/4/14


王者荣耀S6战队赛规则 高渐离上线战队商店
《艋胛》导演钮承泽性侵女员工 国光帮怎么就成了劣迹艺人帮