Cookie和Session都可以实现会话跟踪,将上一次的请求传入下一次内,但它们的实现方式有一个显著的区别,如下:
- Cookie:将当前会话的信息存在浏览器端,每次请求时将Cookie信息传入服务器
- Session:将会话的信息存在服务器端,浏览器保存一个JSESSIONID,每次传入JSESSIONID去取信息
很显然,2种会话跟踪的实现方式,Session是在服务器端保持状态的方案,Cookie实在浏览器端保持状态的方案。对于Cookie而言,如果传输的状态信息较多,将较大的降低网络传输的效率和增大服务器的处理难度,因此Session显然在这种情况下是比较好的。
Session是基于Cookie来实现的,每次为一个客户端创建一个Session对象时,其实也是创建了一个Cookie对象,这个Cookie对象保存的就是JSESSIONID。服务器为每一个客户端创建的Session对象保存在服务器的内存中,Session对象有一个超时间隔时间,当离最后一次访问的时间超过的这个间隔时间之后,这个Session对象将会失效,变成一个垃圾对象,等待回收。默认超时间隔时间为30分钟,可以在<tomcat安装目录>\conf\Web.xml文件里面配置,如下:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
注意conf\Web.xml文件配置和web应用程序的web.xml文件配置的作用域。
当浏览器不支持Cookie或关闭Cookie时,便不能用Cookie的方式来实现Session,这种情况应该很少。此时可以利用URL重写实现Cookie跟踪。按照正常访问网站的规则,用户是直接输入地址进入一个主页面,然后通过超链接进入其他页面,而直接输入地方访问其他页面时视为非法访问,不创建Session对象。当用超链接访问时,浏览器将会话标识号作为参数附加在超链接的URL地址后面就叫URL重写。HttpServletResponse接口中定义了两个完全用于URL重写的方法:
- encodeURL:用于对超链接和form表单的action属性中设置的URL进行重写
- encodeRedirectURL:用于对要传递给HttpServletResponse.sendRedirect方法的URL进行重写
对encodingURL的测试如下:
@WebServlet("/Session1")
public class SessionServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
HttpSession session=req.getSession();
Integer sessionCount=(Integer)session.getAttribute("count");
int count=0;
if(sessionCount!=null){
count=sessionCount.intValue();
}
out.println("当前会话中发生了"+(++count)+"次访问<br>");
session.setAttribute("count",new Integer(count));
count=0;
ServletContext application=getServletContext();
Integer applicationCount=(Integer) application.getAttribute("count");
if(applicationCount!=null){
count=applicationCount.intValue();
}
out.println("Web应用程序中发生了"+(++count)+"次访问<br>");
application.setAttribute("count",new Integer(count));
out.println("<a href='"+resp.encodeURL("Session2")+"'>访问Session2");
}
}
@WebServlet("/Session2")
public class SessionServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
HttpSession session=req.getSession();
Integer sessionCount=(Integer)session.getAttribute("count");
int count=0;
if(sessionCount!=null){
count=sessionCount.intValue();
}
out.println("当前会话发生了"+(++count)+"次访问<br>");
session.setAttribute("count",new Integer(count));
count=0;
ServletContext application=getServletContext();
Integer applicationCount=(Integer)application.getAttribute("count");
if(applicationCount!=null){
count=applicationCount.intValue();
}
out.println("Web应用程序发生了"+(++count)+"次访问<br>");
application.setAttribute("count",new Integer(count));
out.println("<a href='"+resp.encodeURL("Session1")+"'>访问Session1</a>");
}
}
当访问Session1时,查看网页源码如下:
点击超链接,地址栏如下:
对于不支持Cookie而言的浏览器,实现Session跟踪就是以这种形式实现的,如果浏览器支持Cookie也采用了这种实现方式的话,第一次访问会将会话标识号附加到URL路径后,但后续响应消息则不在附加,这是因为创建Session时总是将会话标识号以Cookie的形式发送给浏览器,如果浏览器不支持或关闭Cookie,则不会回传这个标识号,如果支持,会回传,则服务器知道浏览器支持Cookie,便不在附加标识号到URL后。第一次访问时服务器不知道浏览器支不支持,所以也会附加标识号到URL后。