浏览器开始访问网站到访问网站结束期间产生的多次请求响应组合在一起叫做一次会话,会议话的过程中会产生会话相关的数据,我们需要将这些数据保存起来。
Cookie
Cookie是客户端的技术,程序把每个用户的数据以cookie的形式写给用户的各自的浏览器,当用户使用浏览器再去访问服务器中的web资源时,这样,web资源处理的就是用户各自的数据了。
Cookie是基于set-Cookie响应头和Cookie请求头工作的,服务器可以发送set-Cookie请求头命令浏览器保存一个cookie信息,浏览器会在访问服务器时以Cookie请求头的方式带回之前保存的信息cookie在浏览器中的存放只允许存300个cookie,每个站点最多有20个cookie在浏览器的存放cookie是不安全的,很有很能被丢失;
删除cookie必须设置maxAge path 一致性才可以覆盖
cookie是客户端技术
- 数据保存在客户端,这个信息可以保存很长时间
- 数据随时有可能被清空,所以cookie保存的数据是不太靠谱的
- 数据被保存在了客户端,随时有可能被人看走,如果将一些敏感信息比如用户名密码等信息存在cookie中,可能有安全问题
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
//创建cookie数组
Cookie[] cookies=request.getCookies();
Cookie findC=null;
if(cookies!=null){
for(Cookie c :cookies){
if("lasttime".equals(c.getName())){
findC=c;
}
}
}
if(findC==null){
response.getWriter().write("你是第一次访问这个网站");
}else{
//cookies是返回一个long行的值
Long lastTime=Long.parseLong(findC.getValue());
response.getWriter().write("你上次访问的时间是:"+new Date(lastTime).toLocaleString());
}
Date date=new Date();
Cookie cookie=new Cookie("lasttime", date.getTime()+"");
//设置cookies保存的最多时间
//相当于response中添加了一个Set-cookie的响应头
cookie.setMaxAge(36000);
//设置整个web应用的cookie信息都可以带过去;
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
}
setMaxAge与getMaxAge方法
- 一个Cookie如果没有设置过MaxAge则这个Cookie是一个会话级别的Cookie,这个Cookie信息发给浏览器后浏览器会将它保存在浏览器的内存中,这意味着只要浏览器已关闭随着浏览器内存的销毁Cookie信息也就消失了.
- 一个Cookie也可以设置MaxAge,浏览器一旦发现收到的Cookie被设置了MaxAge,则会将这个Cookie信息以文件的形式保存在浏览器的临时文件夹中,保存到指定的时间到来为止.这样一来即使多次开关浏览器,由于这些浏览器都能在临时文件夹中看到cookie文件,所以在cookie失效之前cookie信息都存在.
- 想要命令浏览器删除一个Cookie,发送一个同名同path的cookie,maxage设置为0,浏览器以名字+path识别cookie,发现同名同path,cookie覆盖后立即超时被删除,从而就删除了cookie.就是一个覆盖.
setPath与getPath方法
用来通知浏览器在访问服务器中的哪个路径及其子路径时带着当前cookie信息过来如果不明确设置,则默认的路径是发送Cookie的Servlet所在的路径.
setDomain与getDomain方法
用来通知浏览器在访问哪个域名的时候带着当前的cookie信息.但是要注意,现代的浏览器一旦发现cookie设置过domain信息则会拒绝接受这个Cookie.我们平常不要设置这个方法.
Cookie是不可跨域名的。域名www.google.com颁发的Cookie不会被提交到域名www.baidu.com去。这是由Cookie的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的Cookie。
正常情况下,同一个一级域名下的两个二级域名如www.baidu.com和www.images.baidu.com也不能交互使用Cookie,因为二者的域名并不严格相同。如果想所有www.baidu.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数
Cookie cookie = new Cookie("time","20080808"); // 新建Cookie
cookie.setDomain("www.baidu.com"); // 设置域名
cookie.setPath("/"); // 设置路径
cookie.setMaxAge(Integer.MAX_VALUE); // 设置有效期
response.addCookie(cookie);
/**
* 显示之前看的书从cookie中获取信息
**/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=utf-8");
//查询数据库中的书的展示:
Map<String, Book> map=BookDao.getbooks();
for (Map.Entry<String, Book>entry :map.entrySet()) {
Book book =entry.getValue();
response.getWriter().write("<a href='"+request.getContextPath()+"/BookInfoServlet?id="+book.getId()+"'>"+book.getName()+"</a><br>");
}
response.getWriter().write("<hr>");
//2`显示之前看过的书
Cookie[] cookies=request.getCookies();
Cookie findC=null;
if(cookies!=null){
for(Cookie c :cookies){
if("last".equals(c.getName())){
findC=c;
}
}
}
if(findC==null){
response.getWriter().write("你未浏览过");
}else{
response.getWriter().write("你浏览过书有:"+"<br/>");
//cookies是返回一个long行的值
String[] ids=findC.getValue().split(",");
for(String id :ids){
Book book=BookDao.getbook(id);
//response.getWriter().write(book.getName()+"<br/>");
}
}
}
Session
由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。
session是服务器端技术,数据保存在服务区端,相对来说比较稳定和安全,占用服务器内存,所以一般存活的时间不会太长,超过超时时间就会被销毁.我们要根据服务器的压力和session 的使用情况合理设置session的超时时间,既能保证session的存活时间够用,同时不用的session可以及时销毁减少对服务器内存的占用.
作用范围:
当前会话范围
生命周期:
当程序第一次调用到request.getSession()方法时说明客户端明确的需要用到session此时创建出对应客户端的Session对象.
当session超过30分钟(这个时间是可以在web.xml文件中进行修改的)没有人使用则认为session超时销毁这个session.
程序中明确的调用session.invalidate()方法可以立即杀死session.
当服务器被非正常关闭时,随着虚拟机的死亡而死亡.如果服务器是正常关闭,还未超时的session会被以文件的形式保存在服务器的work目录下,这个过程叫做session的钝化.下次再正常启动服务器时,钝化着的session会被恢复到内存中,这个过程叫做session的活化.
作用:在会话范围内共享数据
session时间的配置:在配置的时是以分钟为单位的;
在web.xml中用配置<session-config><session-timeout>30</></>
session 的原理:
request.getSession()方法会检查请求中有没有JSESSIONID 如果没有则检查请求的URL后有没有以参数的形式带着JSESSIONID过来,如果有则找到对应的Session, 服务器如果找不到则认为这个浏览器没有对应的Session,创建一个Session然后再在响应中添加JSESSIONID
cookie的值就是这个Session 的id
默认情况下,JSESSIONID 的path为当前web应用的名称,并且没有设置过MaxAge,是一个会话级别的cookie.
这意味着一旦关闭浏览器再新开浏览器时,由于JSESSIONID丢失,会找不到之前的Session我们可以手动的发送JSESSIONID cookie,名字和path设置的和自动发送时一样,但是设置一下MaxAge,使浏览器除了在内存中保存JSESSIONID信息以外还在临时文件夹中以文件的形式保存,这样即使重开浏览器仍然可以使用之前的session
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String prod=request.getParameter("prod");
prod=new String(prod.getBytes("iso8859-1"),"UTF-8");
HttpSession session=request.getSession();
Cookie jc=new Cookie("JSESSIONID", session.getId());
jc.setPath(request.getContextPath());
jc.setMaxAge(1800);
response.addCookie(jc);
session.setAttribute("prod", prod);
}
/**
*
*登录后将用户信息存到session中
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//1.获取用户名密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//2.查询数据库检查用户名密码
if(UserDao.valiNamePsw(username, password)){
//3.如果正确登录后重定向到主页
request.getSession().setAttribute("user", username);
response.sendRedirect(request.getContextPath()+"/loginout/index.jsp");
return;
}else{
//4.如果错误提示
response.getWriter().write("用户名密码不正确!");
}
}
/**
* 退出时把session杀死
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//1.杀死session
//request.getsession();如果没有session会创建一个
if(request.getSession(false)!=null
&& request.getSession().getAttribute("user")!=null){
request.getSession().invalidate();
}
//2.重定向到主页
response.sendRedirect(request.getContextPath()+"/loginout/index.jsp");
}
/**
* 防止form表单重复提交
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
request.setCharacterEncoding("utf-8");
try {
Thread.sleep(4*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String username = request.getParameter("username");
String valinum = request.getParameter("valinum");
String valinum2 = (String) request.getSession().getAttribute("valinum");
if(valinum2!=null && !"".equals(valinum2) && valinum.equals(valinum2)){
request.getSession().removeAttribute("valinum");
System.out.println("向数据库中注册一次:"+username);
}else{
response.getWriter().write("from web:不要重复提交!!");
}
}
URL重写:
如果浏览器禁用了Cookie,浏览器就没有办法JSESSIONID cookie,这样就用不了Session了.我们可以使用URL重写的机制,在所有的超链接后都以参数的形式拼接JSESSIONID信息,从而在点击超链接时可以使用URL参数的方式带回JSESSIONID,从而使用Session将URL进行重写拼接上JSESSIONID的过程就叫做URL重写
request.getSession() --在URL重写之前一定要先创建出Session,才有Session id,才能进行重写
response.encodeURL()--- 一般的地址都用这个方法重写
response.encodeRedirectURL() --- 如果地址是用来进行重定向的则使用这个方法
url重写的方法一旦发现浏览器带回了任意cookie信息,则认为客户端没有禁用cookie,就不会再进行重写操作