Java Servlet的Cookie和Session问题

Cookie和Session

两者相类似,都是用于存储客户端和服务端之间的信息的

  • cookie存储于客户端,也就是存储于本地,浏览器中通常有清空缓存与cookie选项,里面的cookie就是这个cookie
  • session存储于服务端,其相对cookie数据较安全

Session跳转访问问题

我在实操菜鸟教程的Session的例子中,由于我是使用了过滤器实现登陆后,经过主页跳转到服务端TestWeb/SessionTrack目录,读取到的session中的用户id为null,而不是我所指定的"admin"

session

即便删去过滤器,只要是客户端先访问了服务端的其他页面后再访问TestWeb/SessionTrack,即便是第一次访问,用户id都将会是null,之后无论怎么刷新都不会改变其结果

//部分代码
HttpSession session = request.getSession();

//设置默认值
String title = "Servlet Session实例";
Integer visitCount = 0;
String visitCountKey = new String("visitCount");
String userIDKey = new String("userID");
String userID = new String("admin");
if(session.getAttribute(visitCountKey) == null) {
    session.setAttribute(visitCountKey, visitCount);
}

//获取新Session
if (session.isNew()){
    title = "Servlet Session 实例";
    session.setAttribute(userIDKey, userID);
} else {
    visitCount = (Integer)session.getAttribute(visitCountKey);
    visitCount = visitCount + 1;
    userID = (String)session.getAttribute(userIDKey);
}
session.setAttribute(visitCountKey,  visitCount);

从代码逻辑上看,首先判断session是否为new,若是的话设置session的userIDKey和userID为我们指定的默认值。

但菜鸟教程上是给出的当我们直接访问SessionTrack时候的情况。

当客户端请求服务端的其他页面,若是第一次访问,服务端就会给出一个sessionID,名为JSESSIONID,同时保存在cookie中。然后在跳转到我们的SessionTrack时,服务端读取cookie,发现里面有一条JSESSIONID:*********的记录,判断为已有session。于是在session.isNew()中返回false,导致我们设置的userID没有置入session。

boolean session.isNew(){
	if(cookie("JSESSIONID", JSESSIONID) in cookies){
        return false;
    }
    return true;
}

在Java中,Session是Cookie的子集,Session不能离开Cookie而存在。

在.NET中,微软实现了Session和Cookie的分离,也就是说,如果浏览器不支持Cookie,Java写的服务端同样不支持Session,而.NET中支持

因此在不使用Cookie的情况下Java写的服务端只能通过 重写URL 的方式获取Session,菜鸟教程中有相关的介绍,但没有相关的例子来具体说明。

这边给出我使用cookie的判断用户对跳转后的当前网页(也就是保证cookie不为空的访问次数方法

  • 定义一个sessionFlag的cookie,当无cookie或cookie中没有sessionFlag时创建
String sessionFlagKey = new String("sessionFlag");
String sessionFlag = new String("Y");
boolean isNew = true;

//判断cookie中是否包含sessionFlag
Cookie[] cookies = request.getCookies();
if(cookies != null) {
    for(int i = 0; i < cookies.length; i++) {
        if(sessionFlagKey.equals(cookies[i].getName())) {
            isNew = false;
            break;
        }
    }
}

//通过布尔变量isNew代替session.isNew()
if (isNew){
    session.setAttribute(userIDKey, userID);
    response.addCookie(new Cookie(sessionFlagKey, sessionFlag));
    System.out.println("NEW SESSION");
} else {
    //省略
}

重写URL实现Session

首先要说明的是,重写URL实现Session会动态生成每个 URL 来为页面分配一个 session 会话 ID,使得后端的开发十分的麻烦。

HttpServletResponse接口提供了重写 URL 的方法:public java.lang.String encodeURL(java.lang.String url)

  • 当不存在或不能发送key为JSESSIONID的Cookie时,路径后面追加参数
  • 如果Cookie存在且可以发送服务器,后面不会追加参数

下面是一个例子,能够实现无论cookie是否禁用都能实现上面的Session实例

入口jsp重写URL

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello</title>
</head>
<body>
	<a href="<%=response.encodeURL("/TestSession/SessionTrack") %>">Hello!</a>
</body>
</html>

Servlet

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //getSession优先读取cookie中的JSESSIONID,其次是URL中传入的jsessionid
		HttpSession session = request.getSession();
    //读取sessionID,并设置对应的cookie
		Cookie cookie = new Cookie("JSESSIONID", session.getId());
		cookie.setMaxAge(60);
		response.addCookie(cookie);
    
		Date createTime = new Date(session.getCreationTime());
		Date lastAccessTime = new Date(session.getLastAccessedTime());
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		String title = "Servlet Session实例";
		Integer visitCount = 0;
		String visitCountKey = new String("visitCount");
		String userIDKey = new String("userID");
		String userID = new String("admin");

    //当session中不存在visitCounts时置入0
		if(session.getAttribute(visitCountKey) == null) {
			session.setAttribute(visitCountKey, visitCount);
		}
   		session.setAttribute(userIDKey, userID);
    
    //获得session中存储的visitCount
        visitCount = (Integer)session.getAttribute(visitCountKey);
        visitCount = visitCount + 1;
    //visitCount++
        userID = (String)session.getAttribute(userIDKey);
        session.setAttribute(visitCountKey,  visitCount);
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();

		String docType = "<!DOCTYPE html>\n";
		out.println(docType +
                "<html>\n" +
                "<head><title>" + title + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                 "<h2 align=\"center\">Session 信息</h2>\n" +
                "<table border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "  <th>Session 信息</th><th>值</th></tr>\n" +
                "<tr>\n" +
                "  <td>id</td>\n" +
                "  <td>" + session.getId() + "</td></tr>\n" +
                "<tr>\n" +
                "  <td>创建时间</td>\n" +
                "  <td>" +  df.format(createTime) + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>最后访问时间</td>\n" +
                "  <td>" + df.format(lastAccessTime) + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>用户 ID</td>\n" +
                "  <td>" + userID + 
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>访问统计:</td>\n" +
                "  <td>" + visitCount + "</td></tr>\n" +
                "</table>\n" +
                "</body></html>"); 
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值