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. Train Problem I hdu 1022(栈)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=1022 题意:给出火车的进站与出站顺序,判断是否可以按照给出的出站顺序出站. #include < ...

  2. .Net中几种常见的页面跳转传值方法

    1.ASP Server对象Execute方法 ASP Server对象的Execute方法可以在执行当前页面的过程中将另一个页面执行结果的内容插入到当前页面的输出中.Execute方法带一个参数,是 ...

  3. js关闭浏览器的tab页(兼容)

    由于在脚本中使用了 window.close(), 当前非弹出窗口在最新版本的chrome和firefox里总是不能关闭,而在 IE中是可以关闭的 . 在console中弹出提示"Scrip ...

  4. 2015/09/09夜晚js继续学习

    单词:标量(scalar)数组(array)元素(element)填充(populating)下标(index) 向数组中添加元素的操作称之填充.在填充数组时,不仅需要给出新元素的值,还需要给新元素在 ...

  5. 【html】:禁止鼠标事件

    <body oncontextmenu="return false" onselectstart="return false" ondragstart=& ...

  6. 安卓奇葩问题之:设置webView超时

    我只想说:what a fucking day! 今天要做一个webView的超时功能,于是开始百度,一看貌似很简单啊,于是开始copy了下面的代码. import java.util.Timer; ...

  7. 数据库知识整理<七>

    组合查询: 7.1使用子查询: 嵌套在其他查询中的查询,我们称之为子查询.子查询本身也可能包含一个子查询.子查询也称为内部查询,而包含子查询的语句也称为外部查询. 所有的子查询可以被分为两个类别:子查 ...

  8. 使用javamail发送邮件错误:550 5.7.1 Unable to relay

    这两天由于客户的邮件服务器迁移,使用了NTLM的验证方式.系统使用javamailAPI进行发送邮件时,发现只能对内部邮箱进行发送,对外部邮箱进行发送的时候,报下图错误: 后面发现是由于系统的java ...

  9. 平衡树模板 bzoj 3224

    program t3224; var tr:array[-1..1000000,1..2] of int64; num,fa,size,quan:array[-1..1000000] of int64 ...

  10. Centos6.7下安装配置VPN

    在Vultr上买了台VPS准备做VPN,不贵5刀,位置是日本东京的.ping值在100-200之间,还好算说的过去. Vultr地址 系统选择的Centos6 的版本是6.7 在网上查了查linux下 ...