会话技术:指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程称之为一次会话。会话跟踪技术有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
浙公网安备 33010602011771号