会话技术
会话,现实生活中会话的含义:交谈、谈话。
在web访问过程中,会话代表什么意思呢?
浏览器打开一个网站,然后访问当前网站的诸多页面,最后关闭,整个的过程叫做一个会话。
HTTP协议,是一个无状态协议。在服务器看来,任何浏览器发送过来的请求数据都是完全相同的,一模一样,服务器是无法却别该请求来自于哪个浏览器。
比如:http://192.168.2.100/app/index.html
A和B用户同时访问了当前页面,发送的HTTP请求报文是完全相同的,对于服务器来说,它是无法区别该请求来自于a还是b
实际场景下,又有这样的需求,我们需要服务器可以给我们浏览器去保存一些数据,比如浏览记录、购物车
就会涉及到我们今天介绍的技术,会话技术。
会话技术i其实是为了解决HTTP协议无状态性而产生的一个解决方案。
会话技术可以分为两种,一个是客户端技术,一个是服务器技术。
客户端技术Cookie
Cookie是由服务器创建的,然后接下来,Cookie会被发送给客户端(响应报文,响应头 Set-Cookie:name=value),客户端会将cookie信息保存下来,下次再次访问服务器时,它会把整个cookie重新带回去给服务器(请求报文,请求头 Cookie:name=value),服务器接收到cookie(又由于cookie的值是唯一的),所以就可以利用cookie来进行会话管理。
服务器技术Session
Cookie
package com.cskaoyan.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
@WebServlet("/cookie1")
public class CookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收cookie的代码应该写在上面
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("lastVisit".equals(cookie.getName())){
String value = cookie.getValue();
Date date = new Date(Long.parseLong(value));
response.getWriter().println(date);
}
}
}
//在内部调用了getHeaders(Cookie)
//显示用户的上次访问时间
//生成cookie cookie的value值里面不能有空格
Cookie cookie = new Cookie("lastVisit", System.currentTimeMillis() + "");
// 以Set-Cookie响应头发送给客户端
//response.setHeader("Set-Cookie", "latLogin=xxx");
//EE规范同样给我们封装了一个简便的设置cookie的方法
response.addCookie(cookie);
//addCookie{
// setHeader(Set-cookie, cookie.getName = cookie.getValue)
// }
}
}
设置存活时间
cookie默认情况下只存在于浏览器的内存中,关闭浏览器,则cookie失效,如果希望cookie能够进行持久化保存,那么可以设置一个存活时间
Cookie cookie = new Cookie("username", username);
//单位是秒
cookie.setMaxAge(180);
设置一个以秒为单位的时间(正数),表示它会在硬盘上存活多久,如果设置的是负数,和不设置是一样的
0表示的是删除cookie
package com.cskaoyan.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
//假设登录成功,那么需要将用户名放入到cookie中
Cookie cookie = new Cookie("username", username);
//单位是秒
cookie.setMaxAge(180);
response.addCookie(cookie);
response.getWriter().println("登录成功,即将跳转至个人主页....");
response.setHeader("refresh", "2;url=" + request.getContextPath() + "/info");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.cskaoyan.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/info")
public class InfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("username".equals(cookie.getName())){
response.getWriter().println("欢迎您," + cookie.getValue());
//0表示删除cookie
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
}
}
}
设置路径
默认情况下,当访问当前服务器下面所有的资源时,默认都会携带cookie,如果希望仅某些页面去携带cookie,那么可以设置一个path
package com.cskaoyan.cookie.path;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/path1")
public class PathServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("key", "path");
//直接写/应用名开头的路径
cookie.setPath(request.getContextPath() + "/path2");
response.addCookie(cookie);
}
}
package com.cskaoyan.cookie.path;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/path2")
public class PathServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如果cookie设置了path,这个时候希望将cookie删除,那么可以怎么做呢
//需要特别注意一点,在删除cookie的时候,有一个注意事项,如果当前cookie设置了path
//那么删除cookie的时候,需要再将path再写一遍
//注意:删除cookie时浏览器删除
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if("key".equals(cookie.getName())){
response.getWriter().println(cookie.getValue());
cookie.setMaxAge(0);
cookie.setPath(request.getContextPath() + "/path2");
response.addCookie(cookie);
}
}
}
}
}
设置域名
注意:cookie有一个大的原则,不可以设置和当前域名无关的cookie,比如当前域名localhost,然后你设置了一个域名叫做cskaoyan.com的cookie,那么其实时设置不成功的。
aaa.com ——— 你申请的
sub.aaa.com ———- 这个域名是属于你的
third.sub.aaa.com————这个域名也是属于你的
父子域名
如果你设置了一个aaa.com域名的cookie,那么默认情况下,下面所有的子域名都可以共享该cookie
package com.cskaoyan.cookie.domain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/domain2")
public class DomainServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("user", "aaa.com");
cookie.setDomain("aaa.com");
response.addCookie(cookie);
}
}
cookie的优缺点
优点:小、轻便、放在浏览器,服务器没有压力
缺点:存储数据比较少,value值只能是字符串类型,有限制;安全问题;
cookie其实可以用来存放一些非敏感性数据,
Session
服务器技术。session对象是在服务器产生的,但是呢,保存也是在服务器上面。
session你可以认为是服务器给每个浏览器所开辟的一块内存空间,将这块内存空间和浏览器做一个绑定,如果今后当前浏览器再次访问服务器,如果需要进行数据的存取,那么就放置在当前内存空间中。
浏览器在访问session的时候,session会给浏览器创建一个独一无二的session对象,session对象有一个id,会把session的id加上响应报文中发送给客户端,客户端接收到之后将其保存,下次再次访问服务器时,将该id再携带回来,服务器就可以取出session的id值,那么就可以拿到原先的session对象。
只需要记住一点,每个浏览器拿到的都是不同的session对象。
创建session
本质:请求头中是否有Cookie:JSESSIONID=XXXX
第一次访问,请求头中肯定没有Cookie:JSESSIONID=xxxx,所以执行到request.getSession的时候,那么就会创建一个session对象,同时以set-Cookie:JSESSIONID=xxxx将session的id返回给浏览器,浏览器会将id保存下来
第二次访问,请求头中会携带Cookie:JSESSIONID=xxxx,所以执行到request.getSession的时候,(根据session的id去找到对应的session对象),就i把当前的session对象返回。
关闭服务器,session对象会销毁吗
肯定会。
关闭浏览器,session对象会销毁吗
没有销毁。此时session对象类似不可达。不可达的原因在于cookie请求头默认情况下只存在浏览器的内存中,关闭浏览器则失效,
JSESSIONID就会丢失。
session的使用
存取数据。
session域。
关闭服务器,重启服务器,还可以访问到原先session中的数据吗
注意:不要使用idea的tomcat关闭来验证,否则你将得不到正确的结论。
还可以进一步验证,比如使用本地的tomcat来部署我们的应用。
需要使用tomcat自带的管理系统来将应用给卸载。
在本地安装的tomcat conf/tomcat-users.xml文件中增加如下设置
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session1")
public class SessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如何去创建一个session呢?
HttpSession session = request.getSession();
session.setAttribute("username", "zhangsan");
System.out.println(session.getId());
System.out.println(session);
}
}
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session2")
public class SessionServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如何去创建一个session呢?
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
System.out.println(session.getId());
System.out.println(session);
System.out.println(username);
}
}
最终session里面的数据还是存在的,还可以访问到。session的地址发生了变化,但是session的id没有变。
秽土转生。
session在临死之前,它会序列化到本地硬盘上面(把里面的id、attributes属性全部序列化到本地硬盘上面),形成一个文件,当应用重新被启动的时候,读取文件,将里面的数据重新读取到内存中,会创建新的session,将这些id、属性值全部赋值给新的session对象。
关闭浏览器,如果我希望还可以访问到原先session中的数据,应该怎么办
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/session3")
public class SessionServlet3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username", "sssss");
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(180);
response.addCookie(cookie);
}
}
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session4")
public class SessionServlet4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
System.out.println(username);
}
}
session域
Context、Request、Session
Context > Session > Request
使用:
Context域:范围最大的一个域。和用户无关的。所以可以用来存放一些和用户无关的,所有用户都相同的数据,比如商城的商品分类
Session域:可以用来存放用户相关的数据。比如用户的购物车数据、用户的浏览记录、用户名等
Request域:非常的小,如果希望在一次请求中用到该数据,那么就可以使用request域,让转发的两个组件之间进行共享该数据。
session的生命周期
创建:对象的创建(request.getSession())
销毁:对象的销毁(应用被卸载、服务器关闭)
数据赋值:setAttribute、getAttribute、removeAttribute
对象的销毁并不意味着数据的销毁,如果希望数据销毁只有两种方式:
1.主动调用session.invalidate();
2.session默认有效期到达,session也会失效 如果30min内没有访问当前session,那么session失效,如果在30min内访问了一次session,那么重新开始计时
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
request.getSession().setAttribute("username", username);
response.getWriter().println("登录成功,跳转中......");
response.setHeader("refresh", "2;url=" + request.getContextPath() + "/info");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/info")
public class InfoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = (String) request.getSession().getAttribute("username");
response.getWriter().println("欢迎您 " + username + "<a href='" + request.getContextPath() + "/logout" + "'>点我注销</a>");
}
}
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//注销的逻辑应该怎么写?
request.getSession().invalidate();
}
}
重构到一个servlet中。因为我们发现这些servlet都是在说用户相关,所以可以放到一个servlet中。
package com.cskaoyan.session;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/user")
public class UserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String op = request.getParameter("op");
if("login".equals(op)){
login(request, response);
}
}
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
request.getSession().setAttribute("username", username);
response.getWriter().println("登录成功,跳转中......");
response.setHeader("refresh", "2;url=" + request.getContextPath() + "/user?op=info");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String op = request.getParameter("op");
if("info".equals(op)){
info(request, response);
}else if("logout".equals(op)){
logout(request, response);
}
}
private void logout(HttpServletRequest request, HttpServletResponse response) {
request.getSession().invalidate();
//跳转
}
private void info(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
String username = (String) request.getSession().getAttribute("username");
response.getWriter().println("欢迎您 " + username + "<a href='" + request.getContextPath() + "/user?op=logout" + "'>点我注销</a>");
}
}
购物车案例
package com.cskaoyan.cart;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet(value = "/index",loadOnStartup = 1)
public class IndexServlet extends HttpServlet {
@Override
public void init() throws ServletException {
//初始化商品信息
Product iphone12 = new Product("1", "iphone12", 6999.0);
Product mate40 = new Product("2", "huawei mate40", 6699.0);
Product product = new Product("3", "mi 11 pro", 5999.0);
List<Product> products = new ArrayList<>();
products.add(iphone12);
products.add(mate40);
products.add(product);
getServletContext().setAttribute("products", products);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//初始化商品信息
List<Product> products = (List<Product>) getServletContext().getAttribute("products");
for (Product product : products) {
response.getWriter().println("<a href='" + request.getContextPath() + "/detail?id=" + product.getId() + "'>" + product.getName() +"</a>");
}
}
}
package com.cskaoyan.cart;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/detail")
public class DetailServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String id = request.getParameter("id");
if(id == null || id.isEmpty()){
response.getWriter().println("invalid parameter");
return;
}
response.getWriter().println("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>");
List<Product> products = (List<Product>) getServletContext().getAttribute("products");
for (Product product : products) {
if(product.getId().equals(id)){
response.getWriter().println(product);
}
}
String index = request.getContextPath() + "/index";
String addCart = request.getContextPath() + "/addCart?id=" + id;
String viewCart = request.getContextPath() + "/viewCart";
response.getWriter().println("<a href='" + index + "'>返回首页</a>");
response.getWriter().println("<a href='" + addCart + "'>加入购物车</a>");
response.getWriter().println("<a href='" + viewCart + "'>查看购物车</a>");
response.getWriter().println("</body>\n" +
"</html>");
}
}
package com.cskaoyan.cart;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
@WebServlet("/viewCart")
public class ViewCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
HttpSession session = request.getSession();
List<String> cart = (List<String>) session.getAttribute("cart");
if(cart == null){
response.getWriter().println("购物车为空,去选购吧.....");
String index = request.getContextPath() + "/index";
response.setHeader("refresh", "2;url=" + index);
return;
}
List<Product> products = (List<Product>) getServletContext().getAttribute("products");
for (Product product : products) {
for (String id : cart) {
if(id.equals(product.getId())){
response.getWriter().println(product);
}
}
}
String index = request.getContextPath() + "/index";
response.getWriter().println("<a href='" + index + "'>返回首页</a>");
}
}
package com.cskaoyan.cart;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/addCart")
public class AddCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String id = request.getParameter("id");
if(id == null || id.isEmpty()){
response.getWriter().println("invalid parameter");
return;
}
HttpSession session = request.getSession();
List<String> cart = (List<String>) session.getAttribute("cart");
if(cart == null){
cart = new ArrayList<>();
session.setAttribute("cart", cart);
}
cart.add(id);
response.getWriter().println("添加到购物车成功....");
String index = request.getContextPath() + "/index";
response.setHeader("refresh", "2;url=" + index);
// List<String> list = new ArrayList<>();
// list.add(id);
//不能用set,因为永远只有一个 session.setAttribute("id", id);
}
}
package com.cskaoyan.cart;
public class Product {
private String id;
private String name;
private Double price;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Product(String id, String name, Double price) {
this.id = id;
this.name = name;
this.price = price;
}
public Product() {
}
@Override
public String toString() {
return "Product{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", price=" + price +
'}';
}
}
session依赖于cookie,如果cookie禁用会怎么样
EE规范提供了一个URL重写方法,此时JSESSIONID会附着在地址栏的后面
今晚可以做的
1.提到了数量问题
2.实现历史足迹。