Session入门_session原理

1.Session概述

1、在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),

注意:一个浏览器独占一个session对象(默认情况下)

 

2Session 是一个域

1.作用范围:一个浏览器和服务器会话范围


2.生命周期:

创建

当程序第一次调用到request.getSession()方法时说明客户端明确的需要用session此时创建出对应客户端的Session对象.

request.getSession()=request.getSession(true),有session返回,没就创建。

request.getSession(false):有session直接返回,没session返回null,不创建


销毁

2.1session超过30分钟(这个时间是可以在web.xml文件中进行修改的)没有人使用则认为session超时销毁这个session.

2.2程序中明确的调用session.invalidate()方法可以立即杀死session.

2.3.服务器被非正常关闭,随着虚拟机的死亡而死亡.


钝化

*如果服务器是正常关闭,还未超时的session会被以文件的形式保存在服务器的work目录下,这个过程叫做session的钝化.


活化

*下次再正常启动服务器时,钝化着的session会被恢复到内存中,这个过程叫做session的活化.

3.作用:在会话范围内共享数据。

 

web.xml文件中进行修改session时间

根目录下配置
<session-config>
     <session-timeout>30 </session-timeout>
</session-config>

 

 

session 的原理:

    1request.getSession()方法会检查请求中有没有JSESSIONID cookie,如果有拿出他的值找到对应的session为他服务.

    2、如果JSESSIONID cookie没有,则检查请求的URL后有没有以拼接JSESSIONID过来,如果有,则根据JSESSIONID的值找到对应的Session为浏览器服务。

    3、如果还找不到JSESSIONID,则认为这个浏览器没有对应的Session,创建一个Session然后再在响应中添加JSESSIONID cookie

    4、默认情况下,JSESSIONID path为当前web应用的名称,并且没有设置过MaxAge,是一个会话级别的cookie.

    5、这意味着一旦关闭浏览器再新开浏览器时,由于JSESSIONID丢失,会找不到之前的Session

    6、我们可以手动的发送JSESSIONID cookie,名字和path设置的和自动发送时一样,但是设置一下MaxAge,使浏览器除了在内存中保存JSESSIONID信息以外还在临时文件夹中以文件的形式保存,这样即使重开浏览器仍然可以使用之前的session

 

URL重写:

1、如果浏览器禁用了Cookie,浏览器就没有办法JSESSIONID cookie,这样就用不了Session.

2、我们可以使用URL重写的机制,在所有的超链接后都以参数的形式拼接JSESSIONID信息,从而在点击超链接时可以使用URL参数的方式带回JSESSIONID,从而使用Session

3、将URL进行重写拼接上JSESSIONID的过程就叫做URL重写

4request.getSession()

 URL重写之前一定要先创建出Session,才有Session id,才能进行重写

5、response.encodeURL()

一般的地址都用这个方法重写

    6response.encodeRedirectURL()

如果地址是用来进行重定向的则使用这个方法

    7*url重写的方法一旦发现浏览器带回了任意cookie信息,则认为客户端没有禁用cookie,不会再进行重写操作

 

总结cookiesession

    1.cookie是客户端技术

    1、数据保存在客户端,这个信息可以保存很长时间

    2、数据随时有可能被清空,所以cookie保存的数据是不太靠谱的

    3、数据被保存在了客户端,随时有可能被人看走,如果将一些敏感信息比如用户名密码等信息存在cookie,可能有安全问题

     

    2.session是服务器端技术

    1、数据保存在服务区端,相对来说比较稳定和安全

    2、占用服务器内存,所以一般存活的时间不会太长,超过超时时间就会被销毁.我们要根据服务器的压力和session 的使用情况合理设置session的超时时间,既能保证session的存活时间够用,同时不用的session可以及时销毁减少对服务器内存的占用.

 

Session案例_登录注销

UserDao.jsp

private UserDao(){}
private static Map<String, String> userMap = new HashMap<String, String>();
static{
    userMap.put("张三", "333");
    userMap.put("李四", "444");
    userMap.put("王五", "555");
}
public static boolean ValiNP(String username,String password){
    return userMap.containsKey(username)&&    
                    userMap.get(username).equals(password);
}

 

index.jsp

  //获取session中的登录状态
  String user = (String)session.getAttribute("user");
  if(user==null||"".equals(user)){
登录,注册
}else{ 注销 }

 

login.jsp

<h1>用户登录</h1>
<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="POST">
    用户名:<input type="text" name="username"/>
    密码:<input type="password" name="password"/>
    <input type="submit" value="登录"/>
</form>

 

LoginServlet.java

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.ValiNP(username, password)){
//3.将名字和密码设置到session中
    HttpSession session = request.getSession();
    session.setAttribute("user", username);
    //4.回主页
    response.sendRedirect(request.getContextPath()+"/logout/index.jsp");
    //5.记得写return 后面的代码不用执行
    return;
}else{
    response.getWriter().write("用户名,密码不正确");
}

 

LogoutServlet.java

//有session直接返回,没session返回null,不创建
 HttpSession session = request.getSession(false);
if(session!=null&& session.getAttribute("user")!=null){
session.removeAttribute("user");
}
 
response.sendRedirect(request.getContextPath()+"/logout/index.jsp");

Session案例_防止表单重复提交

resubIndex.jsp

<script type="text/javascript">
  var isNotSub = true;
  function canSub(){  //客户端提示
  if(isNotSub){
  isNotSub = false;
  return true;
  }else{
  alert("请不要重复提交!!!");
  return false;
  }
  }
  </script>

 

<%
  Random r = new Random();
  int valinum = r.nextInt();
  session.setAttribute("valinum",valinum+"");
  %>

  

<form action="${pageContext.request.contextPath }/servlet/ResubServlet" method="POST" onsubmit="return canSub()">  //客户端提示
  用户名:<input type="text" name="username"/>
  <input type="hidden" name="valinum" value="<%=valinum %>"/>  //服务端提示
  <input type="submit" value="注册"/>
  </form>

 

ResubServlet.java

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"); //提交表单,页面未跳转的时候,同一个浏览器,第一次带着的session和请求参数valinum与第二次请求参数valinum是一致的,第二次的session为null?
    System.out.println("向数据库中注册一次:"+username);
}else{
    response.getWriter().write("from web:不要重复提交!!");
}
}