会话技术:指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程称之为一次会话。会话跟踪技术有Cookie和Session。

Cookie

  • 网页之间的交互是通过HTTP协议传输数据的,而Http协议时无状态的协议。无状态的协议指的是一旦数据提交后,浏览器和服务器的连接就会关闭,再次交互的时候需要重新建立新的连接。
  • 服务器无法确认用户的信息,于是,W3C提出:给每个用户都发一个通行证,无论谁访问的时候都需要携带通行证,这样服务器就可以从通行证上确认用户的信息。通行证就是Cookie

Cookie的流程:浏览器访问服务器,如果服务器需要记录该用户的状态,就使用response向浏览器发送一个cookie,浏览器会把Cookie保存起来。当浏览器再次访问服务器的时候,浏览器会把请求的网址连同Cookie一同交给服务器。

Cookie API

  • Cookie类用于创建一个Cookie对象
  • response接口中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段
  • request接口中定义了一个getCookies方法,它用于获取客户端提交的Cookie

常用的Cookie方法

  • public Cookie(String name,String value)
  • setValue与getValue方法
  • setMaxAge与getMaxAge方法
  • setPath与getPath方法
  • setDomain与getDomain方法
  • getName方法

简单使用Cookie

创建Cookie,发送Cookie给浏览器

//设置response的编码
response.setContentType("text/html;charset=UTF-8");
//创建Cookie对象,指定名称和值
Cookie cookie = new Cookie("UserName", "littletom");
//设置Cookie的时间,否则不会生产Cookie文件
cookie.setMaxAge(1000);
//向浏览器发送Cookie
response.addCookie(cookie);
System.out.println("cookie ok");
response.getWriter().write("已经向浏览器发送一个Cookie");

Cookie细节

Cookie不可跨域性

Cookie具有不可跨域名性。浏览器判断一个网站是否能操作另一个网站的CooKie的依据是域名。如访问baidu,浏览器只会把baidu的Cookie带过去,而不会带其他网站的Cookie。

Cookie保存中文

  • Cookie保存中文有可能会乱码,中文属于Unicode字符,英文数据ASCII字符,中文占4个字符或者3个字符,英文占2个字符。
  • Cookie使用Unicode字符时需要对Unicode字符进行编码。
//对Unicode字符进行编码
Cookie cookie=new Cookie("country",URLEncoder.encode("中国","UTF-8"));

一个Servlet向浏览器写Cookie

//设置response编码
response.setContentType("text/html;charset=UTF-8");
//对中文进行编码
String country=URLEncoder.encode("中国","UTF-8");
//创建Cookie对象
Cookie cookie=new Cookie("Country",country);
//设置Cookie有效时间
cookie.setMaxAge(1000);
//向浏览器发送一个cookie
response.addCookie(cookie);

response.getWriter().write("向浏览器发送了一个Cookie");

另一个Servlet取出Cookie数据

response.setContentType("text/html;charset=UTF-8");
Cookie[] cookies=request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
     String name=cookies[i].getName();
     //使用URLDecoder进行解码
     String value=URLDecoder.decode(cookies[i].getValue(),"UTF-8");
     response.getWriter().write(name+":"+value);
}

Cookie的有效期

Cookie的有效期是通过setMaxAge()来设置的。

  • 如果MaxAge为正数,浏览器会把Cookie写到硬盘中,只要还在MaxAge秒之前,登录网站时该Cookie就有效【无论关闭了浏览器还是电脑】
  • 如果MaxAge为负数,Cookie是临时的,仅在本浏览器内有效,关闭浏览器Cookie就失效了,Cookie不会写到硬盘中。Cookie默认值就是-1。如果没有设置Cookie的有效期,在硬盘中就找不到对应的文件。
  • 如果MaxAge为0,则表示删除该Cookie。Cookie机制没有提供删除Cookie对应的方法,把MaxAge设置为0等同于删除Cookie。

Cookie的修改和删除

Cookie存储的方式类似于Map集合

Cookie的名称,通过response添加到浏览器中,会覆盖原来的Cookie。

//重新添加一个相同名称的Cookie,就相当于修改Cookie
Cookie cookie=new Cookie("country",URLEncoder.encode("美国","UTF-8"));
response.add(cookie)

删除Cookie,把MaxAge设置为0,并添加到浏览器中即可

Cookie cookie=new Cookie("country",URLEncoder.encode("美国","UTF-8"));
cookie.setMaxAge(0);
response.add(cookie);

注意:删除、修改Cookie时,新建的Cookie除了Value、MaxAge之外的所有属性都要与原来Cookie相同。否则浏览器视为不同的Cookie,不予覆盖,导致删除修改失败。

Cookie的域名

Cookie的domain属性决定运行访问Cookie的域名。domain的值规定为“.域名”

Cookie的隐私安全机制决定了Cookie是不可跨域名的。即使是同一级域名,不同二级域名也不能交接。

Cookie的路径

Cookie的path属性决定允许访问Cookie的路径。

Cookie发布出来,整个页面的资源都可以使用,如果只想Servlet1可以获取到Cookie,其他资源不能获取,则需要设置路径为“/Servlet1”。

Cookie的安全属性

HTTP协议不仅仅是无状态的,而且是不安全的。如果不希望Cookie在非安全协议中传输,可以设置Cookie的secure属性为true,属性只会在HTTPS和SSL等安全协议中传输该Cookie。

Cookie的应用

显示用户上次访问的时间

其实就是每次登陆的时候,取到Cookie保存的值,再更新下Cookie的值。

        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
        response.setContentType("text/html;charset=UTF-8");
        //获取所有的Cookie
        Cookie[] cookies=request.getCookies();
        String cookieValue=null;
        for(int i=0;cookies!=null&&i<cookies.length;i++){
            if(cookies[i].getName().equals("time")){
                response.getWriter().write("您上次登陆的时间是:");
                cookieValue=cookies[i].getValue();
                response.getWriter().write(cookieValue);
                cookies[i].setValue(simpleDateFormat.format(new Date()));
                response.addCookie(cookies[i]);
                break;
            }
        }
        //如果Cookie的值为空,那么就是第一次访问
        if(cookieValue==null){
            //创建一个Cookie对象,日期为当前时间
            Cookie cookie=new Cookie("time",simpleDateFormat.format(new Date()));
            //设置Cookie的生命期
            cookie.setMaxAge(20000);
            //response对象回送Cookie给浏览器
            response.addCookie(cookie);
            System.out.println("ok");
            response.getWriter().write("您这是第一次登陆");
        }

addCookie()方法异常:java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

请务必牢记,名称和值中都不能包含空格或者如下的字符:[ ] ( ) = , " / ? @ : ;

因此将时间格式中的空格改为“-”即可。

显示上次浏览过的商品

首先设计Book对象

public class Book {
    private String id;
    private String name;
    private String author;

    public Book(String id, String name, String author) {
        this.id = id;
        this.name = name;
        this.author = author;
    }

    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 String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

设计一个简单的数据库存储数据,就用LinkedHashMap集合

public class DBUtils {
    private static LinkedHashMap<String, Book> linkedHashMap=new LinkedHashMap<>();
    static{
        linkedHashMap.put("1",new Book("1","javaweb","ren"));
        linkedHashMap.put("2",new Book("2","java","guang"));
        linkedHashMap.put("3",new Book("3","sql server","xu"));
        linkedHashMap.put("4",new Book("4","mysql","de"));
        linkedHashMap.put("5",new Book("5","oracle","shu"));
    }

    public static LinkedHashMap<String,Book> getAll(){
        return linkedHashMap;
    }
}

HelloServlet显示所有书及上次浏览过的书

        response.setContentType("text/html;charset=UTF-8");
        //显示所有书籍
        response.getWriter().write("网页上所有的书籍:"+"<br/>");
        LinkedHashMap<String, Book> linkedHashMap= DBUtils.getAll();
        Set<Map.Entry<String,Book>> entry=linkedHashMap.entrySet();
        for(Map.Entry<String,Book> stringBookEntry :entry){
            Book book=stringBookEntry.getValue();
            response.getWriter().write("<a href='/WelcomeServlet?bookId="+book.getId()+"' target='_blank'>"+book.getId()+" "+book.getName()+"</a>"+"<br/>");
        }
        //显示访问记录
        Cookie[] cookies=request.getCookies();
        response.getWriter().write("您最近访问的书籍有:"+"<br/>");
        for(int i=0;cookies!=null&&i<cookies.length;i++){
            if(cookies[i].getName().equals("bookhistory")){
                String[] ids=cookies[i].getValue().split("\\_");
                for(int j=0;j<ids.length;j++){
                    Book book1=(Book) DBUtils.getAll().get(ids[j]);
                    response.getWriter().write(book1.getName()+"<br/>");
                }
                break;
            }
        }

WelcomeServlet显示访问过的书籍信息,并设置Cookie

        response.setContentType("text/html;charset=UTF-8");
        String id=request.getParameter("bookId");
        Book book= (Book) DBUtils.getAll().get(id);
        Cookie[] cookies=request.getCookies();
        String[] ids=null;
        for(int i=0;cookies!=null&&i<cookies.length;i++){
            if(cookies[i].getName().equals("bookhistory")){
                ids=cookies[i].getValue().split("\\_");
                break;
            }
        }
        String idstr=id+"_";
        if(ids==null){

        }else if(ids.length<3){
            for(String tempId :ids){
                idstr=idstr+tempId+"_";
            }
        }else{
            idstr=idstr+ids[0]+"_"+ids[1]+"_";
        }
        Cookie cookie=new Cookie("bookhistory",idstr);
        response.addCookie(cookie);
        response.getWriter().write("书的编号是:"+book.getId()+"<br/>");
        response.getWriter().write("书的名称是:"+book.getName()+"<br/>");
        response.getWriter().write("书的作者是:"+book.getAuthor()+"<br/>");

访问的效果

 

 posted on 2019-05-19 21:42  会飞的金鱼  阅读(79)  评论(0)    收藏  举报