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. CMS为什么采用“标记-清除”算法

    分代式GC里,年老代常用mark-sweep:或者是mark-sweep/mark-compact的混合方式,一般情况下用mark-sweep,统计估算碎片量达到一定程度时用mark-compact. ...

  2. [刘阳Java]_Java程序员的成长路线_第3讲

    按照Java从业人员的职位晋升来说,Java程序成长路线大致如下 Java程序员 JavaEE初级软件工程师 JavaEE中级软件工程师 JavaEE高级软件工程师 Java架构师 按照职业发展方向, ...

  3. 在spark中操作mysql数据 ---- spark学习之七

    使用spark的 DataFrame 来操作mysql数据. DataFrame是比RDD更高一个级别的抽象,可以应用SQL语句进行操作,详细参考: https://spark.apache.org/ ...

  4. andorid SQLite数据库的增删改查 和事务操作

    .xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ...

  5. [C#-SQLite] SQLite一些奇怪的问题

    今天整C#的DAO层,我用的2013, 用的4.0的.NetFramework刚刚创建完Helper就出现异常 +        Connection    "helper.Connecti ...

  6. Tomcat Xms Xmx PermSize MaxPermSize 区别 及 java.lang.OutOfMemoryError: PermGen space 解决

    解决方案 在 catalina.bat 里的 蓝色代码前加入: 红色代码 rem ----- Execute The Requested Command ----------------------- ...

  7. poj3050

    #include <stdio.h> #include <set> #include <string> using namespace std; int a[6]; ...

  8. 【erlang】执行linux命令的两种方法

    os.cmd(Cmd) os模块提供了cmd函数可以执行linux系统shell命令(也可以执行windows命令).返回一个Cmd命令的标准输出字符串结果.例如在linux系统中执行os:cmd(& ...

  9. Hyper-V 共享式网络链接 端口映射

    远程路由访问我配置了很久都不成功,经过多方搜索,现面的命令能实现端口映射一.查询端口映射情况netsh interface portproxy show v4tov4查询这个IP所有的端口映射.net ...

  10. 1201新课程TSQL语句

    1.创建数据库 create datebase 表名称 2.删除数据库 drop datebase 表名称 3.创建表 -create table test(表名称)( code(列名称) varch ...