1:什么是会话

通俗来说就是客户和服务器的一次私密谈话,客户发送请求以后服务器能够识别请求是来自同一个客户,他们是1对1的关系。

了解会话以后我们就要去考虑如何去实现这些问题下面一一进行解析

2:会话的跟踪

2.1:用cookies进行会话跟踪

竟然服务器能别识别不同的用户,但是他是如何识别的呢,这里就说到了SessionId,它是Session的唯一识别,保存在cookies中存放于本地硬盘里面,每次客户请求的时候会把SessionId一起传给服务器,那么服务器就能根据SessionId来识别Session。那么下面我们用代码来演示Session的运行方式

第一步:我们先写一个LoginServlet类

 public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
HttpSession session=request.getSession();
String userName=(String)session.getAttribute("username"); PrintWriter out =response.getWriter();
out.println("<html>");
out.println("<meta http-equiv=\"pragma\" content=\"no-cache\">");
out.println("<head><title>登录页面</title></head>");
out.println("<body>"); printSessionInfo(out, session);
out.println("<p>");
out.println("<form action=loginchk method=post>");
out.println("<table>");
out.println("<tr>");
out.println("<td>请输入用户名:</td>");
if(userName==null)
{
out.println("<td><input type=text name=username></td>");
}
else {
out.println("<td><input type=text name=username value="+userName+"></td>");
}
out.println("</tr>"); out.println("<tr>");
out.println("<td>请输入密码:</td>");
out.println("<td><input type=password name=password></td>");
out.println("</tr>"); out.println("<tr>");
out.println("<td><input type=reset value=重填></td>");
out.println("<td><input type=submit value=登录></td>");
out.println("</tr>"); out.println("</table>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* 打印与session相关的信息
* @param out
* @param session
*/
public void printSessionInfo(PrintWriter out,HttpSession session)
{
out.println("<table>");
out.println("<tr>");
out.println("<td>会话的状态:</td>");
if(session.isNew())
{
out.println("<td>新的会话</td>");
}
else {
out.println("<td>旧的会话</td>");
}
out.println("</tr>"); out.println("<tr>");
out.println("<td>会话ID:</td>");
out.println("<td>"+session.getId()+"</td>");
out.println("</tr>"); out.println("<tr>");
out.println("<td>创建时间:</td>");
out.println("<td>"+new Date(session.getCreationTime())+"</td>");
out.println("</tr>"); out.println("<tr>");
out.println("<td>上次访问时间:</td>");
out.println("<td>"+new Date(session.getLastAccessedTime())+"</td>");
out.println("</tr>"); out.println("<tr>");
out.println("<td>最大不活动时间间隔:</td>");
out.println("<td>"+session.getMaxInactiveInterval()+"</td>");
out.println("</tr>");
out.println("</table>");
}

LoginServlet

在代码中我们首先获取Session,(如果没有的话Tomcat容器会自动创建一个Session)然后打印出Session的相关信息。然后在渲染出来登录界面

第二步:我们在写一个LoginChkServlet类

 public class LoginChkServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public LoginChkServlet() {
super();
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("gb2312");
String userName=request.getParameter("username");
String passWord=request.getParameter("password"); if(userName==null||userName.equals("")||passWord==null||passWord.equals(""))
{
response.sendRedirect("login");
return;
}
else
{
HttpSession session=request.getSession();
session.setAttribute("username", userName);
response.sendRedirect("welcome");
}
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

LoginChkServlet

这个Servlet类主要是验证登录的用户信息,如果成功就把用户名写入Session中

第三步:写一个登录成功以后指向的WelcomeServlet类

 public class WelcomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public WelcomeServlet() {
super();
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session=request.getSession();
String userName=(String)session.getAttribute("username"); if(userName==null)
{
response.sendRedirect("login");
}
else
{
response.setContentType("text/html;charset=gb2312");
PrintWriter out=response.getWriter();
out.println("<html><head><title>欢迎页面</title></head><body>");
LoginServlet loginServlet=new LoginServlet();
loginServlet.printSessionInfo(out, session); out.println("<p>");
out.println("欢迎你,"+userName+"<p>");
out.println("<a href=login>重新登录</a>");
out.println("<a href=logout>注销</a>");
out.println("</body></html>");
out.close();
}
} /**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

WelcomeServlet

这个类是登录成功以后要显示的界面

第四步:在写一个退出类LogOutServlet类

 public class LogOutServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* @see HttpServlet#HttpServlet()
*/
public LogOutServlet() {
super();
// TODO Auto-generated constructor stub
} /**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=gb2312");
HttpSession session=request.getSession();
session.invalidate(); PrintWriter out=response.getWriter();
out.println("<html><head><title>退出登录</title></head><body>");
out.println("已退出登录<br>");
out.println("<a href=login>重新登录</a>");
out.println("</body></html>");
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

LogOutServlet

这个类是清除Session返回登录页面。

然后我们在配置一下web.xml

 <web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<display-name>LoginServlet</display-name>
<description></description>
<servlet-class>com.lp.servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginChkServlet</servlet-name>
<display-name>LoginChkServlet</display-name>
<description></description>
<servlet-class>com.lp.servlet.LoginChkServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<display-name>WelcomeServlet</display-name>
<description></description>
<servlet-class>com.lp.servlet.WelcomeServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LogOut</servlet-name>
<display-name>LogOut</display-name>
<description></description>
<servlet-class>com.lp.servlet.LogOutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginChkServlet</servlet-name>
<url-pattern>/loginchk</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LogOut</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
</web-app>

web.xml

其中<session-config>是设置Session的过期时间。ok现在整个项目写好了,我们运行一下看看结果

注解:由于是第一次访问所以服务器会首次创建会话所以这是一个新的会话,最大不活动时间指的就是Session失效的时间,由于我们在配置文件定义的是10分钟,所以默认就是60*10=600s(输出的单位是秒)

如果我用F5刷新我们看下结果

我们可以看出已经是旧的会话了,而且他们的SessionId是相同的。这是说明这2次是同一个会话,然后我们输入用户名和密码进行登录

我们通过SessionId可以看出这依然是同一个会话,然后我们在点击重新登录按钮输入用户名和密码如下图

我们发现SessionId依然相同,这说明了一个问题就是同一个浏览器并不支持2个用户同时登录,第二个登录的用户会把第一个用户信息进行覆盖(这也是Session覆盖问题)

但是有人会疑问如果用另一种浏览器登录会不会还是同一个会话呢,那么我们在IE浏览器输入http://localhost:8080/session-test/login如下图

是一个新的会话,这就说明不同浏览器会有不同会话的。那么有人就说如果我们禁用Cookies了是不是就不可以登录了呢我们来看看结果。

登录不上了,这也恰恰说明SessionId需要Cookies,刚刚禁止Cookies以后我自己都登录不了博客园,(⊙﹏⊙)。那么怎么办呢 就有另一种方法Url重写机制。

2:利用URL重写机制来跟踪会话

指的是如果客户端不支持Cookies的时候,可以使用URL重写机制来跟踪会话。URL重写机制就是在URL中附加客户的标识SessionId,Servlet容器解释URL的时候取出SessionId,在Servlet容器规范中这个参数的名字必须是jsessionid,完整的例子如http://localhost:8080/session-test/login;jsessionid=1。这样一来服务器将SessionId作为Url一部分发送给客户端,客户端在请求URL的时候再把SessionId传回来这样就会达到会话跟踪。

我们把上面代码中类似于

1:response.sendRedirect("login")修改为response.sendRedirect(response.encodeRedirectURL("login"));

2:action=loginchk修改为action="+response.encodeURL("loginchk")

然后再次运行就会发现可以登录了如下图

登录成功以后我们从浏览器来看一下jsessionid,会发现和上面的sessionId一模一样

3:Session的其他知识

3.1:当关闭浏览器以后,Session如果没有达到失效的时间是没有消除的,登录以后依然会发现是一个旧的Session。

3.2:用户会话跟踪的Cookies名字必须是jsessionid,通常报错在浏览器内存中,在浏览器内存中的cookies是不能被不同浏览器进程所共享。

3.3:如果想用另一种方式了解Session,我的另一个博客用.net写的也讲解了Session  http://www.cnblogs.com/LipeiNet/p/4755103.html

 

javaweb回顾第五篇浅谈会话的更多相关文章

  1. javaweb回顾第六篇谈一谈Servlet线程安全问题

    前言:前面说了很多关于Servlet的一些基础知识,这一篇主要说一下关于Servlet的线程安全问题. 1:多线程的Servlet模型 要想弄清Servlet线程安全我们必须先要明白Servlet实例 ...

  2. javaweb回顾第七篇jsp

    1:为什么会有JSP jsp全名(java server pages)中文叫做java服务器页面.在Servlet那一篇我们发现用Servlet可以生成动态页面,但是我们却在Servlet中却写了大量 ...

  3. Servlet第五篇【介绍会话技术、Cookie的API、详解、应用】

    什么是会话技术 基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话. 为什么我们要使用会话技术 ...

  4. javaweb回顾第十篇JSTL

    前言:JSTL(JSP Standard Tag Library)JSP标准标签库.它的目的是为了简化JSP的开发,如何没有JSTL可能我们开发的时候就需要写大量的自定义标签,无疑会加大开发难度,有了 ...

  5. javaweb回顾第八篇如何创建自定义标签

    前言:在javaweb开发中自定义标签的用处还是挺多的.今天和大家一起看自定义标签是如何实现的. 1:什么是标签 标签是一种XML元素,通过标签可以使JSP页面变得简介易用,而且标签具有很好的复用性. ...

  6. javaweb回顾第四篇Servlet异常处理

    前言:很多网站为了给用户很好的用户体验性,都会提供比较友好的异常界面,现在我们在来回顾一下Servlet中如何进行异常处理的. 1:声明式异常处理 什么是声明式:就是在web.xml中声明对各种异常的 ...

  7. javaweb回顾第三篇数据库访问

    前言:本篇主要针对数据库的操作,在这里不适用hibernate或者mybatis,用最原始的JDBC进行讲解,通过了解这些原理以后更容易理解和学习hibernate或mybatis. 1:jdbc的简 ...

  8. salesforce零基础学习(七十五)浅谈SOSL(Salesforce Object Search Language)

    在工作中,我们更多操作的是一个表的对象,所以我们对SOQL的使用很多.但是有时候,我们需要对几个表进行查询操作,类似salesforce的全局搜索功能,这时,使用SOQL没法满足功能了,我们就需要使用 ...

  9. javaWeb核心技术第五篇之jQuery

    - 概述 - jQuery是一个优秀的javascript框架(js类库),兼容css3和各大浏览器,提供dom,events,animate,ajax等简易的操作.并且jQuery有非常丰富的插件, ...

随机推荐

  1. ios开发 通讯录

    一.通信录开发 通信录开发主要是获取用户手机中的联系人 通过获取用户的通信录,可以在应用中添加好友等 二.如何访问用户的通讯录 在iOS9之前,有2个框架可以访问用户的通讯录 目前需要适配iOS8,所 ...

  2. snmp switch traffic交换机带宽

    上代码 <?php function getstr1($strall,$str1,$str2,$html_charset='utf-8'){ $i1=mb_strpos($strall,$str ...

  3. DB2 UDB DBA 核对清单

    本文摘自 http://www-128.ibm.com/developerworks/cn/db2/library/techarticles/dm-0404snow/index.htmlDB2 UDB ...

  4. [MyBean-插件]MyBean通用报表免费无限制版本发布

      [优点]    1.开发时无需安装报表组件(可以直接用编译好的文件,注意版权说明,请自行编译一次相应的报表插件文件).    2.无带包烦恼所有版本Delphi都可以使用,不拖累Delphi版本的 ...

  5. Apache配置多域名 AH00548: NameVirtualHost has no effect and will be removed in the next release

    httpd-vhosts.conf 中首行 NameVirtualHost *:80 删除掉即可解决.

  6. Map:containsKey、containsValue 获取Map集合的键值的 值

    get(Object key) 返回与指定键关联的值: containsKey(Object key) 如果Map包含指定键的隐射,则返回true: containsValue(Object valu ...

  7. 开始学CI

    未来一段时间的学习计划 1.codeIgniter 2.angular JS 深入 3.react 4.python 边工作边学习,保持进步

  8. jsp_设置文件编码

    jsp有两种方法可以设置文件编码: (1)<%@page language="java" contentType="text/html;charset=utf-8& ...

  9. 『TCP/IP详解——卷一:协议』读书笔记——04

    2013-08-18 16:31:17 第2章 链路层 2.1 引言 链路层主要有三个目的: 为IP模块发送和接受IP数据报 为ARP模块发送ARP请求和接受ARP应答 为RARP发送RARP请求和接 ...

  10. day4----json的简单实用

    json官方说明参见:http://json.org/ Python操作json的标准api库参考:http://docs.python.org/library/json.html 重要函数 编码:把 ...