Java Web学习笔记(六):Session和Cookie

Session

在Web开发中,服务器可以为每个用户浏览器创建一个会话对象(Session对象),注意:一个浏览器独占一个Session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

Session原理

用户打开浏览器访问Servlet时,在该Servelt调用如下代码,即可创建Session。

HttpSession session = request.getSession();

服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号去,服务器发现客户机浏览器带session id过来了,就会使用内存中与之对应的session为之服务。

Session创建与销毁

Session创建

在程序中第一次调用request.getSession()方法时就会创建一个新的Session,可以用isNew()方法来判断Session是不是新创建的,随后同一个客户端再次调用会使用同一个Session。

可以使用request.getSession(false)来保证不创建新的Session;相反,request.getSession(true)方法每次都创建新的Session。

Session销毁

在Java中,默认session在30分钟之内未被使用,服务器就会将session销毁,不管用户浏览器此时有没有关闭。即便用户关闭了浏览器,结束了当前会话,session也不会立即销毁,直到默认时效内session未被使用。

可以通过Web应用的配置文件web.xml,配置session的有效时间,如这里设置为10分钟:

<session-config>
    <session-timeout>10</session-timeout>
</session-config>

手动销毁session,则调用session对象的方法,如:

session.invalidate();

Session实战

下面完成一个利用session完成用户登录的简单例子。

创建一个Java Web项目,编写登陆页面login.html。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
    </head>
    <body>
        <form action="LoginServlet" method="post">
            <label>用户名</label><input type="text" name="username"><br/>
            <label>密 码:</label><input type="password" name="password"><br/>
            <input type="submit" value="登录">
        </form>
    </body>
</html>

编写处理登录请求的页面LoginServlet.java。

public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        // 获取用户, 因为是示例省略了校验的过程
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 将用户名存入session
        HttpSession session = request.getSession();
        session.setAttribute("username", username);
        response.sendRedirect(request.getContextPath() + "/hello.jsp");
        return;
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

登陆成功后的跳转页面hello.jsp。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>欢迎页面</title>
  </head>
  <body>
  欢迎您,${username}! <a href="/LogoutServlet">退出登录</a>
  </body>
</html>

退出登录LogoutServlet.java。

public class LogoutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        HttpSession session = request.getSession(false);
        if(session == null) {
            response.sendRedirect(request.getContextPath() + "hello.jsp");
            return;
        }
        session.removeAttribute("user");
        response.sendRedirect(request.getContextPath() + "/login.html");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }
}

在web.xml中配置servlet。

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.wyk.servletdemo.web.LoginServlet</servlet-class>
</servlet>
<servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.wyk.servletdemo.web.LogoutServlet</servlet-class>
</servlet>


<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/LogoutServlet</url-pattern>
</servlet-mapping>

运行程序,访问 http://localhost:8080/servletdemo/login.html ,随便输入一个用户名和密码。

login.jpg

点击登录,跳转到欢迎界面。可以看到session传递过来的用户名显示在了界面。

hello.jpg

通过退出登录将用户名从session中移除。

解决浏览器关闭后丢失Session ID的问题

根据Session实现原理,我们可以知道,在默认情况下,当我们关闭浏览器后保存Session ID的Cookie也将被销毁,即我们再次打开浏览器发送相同请求,获得到的Session对象也不再与之前相同。

需要注意的是,关闭浏览器后服务器存储的Session不一定就被销毁了,服务器存储的Session是在一定时间内未被操作,服务器才会将其销毁。这里关闭浏览器之后无法再使用上次Session的原因,在于我们丢失了Session ID(保存Cookie的Session ID默认在浏览器关闭时销毁)。

如果需要解决这个问题,我们只需要延长保存Session ID的Cookie的有效期限即可。

String sessionId = session.getId();
Cookie cookie = new Cookie("JSESSIONID", sessionId);
cookie.setPath("/day07/"); // path的值需要与原来的一致才行
cookie.setMaxAge(30 * 60); // 设置为30分钟内有效
response.addCookie(cookie);

浏览器禁用Cookie后如何使用Session技术

从Session的实现原理中,我们可以发现Session的实现需要依赖于Cookie,那么当用户浏览器禁用了Cookie后又该如何使用Session技术呢?

Session的实现原理最基本的是要求用户在每次请求时发送保存有Session ID的信息(如发送保存有Session ID的Cookie)。禁用Cookie后,我们可以为页面中每条请求增加一个参数,用于发送Session ID的值。这样,服务器获取到Session ID后就可以获取到用户独占的Session,为用户服务。

通过response.encodeRedirectURL(java.lang.String url) 用于对sendRedirect方法后的url地址进行重写。通过response.encodeURL(java.lang.String url)用于对表单action和超链接的url地址进行重写,以此来实现对session数据的共享。

Cookie

Cookie是一种浏览器和服务器交互数据的方式。它是由服务器端创建,但是不会保存在服务器。创建好之后,发送给浏览器。浏览器保存在用户本地,下一次访问网站的时候,就会把该Cookie发送给服务器。

Cookie规范

Http协议提供了有关Cookie的规范,主要包含以下几点:

  • Cookie存储的大小上限为4KB。
  • 一个服务器最多在客户端浏览器中可以保存20个Cookie。
  • 一个浏览器最多可以保存300个Cookie。

值得注意的是,不同浏览器之间不能共享Cookie缓存文件。

Cookie方法

Cookie常用方法如下。

方法 说明
Cookie(String name, String value) 构造方法,实例化Cookie对象,传入cooke名称和cookie的值
public String getName() 取得Cookie的名字
public String getValue() 取得Cookie的值
public void setValue(String newValue) 设置Cookie的值
public void setMaxAge(int expiry) 设置Cookie的最大保存时间,即cookie的有效期。
public int getMaxAge() 获取Cookies的有效期
public void setPath(String url) 设置cookie的有效路径.
cookie public String getPath() 获取cookie的有效路径
public void setDomain(String pattern) 设置cookie的有效域
public String getDomain() 获取cookie的有效域

其中,有效路径指的是cookie的有效路径保存在哪里,浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容