五、cookie & session

一、JSP

1. jsp的介绍

JSP全名为Java Server Pages,中文名叫java服务器页面,本质是一个简化的Servlet设计,它是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件,后缀名为(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。
它实现了Html语法中的java扩张(以 <%, %>形式)。JSP与Servlet一样,是在服务器端执行的。通常返回给客户端的就是一个HTML文本,因此客户端只要有浏览器就能浏览。
jsp的作用:将内容的生成和显示进行分离
用JSP技术,Web页面开发人员可以使用HTML或者XML标识来设计和格式化最终页面,并使用JSP标识或者小脚本来生成页面上的动态内容

2. jsp的原理

jsp的原理.png

上图描述的是一个jsp页面hello.jsp在服务器中处理的过程。
创建web工程day10,创建一个hello.jsp页面。
1.在浏览器中输入 http://localhost/day10/hello.jsp
2.服务器得到请求,会通过jsp引擎查找到hello.jsp页面
3.服务器将查找到的hello.jsp页面翻译成hello_jsp.java(其本质就是一个servlet)
4.jvm会将hello_jsp.java文件编译成hello_jsp.class
5.服务器运算hello_jsp.class文件
6.服务器生成响应结果

  • jsp对应java文件分析
    上述是我们对于一个jsp运行的原理的简单分析,我们可以通过查看hello.jsp文件翻译后的.java文件来了解具体内容,生成的hello.jsp页面的java源文件存在于tomcat/work目录 下。
    hello.jsp页面源代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>    
    <title>hello.jsp</title>
  </head>  
 <body>
    hello jsp
  </body>
</html>

hello_jsp.java文件源代码

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>    \r\n");
      out.write("    <title>hello.jsp</title>\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("    hello jsp\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

通过上面的内容,大家会发现在jsp页面中的所有的html代码,最终都会被流写回到浏览器端,所以我们可以在浏览器上查看到jsp页面上的html内容

3. jsp的脚本与注释

  • jsp中三种脚本元素
    有三个基本的脚本元素,作用是使JAVA代码可以直接插入到HTML代码中
    声明标签
    格式:<%! int a = 1; %>
    作用:声明的变量在类的成员位置上
    脚本片断
    格式:<% int a = 1; out.println(a); %>
    作用:内容会生成在_jspService()方法中
    脚本表达式
    格式:<%= "hello " + a %>
    作用:它就相当于是out.println()将内容直接输出到页面中,注意表达式不能以分号结尾

  • jsp中的注释
    在jsp页面中可以使用三种注释

可以使用html中注释  
<!-- html的注释  -->
可以对jsp脚本内容使用java注释  //单行注释  /* 多行注释 */
可以使用jsp注释(推荐)
<%--  jsp注释  --%>

二.会话技术

会话的介绍:
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话
会话的作用:
每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据。
例如:用户点击超链接通过一个servlet购买了一个商品,程序应该保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户商品为用户结帐

会话技术会为两类
Cookie
Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

三、cookie

1. cookie的介绍

Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,对于JSP而言也可以直接写入jsessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

cookie与http

  • cookie与http协议关系
    Cookie是Http协议制定的,并不是Java语言独有的,PHT、.NET中也使用了cookie技术,因此只要是和HTTP协议相关,那么就可以使用cookie技术。
    我们知道cookie是服务器创建的一个键值对,并保存在浏览器端。那么服务器是如何将cookie发送给浏览器的呢?
    在服务器端先创建cookie,如 Cookie cookie=new Cookie(String name,String value),其中Cookie可以在javaeeAPI中查到的,详情可参考java_ee API。然后再通过response对象将cookie信息作为响应头发送到浏览器端。我们可以通过HttpWatch抓包工具查看响应信息,可以发现cookie是基于一个Set-Cookie响应头工作的,由于Set-Cookie响应头可以有多个,所以我们可以通过response.addHeader(String name,String value)方法发送Set-Cookie响应头,例如,有两个cookie,分别为one=aaa,two=bbb,其中one、two是cookie的名称,aaa、bbb是cookie的值。发送响应头如下所示:
    response.addHeader(“Set-Cookie”,”one=aaa”);
    response.addHeader(“Set-Cookie”,”two=bbb”);
    当浏览器再次访问服务器时,会将cookie送还给服务器。那么浏览器是如何将cookie带给服务器的呢?其实通过Cookie请求头传递过去的。请求头Cookie与响应头Set-Cookie有区别,多个cookie对应多个Set-Cookie响应头,但是只对应一个Cookie请求头,格式为:Cookie:one=aaa; two=bbb。即多个cookie之间用分号和空格隔开。
    需要注意的是:cookie是不能跨浏览器的。例如,张三首先使用IE浏览器访问服务器,服务器发送了一个cookie,这个cookie只会保存在IE浏览器,如果再使用火狐浏览器访问服务器,服务器会再发送一个cookie个火狐浏览器,在火狐浏览器中不能获取IE浏览器中的cookie,同理IE浏览器也获取不到火狐浏览器中的cookie。

  • http协议规定
    Http协议对Cookie做了一些规定,如下所示:
    a. 一个Cookie的大小,最大为4KB;
    b. 一个服务器最多向一个浏览器保存20个Cookie;
    c. 一个浏览器最多可以保存300个Cookie。
    我们知道,浏览器将服务器发送过来的cookie保存在本地磁盘,如果cookie过多,必然会加大浏览器的压力,因此Http协议对Cookie做了以上规定。
    但是,目前浏览器之间因为竞争,很多都在一定范围内违反了Http规定,例如,一个浏览器最多保存的Cookie个数超过300个。但是也不会出现浏览器允许一个Cookie的大小超过4GB。

2. cookie常用api及其原理

javax.servlet.http.Cookie类用于创建一个Cookie,response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。
构造方法
public Cookie(String name, String value):构造带指定名称和值的 cookie。
成员方法
public String getName():返回 cookie 的名称
public String getValue():返回 cookie 的值。
public void setMaxAge(int expiry):设置 cookie 的最大生存时间,以秒为单位
public void setPath(String uri):指定客户端应该返回 cookie 的路径。
接下来,咱们来做个案例看下cookie是如何使用的.
在day10工程下创建一个CookieDemo1Servlet,写入以下代码:
//1.创建cookie
Cookie cookie=new Cookie("cookieName","cookieValue");
//2.通过response对象将cookie响应到浏览器
response.addCookie(cookie);

然后通过抓包工具看下:
当在浏览器上访问http://localhost/day10/cookieDemo1时,抓取到的http请求与响应信息如下:
请求信息:

GET /day10/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive

响应信息

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: cookieName=cookieValue
Content-Length: 0
Date: Tue, 12 May 2015 05:26:53 GMT

再次访问此页面
请求信息:

GET /day10/cookieDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
Cookie: cookieName=cookieValue

通过以上分析,我们通过下面图进行总结:


ckkoie原理.png

3. cookie的持久化

持久化
如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用Cookie类的setMaxAge方法,并给出一个以秒为单位的时间。
0代表的是删除持久cookie,注意,删除cookie时,path必须一致,否则不会删除
-1代表的是浏览器关闭后失效.

路径:
Cookie的路径是在服务器创建Cookie时设置的,它的作用是决定浏览器访问服务器的某个资源时,需要将浏览器端保存的那些Cookie归还给服务器,可以通过Cookie类的setPath方法来设置cookie的路径.
关于路径包含关系
例如,浏览器中保存如下几个cookie,它们的路径分别是:
aCookie.path=/day10/
bCookie.path=/day10/jsps/
cCookie.path=/day10/jsps/cookie/
访问路径是:http://localhost:8080/day10/index.jsp
浏览器发送给服务器的cookie有:aCookie;
访问路径是:http://localhost:8080/day10/jsps/a.jsp
浏览器发送给服务器的cookie有:aCookie,bCookie;
访问路径是:http://localhost:8080/day10/jsps/cookie/b.jsp
浏览器发送给服务器的cookie有:aCookie,bCookie,cCookie。

4. 案例--记录上次访问时间

案例分析


记录上次访问时间.png

使用到的知识点分析
Cookie cookie=new Cookie(); 创建cookie
response.addCookie() 将cookie添加到http响应中
request.getCookies(); 获取所有的cookie

代码实现

public class ShowCurrentTimeServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    / 1.设置响应编码
    response.setContentType("text/html;charset=utf-8");

    / 2.获取一个名称叫time的cookie.
    Cookie cookie = findCookieByName("time", request.getCookies());
    Date now = new Date();
    if (cookie == null) {
        / 说明第一次访问
        response.getWriter().write("第一次访问时间是:" + now.toLocaleString());
    } else {
        / 不是第一次访问
        long time = Long.parseLong(cookie.getValue());
        response.getWriter().write("上次访问时间是:" + new Date(time).toLocaleString());
    }

    / 需要将这时访问的时间存储到cookie中。
    cookie = new Cookie("time", now.getTime() + "");
    /持久化cookie
    /cookie.setMaxAge(60*60*24*7);
    cookie.setMaxAge(0);/删除cookie
    response.addCookie(cookie);

}

/ 根据名称查找cookie
private Cookie findCookieByName(String name, Cookie[] cs) {
    if (cs == null || cs.length == 0) {
        return null;
    }
    for (Cookie c : cs) {
        if (name.equals(c.getName())) {
            return c;
        }
    }
    return null;
}
}

5. 案例--查看历史记录

查看历史记录.png

使用到的知识点分析
超连接带参数 <a href=”/day10/book?id=1”>
获取请求参数 request.getParameter()
创建Cookie cookie=new Cookie()
获取所有cookie request.getCookies()
将cookie响应到浏览器端 response.addCookies()

代码实现
book.jsp

<a href="/day10/book?id=1">西游记</a><br>
<a href="/day10/book?id=2">水浒传</a><br>
<a href="/day10/book?id=3">红楼梦</a><br>
<a href="/day10/book?id=4">三国演义</a><br>
<hr>
<a href="/day10/bookHistory.jsp">查看浏览商品记录</a>

BookServlet

public class BookServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=utf-8");
    / 1.得到商品的id
    String id = request.getParameter("id");

    / 2.将id值保存到cookie的名称叫ids这个cookie中。
    Cookie cookie = CookieUtils.findCookieByName("ids",
            request.getCookies());

    if (cookie == null) { / 第一次没有ids,就得到null
        cookie = new Cookie("ids", id);
    } else { / 不是第一次,就得到的不是null.
                / 3.得到cookie的value值。
        String ids = cookie.getValue();

        / 判断id是否重复
        List<String> list = Arrays.asList(ids.split("-")); /将数组转换成集合。

        if (!list.contains(id)) {
            ids = ids + "-" + id;
        }
        cookie = new Cookie("ids", ids);

    }

    response.addCookie(cookie);
    response.getWriter().write("商品展示成功,<a href='/day10/book.jsp'>继续浏览</a>");
}
}

bookHistory.jsp

<%
        String[] books = { "西游记", "水浒传", "红楼梦", "三国演义" };

        /1.得到所有的cookie,得到名称叫ids的cookie
        Cookie[] cs = request.getCookies();
        Cookie c = CookieUtils.findCookieByName("ids", cs);

        if (c == null) {
            /没有浏览记录
            out.print("无浏览记录");
        } else {
            /有浏览记录
            /2.得到cookie的value
            out.print("浏览记录如下:<br>");
            String ids = c.getValue(); /1-2-4

            String[] id = ids.split("-");

            for (int i = 0; i < id.length; i++) {
                int bookid = Integer.parseInt(id[i]) - 1;
                out.print(books[bookid] + "<br>");
            }

        }
%>

四.session

1. session的介绍

首先,HttpSession是javax.servlet.http包下的一个接口。从名字来看,我们可以知道HttpSession与Http协议有一定的关系,但是它并不是由Http协议定义的,而是由Javaweb提供。我们可以在JavaEE api中查看它的详细信息。
其次,HttpSession是用来进行会话跟踪的接口,我们之前也学过另外一个与会话相关的技术Cookie。在Cookie介绍中我们了解到,Cookie是由Http协议制定的,在请求信息和响应信息中分别对应了Cookie请求头和Set-Cookie响应头,并且Cookie是由服务器创建,保存在客户端。而HttpSession对象也是由服务器创建,但是与Cookie不同的是,它保存在服务器端。
HttpSession对象是Servlet的三大域对象之一,其他两个域对象是HttpServletRequest和ServletContext。这三个域中,request的域范围最小,它的域范围是整个请求链,并且只在请求转发和包含时存在;session域对象的域范围是一次会话,而在一次会话中会产生多次请求,因此session的域范围要比request大;application的域范围是最大的,因为一个web应用只有唯一的一个application对象,只有当web应用被移出服务器或服务器关闭它才死亡,它的域范围是整个应用。

2. session常用api,生命周期及其原理

session底层是依赖Cookie的,如果浏览器禁用Cookie则session会依赖URL重写。详情我们会在后面介绍。如何获取HttpSession对象?在服务器端,例如在Servlet中,我们通过request对象的getSession()方法获取服务器为当前用户创建的session对象,即:HttpSession session=request.getSession()。而在jsp中,session是jsp的内置对象,不用获取就可以直接使用。

session的常用api
我们知道每一个域对象都会有以下三个方法,HttpSession也不例外:
void setAttribute(String name,Object value):向域中添加域属性;
Object getAttribute(String name):从域中获取指定名称的属性值;
Void removeAttribute(String name):移出域中指定名称的域属性

接下来,咱们来做个案例看下session是如何使用的.
在day10工程下创建一个SessionDemo1Servlet,写入以下代码:

/ 1.获取session
HttpSession session = request.getSession();
/ 2.向session中存储数据据
session.setAttribute("name", "tom");

在day10工程下创建一个SessionDemo2Servlet,写入以下代码:

/ 1.获取session
HttpSession session = request.getSession();
/ 2.获取session中信息
String name = (String) session.getAttribute("name");
System.out.println(name);

接下来使用抓包工具看下:
打开浏览器访问http:/localhost/day10/sessionDemo1
请求信息:

GET /day10/sessionDemo1 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive

响应信息:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=2021FCEFDF31A6DAC8E7CC201F7AF404; Path=/day10/; HttpOnly
Content-Length: 0
Date: Tue, 12 May 2015 21:58:39 GMT

再次访问http:/localhost/day10/sessionDemo2:

请求信息:

GET /day10/sessionDemo2 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost
Connection: Keep-Alive
Cookie: JSESSIONID=2021FCEFDF31A6DAC8E7CC201F7AF404

响应信息

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Tue, 12 May 2015 22:00:46 GMT

session对象的创建分析
如果请求时,cookie中有jsessionid这个cookie,那么我们通过request.getSession()时,
就会根据jsessionid值查找session的id,如果查找到,会使用已有的,如果没有查找到,会创建。
如果请求时,cookie中没有jsessionid这个cookie,那么request.getSession()就会创建一个新的session对象.

session对象的销毁分析
浏览器关闭了,session对象不会销毁的,session的销毁与关闭浏览器无关.
session对象销毁方式:
1.关闭服务器
2.默认超时
在tomcat/conf/web.xml文件中设置了session默认超时时间
<session-config>
<session-timeout>30</session-timeout>
</session-config>
默认30分钟超时
3.可以设置session超时时间(以秒为单位)
void setMaxInactiveInterval(int interval)
4.销毁session
invalidate();

session的原理

session的原理.png

第一次访问,请求中不存在jsessionid值,这时发送请求到服务器端就会创建HttpSession对象.工将session的id值存储到cookie中响应到浏览器端
当下一次在请求时,这时会在请求中存在jsessionid值,到服务器端后,就会根据jsessionid值,查找指定id的session对象。
如果查找到,就直接使用,而不会重新创建。如果没有查找到,会重新创建.
HttpSession session=request.getSession();
扩展
HttpSession session=request.getSession(true/false);
如果值是true与无参数一样.
如果是false,它不会重新创建session对象,会返回null值。(用的很少)

3. 案例--购物车

案例--购物车.png

使用到的知识点分析
购物车使用的数据结构 Map<String,Integer>
获取session request.getSession()
解决请求参数乱码 new String(name.getBytes(“iso8859-1”),”utf-8”)

Productlist.jsp

<table border='1' width="65%" align="center">
        <tr>
            <td>商品名称</td>
            <td>操作</td>
        </tr>
        <tr>
            <td>洗衣机</td>
            <td><a href="/day10/addProductToCart?name=洗衣机">添加到购物车</a></td>
        </tr>
        <tr>
            <td>电视机</td>
            <td><a href="/day10/addProductToCart?name=电视机">添加到购物车</a></td>
        </tr>
        <tr>
            <td>缝纫机</td>
            <td><a href="/day10/addProductToCart?name=缝纫机">添加到购物车</a></td>
        </tr>
        <tr>
            <td>打火机</td>
            <td><a href="/day10/addProductToCart?name=打火机">添加到购物车</a></td>
        </tr>
        
    </table>

AddProductToCartServlet

public class AddProductToCartServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        
        / 1.获取商品名称
        String name = request.getParameter("name");
        / 2.解决乱码
        name = new String(name.getBytes("iso8859-1"), "utf-8");
        / 3.获取购物车
        HttpSession session = request.getSession();
        Map<String, Integer> cart = (Map<String, Integer>) session
                .getAttribute("cart");

        / 4.判断购物车是否存在
        Integer count = null; /代表的是商品数量
        if (cart == null) {
            cart = new HashMap<String, Integer>();
            / cart.put(name, 1);
            count = 1;
        } else {
            / 如果购物车存在,我们需要考虑商品在购物车中是否存在。
            count = cart.get(name);
            if (count == null) {
                / 说明购物车中无此商品
                count = 1;
            } else {
                / 如果有此商品,将数量加1
                count += 1;
            }

        }
        cart.put(name, count);
        / 5.将购物车存储到session中.
        session.setAttribute("cart", cart);
        
        response.getWriter().write("添加成功,<a href='/day10/productlist.jsp'>继续购物</a>,<a href='/day10/cart.jsp'>查看购物车</a>");

    }
}

cart.jsp

<table border='1' align="center" width="65%">

        <tr>
            <td>商品名称</td>
            <td>商品数量</td>
        </tr>

        <%
            /1.得到session
            HttpSession mysession = request.getSession();

            /2.得到购物车
            Map<String, Integer> cart = (Map<String, Integer>) mysession
                    .getAttribute("cart");

            /3.判断购物车是否存在
            if (cart == null || cart.size() == 0) {
                out.print("购物车中无商品<br>");
            } else {
                /4.遍历cart
                for (String name : cart.keySet()) {

                    out.print("<tr><td>" + name + "</td><td>" + cart.get(name)
                            + "</td></tr>");

                }
            }
        %>

    </table>

4. url重写

url重写介绍
如果浏览器不支持Cookie或用户阻止了所有Cookie,可以把会话ID附加在HTML页面中所有的URL上,这些页面作为响应发送给客户。这样,当用户单击URL时,会话ID被自动作为请求头的一部分而不是作为头行发送回服务器。这种方法称为URL重写(URL rewriting)。

url重写作用
当客户机不接受cookie时,server就使用URL重写作为会话跟踪的基本方式.URL重写,添加了附加数据(会话ID)到请求的URL路径上.
会话ID必须被编码作为该URL字符串中的路径参数。该参数的名称为jsessionid,
简单说就是cookie禁用了jsessionid就不能携带,那么每次请求,都是一个新的session对象。
如果想要使用同一个session对象,可以使用url重写.

url重写实现
response. encodeRedirectURL(java.lang.String url)
用于对sendRedirect方法后的url地址进行重写。
response. encodeURL(java.lang.String url)
用于对表单action和超链接的url地址进行重写

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

推荐阅读更多精彩内容