1 案例1-显示上一次登陆的时间
1.1 需求
当用户访问我们的servlet时,如果是第一次访问,则提示是第一次访问,否则显示用户上一次的访问时间;
1.2 技术分析
需要记录用户上一次的访问时间,根据分析,request生命周期太短,不合适。servletContext生命周期太长,且是占用服务器的内存空间,使用会话技术,就可以解决这个问题。
1.3 会话概述
所谓的会话技术,就是浏览器与服务器的多次通信之间的一个技术。
按照会话技术的位置,可以分为客户端会话技术和服务器端会话技术。
客户端会话:
专业术语就是cookie技术。
Cookie就是由服务器负责创建的,由浏览器负责保存的一个小文件,这个小文件可以保存少量的信息。
服务器端会话技术:
Session是服务器端的会话技术,可以简单理解为是服务器为每一个浏览器创建的一个内存空间,用于保存与浏览器交互的过程中(会话)保存一些信息。
1.4 Cookie的作用
可以让多个request对象之间的数据共享(多次请求的数据共享);
1.5 Cookie的使用步骤
1:创建cookie的格式:
构造方法:Cookie(String name, String value)
name就是cookie的名称;
value就是cookie要保存的值(不能含中文,否则语法报错)
2:将cookie交给浏览器的方法
response.addCookie(cookie对象);
3:获取cookie的方法:
Cookie[] 数组名 = reqesut.getCookies();
迭代数组,可以获取每一个cookie对象;
面向cookie对象,获取cookie的名称和值;
cookie对象.getName();
cookie对象.getValue();
1.6 Cookie的路径与保存时间
(1)路径
Cookie可以设置一个有效路径(有效路径就是表示这个cookie在访问哪儿的时候有效),如果不设置,默认就是当前路径的上一级路径。
例如:
http://localhost/day33/c1 默认cookie的路径就是:http://localhost/day33
手动修改路径:
Cookie对象.setPath(“/”); 代表的就是当前这个服务器,只要访问的是这个服务器地址,都会带着cookie。
(2)保存时间
设置cookie的存活时间:
Cookie对象.setMaxAge(int值代表的是秒);
如果参数小于0,代表当前会话有效(只要浏览器不关闭,一直有效)
如果参数等于0,代表响应给浏览器的时候cookie立刻死亡(删除cookie的时候使用)
如果参数大于0,代表响应给浏览器的时候开始计时,指定的秒数后cookie死亡。
1.7 设置cookie的域名
package com.itheima.demo01_cookie;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 设置cookie的域名
*/
public class Cookie_扩展 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1:创建一个cookie对象
Cookie c1 = new Cookie("c11","jack11");
//2:设置路径
//c1.setPath("/");//只要访问这个tomcat,都会带cookie
//设置cookie的域名
c1.setDomain(".abc.com");//地址的域名是本ip地址的www.abc.com的时候,携带这个cookie
//3:设置cookie的存活时间
c1.setMaxAge(50);
//3:将cookie响应给浏览器
response.addCookie(c1);
response.getWriter().print("okk...");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1.8 案例-纪录上一次的访问时间-步骤分析
1:编写一个servlet,先获取用户携带的cookie,如果有,则显示用户上一次登陆的时候;
2:如果没有显示第一次登陆;
3:更新cookie的值为本次登陆的时间;
参考代码:
/*
* 1:编写一个servlet,先获取用户携带的cookie,如果有,则显示用户上一次登陆的时候;
2:如果没有显示第一次登陆;
3:更新cookie的值为本次登陆的时间;
*/
//0:解决响应体的中文乱码
response.setContentType("text/html;charset=utf-8");
//1:编写一个servlet,先获取用户携带的cookie,如果有,则显示用户上一次登陆的时候;
Cookie[] cs = request.getCookies();
//1.5:为了解决有cookie,但不是hiscookie的情况,我们需要定义一个boolean类型的变量,用于解决逻辑文件
boolean flag = false;//没有his cookie
if(cs!=null){
for (Cookie c : cs) {
String name = c.getName();
//1:判断用户携带过来的cookie,是不是我们想要的cookie
if("his".equals(name)){
//说明是我们要找的cookie
String value = c.getValue();
response.getWriter().println("亲,欢迎回来,您上一次的访问时间是:"+value);
flag=true;//说明找到了
break;
}
}
}else{
//什么cookie都没有
response.getWriter().println("亲,您是第一次访问该网站...");
}
//判断flag
if(!flag){
////有其他cookie,但是不是hiscookie
response.getWriter().println("亲,您是第一次访问该网站...");
}
//3:更新cookie的值为本次登陆的时间;
Cookie c = new Cookie("his",new Date().toLocaleString());
c.setPath("/");
c.setMaxAge(60*60);
response.addCookie(c);
1.9 Cookie与缓存的区别
缓存:
是指服务器给浏览器响应的所有信息;(包含页面上的所有内容,例如:图片、文件、页面)
Cookie:
是指服务器让浏览器记住的一些很少量的信息(简单理解为只是缓存中的一小部分信息)
2 案例2—验证码
2.1 需求
当用户访问jsp页面的时候,显示一张验证码,并让用户填写一个验证码,当用户提交填写的验证码的时候在servlet中比对用户填写的验证码是否正确。
2.2 技术分析
1: 由于用户访问jsp时会发出一次请求,提交表单的时候会发出第二次请求,因此只能使用会话技术,保存真正的验证码的值,才可以在服务器端比较用户填写的验证码是否正确;
2: 会话技术有两种,一个是客户端会话技术(Cookie),另一个是服务器端会话技术(session)
本案例采用session技术实现。(因为cookie保存在客户端,不安全!!!,在开发中验证码绝对不能存在cookie里面,极度不安全,非常容易被破解。)
2.3 Session概述
Session是服务器端的会话技术,可以简单理解为是服务器为每一个浏览器创建的一个内存空间,用于保存与浏览器交互的过程中(会话)的一些信息。
2.4 Session的作用
1:保存验证码;
2:保存用户登录的对象;
3:用于与浏览器会话的数据保存;
4:session可以自动与cookie相互关联,完成会话技术(服务器可以自动识别每一个浏览器的身份)
2.5 Session使用原则
能少存尽量少存!因为服务器使用的是服务器的内存空间,能少存尽量少存,能让他快点死尽量让他快点死。
2.6 Session如何使用
Session主要用于保存信息,且session由服务器创建,保存在服务器端,程序员只能获取session并使用session,不能手动创建session。
常用API:
获取session:
request.getSession();
存值:
Session对象.setAttribite(“属性名”,属性值);
取值:
Session对象.getAttribite(“属性名”);
删除值:
Session对象.removeAttribute(“属性名”);
销毁session对象:
Session对象.invalidate();
设置存活时间:
Session对象.setMaxInactiveInterval(秒数); (默认存活30分钟)
2.7 Session的生命周期问题(面试常用)
从session对象创建到session对象死亡;
(1)创建时机
1)这个浏览器在servlet中第一次使用session的时候会创建。
2)这个浏览器第一次访问jsp的时候,服务器也会为这个浏览器创建一个session对象。
(2)销毁时机
1)程序员调用invalidate方法(立刻销毁)
2)设置的存活时间到了(默认是30分钟)
3)服务器非正常关闭(例如突然断电)
注意事项:
1: 正常关闭服务器,session不会销毁,而是直接序列化到硬盘上,下一次服务器启动的时候,会重新创建出来。
2: 如果浏览器单方面关闭会话,服务器上对应的session不会死亡,但是会导致服务器给浏览器创建的JSESSIONID的cookie死亡,当cookie死亡后,会导致浏览器无法找到上一个session对象,会造成服务器中session死亡的假象。(非常浪费服务器性能)
2.8 案例的思路分析与代码步骤
部分参考代码:
项目结构
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function change(t) {
t.src="http://localhost/day33/code?"+new Date().getTime();
}
</script>
</head>
<body>
<font color="red">
<%=
request.getAttribute("msg")==null?"":request.getAttribute("msg")
%>
</font>
<form action="http://localhost/day33/CodeYanZheng" method="get">
验证码:<input type="text" name="code">
<img src="http://localhost/day33/code" onclick="change(this)">
<br>
<input type="submit" value="开始验证">
</form>
</body>
</html>
CodeServlet.java
这是个生成验证码的servlet,改写的代码是62-64行主要是将生成的验证码添加到session中
package com.itheima.demo04_验证码;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用java图形界面技术绘制一张图片
int charNum = 4;
int width = 20 * 4;
int height = 28;
// 1. 创建一张内存图片
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2.获得绘图对象
Graphics graphics = bufferedImage.getGraphics();
// 3、绘制背景颜色
graphics.setColor(Color.YELLOW);
graphics.fillRect(0, 0, width, height);
// 4、绘制图片边框
graphics.setColor(Color.GRAY);
graphics.drawRect(0, 0, width - 1, height - 1);
// 5、输出验证码内容
graphics.setColor(Color.RED);
graphics.setFont(new Font("宋体", Font.BOLD, 22));
// 随机输出4个字符
String s = "ABCDEFGHGKLMNPQRSTUVWXYZ23456789";
Random random = new Random();
// session中要用到
String msg = "";
int x = 5;
for (int i = 0; i < charNum; i++) {
int index = random.nextInt(32);
String content = String.valueOf(s.charAt(index));
msg += content;
graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
graphics.drawString(content, x, 22);
x += 20;
}
System.out.println("本次验证码是:"+msg);
//将msg的值保存到session中
request.getSession().setAttribute("seCode",msg);
// 6、绘制干扰线
graphics.setColor(Color.GRAY);
for (int i = 0; i < 5; i++) {
int x1 = random.nextInt(width);
int x2 = random.nextInt(width);
int y1 = random.nextInt(height);
int y2 = random.nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
// 释放资源
graphics.dispose();
// 图片输出 ImageIO
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
CodeYanZheng.java
package com.itheima.demo04_验证码;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class EqualsServlet
*/
public class CodeYanZheng extends HttpServlet {
//专门比较验证码的servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1:参 调 存 转
String c = request.getParameter("code");//获取用户填写的验证码
//2:获取session中的验证码
Object sec = request.getSession().getAttribute("seCode");//根据属性名从session获取属性值
//3:比较
if(c!=null&&c.equalsIgnoreCase((String)sec)){
//说明验证码对了
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("验证码正确,可以去购物了...");
}else{
//说明验证码错了
request.setAttribute("msg","验证码错误!");
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}