黑马小日子---servlet会话技术

会话技术:

什么是会话?

  会话就是用户打开浏览器,读取多个页面,再关闭浏览器的过程IE8以下的IE浏览器中,如果打开了一个浏览器,在没有关闭的情况下,又打开另一个浏览器,那么 视为两个不同的会话,IE8以上的IE浏览器则视为同一次会话.

会话的作用:

会话技术主要用于解决一次会话过程中的数据保存问题.

Cookie:

是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

各自的数据了

Cookie特性:

1.name 必须的

2.Value 必须的,单一的值

3.Path  可选的,路径

4.Domain  可选的

5.Age   可选的,生命周期

注意:浏览器针对每一个网站最多支持20cookie,浏览器最多支持300cookie,每个cookie的大小不能超过4KB.


Cookie案例 1: 查看上次访问的时间

//设置cookie

resp.setCharacterEncoding("UTF-8");

resp.setContentType("text/html;charset=UTF-8");

PrintWriter writer=resp.getWriter();

writer.write("你上次访问的时间是 : ");

Cookie [] cooks=req.getCookies();//得到所有的cooks的参数

for (int i = 0; cooks!=null&&i < cooks.length; i++) {

if("lastAcceptTime".equals(cooks[i].getName()))//找到了对应的参数名

{

String value =cooks[i].getValue();//得到值

long time=Long.parseLong(value);//把value变成字符串

writer.write(new Date(time).toLocaleString());

}

}

writer.write("<a href='"+req.getContextPath()+"/servlet/Test2'>clear</a>");

Cookie cook=new Cookie("lastAcceptTime",System.currentTimeMillis()+"");

cook.setMaxAge(Integer.MAX_VALUE);//设置生命周期

resp.addCookie(cook);

//cookie的生命周期设置为0

Cookie [] cook=req.getCookies();

for (int i = 0;cook!=null&& i < cook.length; i++) {

if("lastAcceptTime".equals(cook[i].getName())){

cook[i].setMaxAge(0);

cook[i].setPath(req.getContextPath());

resp.addCookie(cook[i]);

}

}

Cookie案例2 : 记住用户名

//设置页面

resp.setCharacterEncoding("UTF-8");

req.setCharacterEncoding("UTF-8");

resp.setContentType("text/html;charset=UTF-8");

PrintWriter out=resp.getWriter();

String username="";

String checked="";

Cookie[]cooks=req.getCookies();

for (int i = 0;cooks!=null&& i < cooks.length; i++) {

if("username".equals(cooks[i].getName())){//查找到了username这个属性

username=cooks[i].getValue();//把cooks[i]的值赋给username

checked="checked='checked'";

}

}

//提供登录页面

out.print("<html><head><title>登录</title></head><body>");

out.print("<form action='"+req.getContextPath()+"/servlet/ProcessServlet' method='post'>");

out.print("用户名:<input type='text' name='username' value='"+username+"'/><br/>");

out.print("密码:<input type='password' name='password' /><br/>");

out.print("<input type='checkbox' name='remember' "+checked+"/>记住用户名<br/>");

out.print("<input type='submit' value='登录' /><br/>");

out.print("</form></body></html>");

//判断是否记住用户名

req.setCharacterEncoding("UTF-8");

resp.setContentType("tet/html;charset=UTF-8");

String username=req.getParameter("username");//得到username的值

String remember=req.getParameter("checked");//得到checked的值

 PrintWriter out=resp.getWriter();

if(remember!=null){//判断复选框是否勾选,如果没勾选,就=null

Cookie cook=new Cookie("username",username);//创建一个cookie,把用户名添加到cookie中

cook.setPath(req.getContextPath());

cook.setMaxAge(Integer.MAX_VALUE);

resp.addCookie(cook);

}else{

Cookie []cooks=req.getCookies();//复选框没有勾选,就查找cookie

for (int i = 0; cooks!=null&&i < cooks.length;i++) {//遍历cookie数组,得到用户名

if("username".equals(cooks[i].getName())){

cooks[i].setPath(req.getContextPath());

cooks[i].setMaxAge(0);//把用户名的cookie的生命周期设置为0

resp.addCookie(cooks[i]);

}

}

out.print("恭喜!登录成功!");

}

Session

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

Web中的Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。因此从上述的定义中我们可以看到,Session实际上是一个特定的时间概念。需要注意的是,一个Session的概念需要包括特定的客户端,特定的服务器端以及不中断的操作时间。A用户和C服务器建立连接时所处的SessionB用户和C服务器建立连接时所处的Session是两个不同的Session。 


Session原理:

HttpSession其实是一个域对象,内部维护一个Map集合.

HttpServletRequest,可以使用getSession()方法或者getSession(boolean creat)方法得到session对象,那么这两个方法有什么区别呢?

getSession(): 如果客户端没有对应的session对象,那么就创建一个,如果有对应的session对象,就得到它.

getSession(boolean creat); 参数如果为true,那么和上面的方法一样,如果为false, 则只能获取.

实际上HttpSession实现原理就是使用了Cookie技术,session对象的IDcookie的形式写到了浏览器中.

Cookid的名称是:JSESSIONID

Cookid的取值是:SessionID

Cookiepath当前应用的路径

Cookieage浏览器的经进程

浏览器关闭,默认情况下结束会话,但是HttpSession对象不会立刻消失,而是保存30分钟,,要想立刻销毁HttpSession对象,可以执行invalidate方法

HttpSession的常用方法:

getId(); 获取到每个SessionID,这个ID值是随机生成的唯一值

getAttribute("name"); 得到指定的参数的值

setAttribute("key","value");设置参数的值

               

Session的内部实现原理其实就是Cookie,如果客户端禁用了Cookie,如果保存会话数据呢?

   解决方法:在访问其他URL的时候,在后面加上JSESSIONID.因为Cookie的名称是JSESSIONID, URL中以参数的形式加上JSESSIONID,就可以把Cookie带给服务器.

这个过程称为URL重写.

Session的生命周期    

浏览器关闭后,HttpSession不会立刻销毁,而是保存30分钟,如果想立刻销毁Httpsession,可以执行Httpsessioninvalidate()方法.

可以再xml文件中设置session-timeout属性,属性值是的单位是分钟

<session-config>

<session-timeout>10</session-timeout>

</session-config>

强烈注意放入HttpSession中的对象的类型需要实现Serializable接口进行序列化

Session的状态:

SessiongetSession的时候调用然后进入运行状态,当超时(30分钟未访问资源),或调用了invalidate()方法的时候,Session就被销毁了Session运行状态的时候,如果session太多,或者应用重写启动了,那么session会被钝化,也就是进入持久化状态;当应用重新开启,或者常久没活动的session又活动了,那么session会从持久化状态被激活.

Session案例练习

1.验证表单是否重复提交.

//设置表单,并且给表达隐藏域和session都提供一个相同的令牌,使用UUID对象的randomUUID方法生成随机令牌

resp.setContentType("Text/html;charset=UTF-8");

PrintWriter out=resp.getWriter();

 UUID token=UUID.randomUUID();//生成一个随机数

 req.getSession().setAttribute("token", token.toString());//把随机数写入session

 out.print("<form action='/day07/servlet/TestSubmit' method='post'>");

out.print("用户名:<input type='text' name='username'/><br/>");

out.print("<input type='hidden' name='token' value='"+token+"'/>");

out.print("<input type='submit' value='go'/></form>");

//得到表单隐藏域中的令牌和session中的令牌,对比令牌是否一致,如果一致,就登录成功,然后删除session中的令牌

resp.setContentType("Text/html;charset=UTF-8");

PrintWriter out=resp.getWriter();

String code=req.getParameter("token");//得到表单中的令牌

String scode=(String)req.getSession().getAttribute("token");//得到session中的令牌

if(code.equals(scode)){

out.write("登录成功!!");

req.getSession().removeAttribute("token");

}else{

out.write("请不要重复登录");

}

UUID: 使用算法,计算出世界上唯一的一个令牌

使用UUID对象的randomUUID()可以生成令牌

验证码验证

//在生成验证码数字的时候,通过MD5来进行加密,然后通过BASE64来找到加密后的密文对应的字符,再把这个密文加进session

//MD5加密

MessageDigest md=MessageDigest.getInstance("md5");//通过MD5加密

byte [] b=md.digest(code.getBytes());

BASE64Encoder base=new BASE64Encoder();//密文找到对应的

return base.encode(b);

//生成验证码,然后把验证码加密写入session

private static int WIDTH = 120;

private static int HEIGHT = 25;

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//图片默认是会缓存的,去掉缓存

response.setHeader("Expires""-1");

response.setHeader("Cache-Control""no-cache");

response.setHeader("Pragma""no-cache");

//BufferedImage代表一副内存图片

BufferedImage image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);

//Graphics得到画笔,在图片上画

Graphics g = image.getGraphics();

g.setColor(Color.YELLOW);

g.fillRect(0, 0, WIDTHHEIGHT);

g.setColor(Color.BLUE);

g.drawRect(1, 1, WIDTH-2, HEIGHT-2);

g.setColor(Color.GREEN);

Random r = new Random();

for(int i=0;i<9;i++)

g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT));

g.setColor(Color.GRAY);

g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 22));

StringBuffer sb = new StringBuffer();

int x = 20;

for(int i=0;i<4;i++){

int num = r.nextInt(10);

g.drawString(num+"", x, 20);

x+=20;

sb.append(num);

}

try {

request.getSession().setAttribute("code", MD5.codeing(sb.toString()));//验证码加密后写入session中

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

ImageIO.write(image, "jpeg", response.getOutputStream());

}

//在输入验证码的时候,把输入的验证码也使用MD5加密,然后与session中的密文进行对比,如果相同,那么验证通过

String code=req.getParameter("code");

try {

String scode=MD5.codeing((String) req.getSession().getAttribute("code"));

if(code.equals(scode)){

System.out.println("登录成功!");

req.getSession().removeAttribute("code");

}else{

System.out.println("验证码失败!");

}

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值