JavaWeb详解(第二篇)之Servlet基础简介-会话技术介绍

Posted 穆瑾轩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb详解(第二篇)之Servlet基础简介-会话技术介绍相关的知识,希望对你有一定的参考价值。

JavaWeb详解(第二篇)之Servlet基础简介-会话技术介绍

1、会话技术介绍

1.1、会话技术概述

1.1.1、什么是会话

    会话是指:用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话。

    为什么我们要使用会话技术?

    这里先科普下另外两个知识点HTTP 协议的五个特点:

    1)简单快速;2)灵活;3)无连接;4)无状态;5)支持B/S及C/S模式。

1.1.2、什么是无连接

    无连接:是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

    我们知道在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。早期这么做的原因是因为每个客户端(即浏览器)与服务器之间交换数据的间歇性较大,如果应用程序或者上层协议一直不发送数据,或者隔很长时间才发送一次数据,大部分通道实际上会很空闲,无端占用资源。因此HTTP的设计者有意利用这个特点将协议设计为请求时建立连接、请求完释放连接,以尽快将资源释放出来服务其他客户端,这样做的好处是,可以极大的减轻服务端的压力。

    但随着时间的推移,网页变得越来越复杂。通常一个网页可能会有很多组成部分,除了文本内容,还会有诸如:js、css、图片等静态资源。如果每遇到这样一个Web资源,浏览器就会重新建立一个TCP连接,再发起HTTP请求,然后关闭,这就显得很低效。后来keep-alive被提出来解决低效率的问题。

    从HTTP/1.1起,默认使用长连接(默认启用Keep-Alive),当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,一般HTTP协议中keep-alive的连接复用机制主要是由服务端来控制的。

1.1.3、什么是无状态

    无状态:是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。但是服务器不需要先前信息时它的应答就较快。

     HTTP在设计之初就没有考虑过要保存会话状态。无论你之前访问过什么网页、提交过什么数据,你获得的网页都是一样的;不同的浏览器访问同一个网页所得到的结果也是完全一样的。这就是所谓的“无状态”——访问URI得到的结果与上下文操作无关、与用户无关

1.1.4、为什么使用会话技术

    前面我们了解到HTTP并不会保存会话状态,也不关心整个上下文操作。面对日益复杂化的web应用,页面与页面、页面与用户之间难免产生点什么关系。

    比如案例一:A和B两人在某购物网站上登陆账号后,想要知道A/B的偏好,A通过Servlet_Look,点开了一个详情链接是一个雷蛇鼠标,而B也通过Servlet_Look,点开了一个详情链接是一个机械键盘,这些信息都会被保存下来,但是这个Servlet_Look并不知道是谁在查看。现在,如果想要把这些信息保存下来呢?

    思考下:能不能用我们之前学过的 HttpServletRequest 对象和 ServletContext 对象来保存这些数据呢?

    答案是:不能。

    不能用 HttpServletRequest 的原因:我们的一次会话中,存在多次请求和响应,而浏览器客户端的每一次请求都会产生一个 HttpServletRequest 对象,它只会保存此次请求的信息。之前保存的信息就会丢失。

    不能用 ServletContext 的原因:ServletContext对象是被整个web应用所共享的,将数据都存到这里,无疑会无法区分具体信息的归属。是A浏览的、还是B浏览的?

    比如案例二:A在自己电脑上,通过IE浏览器,请求Servlet_Login进入了购物网站登陆页面,并且成功登陆了。第二天,A又在自己电脑上通过IE浏览器请求Servlet_Login,此时服务器并不在知道是谁发起了这个HTTP请求,业务HTTP请求并不会标识是谁发起的。于是呢,A又要再次输一遍用户名和密码。

    那鉴于这种情况,服务器怎么去保存这个信息呢?如果要绑定客户端、绑定用户这确实很麻烦了,如果是其他人使用呢?如果换了客户端呢?

    于是,会话跟踪技术应运而生,一个是cookie 一个是session。会话跟踪技术可以解决我们很多问题。

1.2、Cookie技术

1.2.1、什么是Cookie

    Cookie是由W3C组织提出,最早由netscape社区发展的一种机制。网页之间的交互是通过HTTP协议传输数据的,而Http协议是无状态的协议。服务器也无法确定用户信息,于是,W3C就提出了:给每一个用户都发一个通行证,无论谁访问的时候都需要携带通行证,这样服务器就可以从通行证上确认用户的信息。通行证就是Cookie(一般一个cookie大小限制4k)。

    Cookie是客户端技术,服务器把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,浏览器会把请求的网址连同Cookie一同交给服务器。这样,web资源处理的就是用户各自的数据了。

1.2.2、Cookie常用API

方法说明
response.addCookie(Cookie cookie)将Cookie添加到客户端
Cookie cookies[]=request.getCookies();读取Cookie
Cookie(String name, String value)构造一个cookie包含指定名称和值
getValue()返回cookie的值
setValue(String newValue)将新值赋给一个cookie之后创建的cookie
setMaxAge(int expiry)设置cookie的生命周期,以秒为单位指定
getPath()返回这个cookie在服务器路径
setPath(String uri)指定一个路径对客户机cookie应该返回cookie
getDomain()返回这个cookie设置的域名
getName()返回cookie的名称

1.2.3、创建和读取Cookie

使用案例:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServletDemo1 extends HttpServlet{

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  response.setContentType("text/html;charset=gbk");
	      PrintWriter out = response.getWriter();
	      //创建Cookie
	      Cookie cookie=new Cookie("name","穆瑾轩");
	      //设置cookie的生命周期:MaxAge为正数,浏览器会把Cookie写到硬盘中
          //MaxAge为负数,Cookie是临时性的,仅在本浏览器内有效,关闭浏览器Cookie就失效了
          //如果MaxAge为0,则表示删除该Cookie
	      cookie.setMaxAge(3600);
	      //把cookie信息回写给浏览器
	      response.addCookie(cookie);
	      out.println("<form action='/CookieServletDemo1' method='post' >");
	      out.println("<input type='submit' value='创建Cookie' /><br />");
	      out.println("</form><br />");
	      out.flush();
	      out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=gbk");
		//读取cookie信息
	    Cookie cookies[]=request.getCookies();
	    PrintWriter out = response.getWriter();
	    for(int i=0;i<cookies.length;i++){
	         Cookie cookie=cookies[i];
	         out.println(cookie.getName()+"="+cookie.getValue());
	         out.println("生命周期:"+cookie.getMaxAge());
	    }
	    out.flush();
	    out.close();
	}
}

案例效果:

 

    google会把Cookie写到Cookies文件中。IE会单独生成一个文件,存相应的Cookie。如果存入的Cookie的key相同,则会覆盖。

1.2.4、Cookie的生命周期和有效路径

    Cookie的生命周期可以通过cookie.setMaxAge(秒),如果不设置setMaxAge则该cookie的生命周期当浏览器关闭时,就消亡;

cookie.setMaxAge(秒):

    正数,表示在指定的秒数后过期;

    负数,表示浏览器一关,Cookie就会被删除(默认值是-1)。

    0,表示马上删除Cookie。

    Cookie的path属性可以有效的过滤哪些Cookie可以发送给服务器,哪些不发。

使用案例:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServletDemo2 extends HttpServlet{
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  response.setContentType("text/html;charset=gbk");
	      PrintWriter out = response.getWriter();
	      
	      //创建Cookie:第一次访问/CookieServletDemo2时才添加
	      Cookie cookie=new Cookie("name","穆瑾轩");
	      //设置cookie的生命周期
	      cookie.setMaxAge(3600);
	      
	      //创建Cookie2:如果访问/CookieServletDemo3时才添加
	      Cookie cookie2=new Cookie("name2","穆瑾轩2");
	      //设置cookie2的生命周期
	      cookie2.setMaxAge(3600);
	      cookie2.setPath("/CookieServletDemo3");
	      
	      //把cookie信息回写给浏览器
	      response.addCookie(cookie);
	      response.addCookie(cookie2);
	      out.println("<form action='/CookieServletDemo2' method='post' >");
	      out.println("<input type='submit' value='创建Cookie' /><br />");
	      out.println("</form><br />");
	      out.flush();
	      out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=gbk");
		//读取cookie信息
	    Cookie cookies[]=request.getCookies();
	    PrintWriter out = response.getWriter();
	    for(int i=0;i<cookies.length;i++){
	         Cookie cookie=cookies[i];
	         out.println(cookie.getName()+"="+cookie.getValue());
	         out.println("生命周期:"+cookie.getMaxAge());
	    }
	    
	    //创建Cookie3:如果访问/CookieServletDemo2时才添加
	    Cookie cookie3=new Cookie("name3","穆瑾轩3");
	    //设置cookie3的生命周期
	    cookie3.setMaxAge(3600);
	    cookie3.setPath("/CookieServletDemo2");
	    response.addCookie(cookie3);
	    
	    out.flush();
	    out.close();
	}
}

案例效果:

    上述案例中:当我访问http://localhost:8080/CookieServletDemo2时cookie2并没有被添加。

1.2.5、Cookie的域名

    我们在学习javascript的时候,JavaScript出于安全方面的考虑(因同源策略的限制),不允许跨域调用其他页面的对象。同样,Cookie的隐私安全机制决定Cookie也是不可跨域的。简单的理解就是,不同URL之间的Cookie对象是无法访问的。

    我们访问网站,很多为了记忆便捷,于是有了域名的概念。域名最终会被翻译为对应的IP地址,首先查找的就是我们的hosts文件,如果没有才会去DNS域名系统中获取。

此案例执行前提:

    1)在C:\\Windows\\System32\\drivers\\etc路径下找到:hosts文件

    配置如下域名和IP的映射关系:

    127.0.0.1 localhost ​

    127.0.0.1 www.mjx.com

使用案例:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CookieServletDemo3 extends HttpServlet{
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  response.setContentType("text/html;charset=gbk");
	      PrintWriter out = response.getWriter();
	      
	      //创建Cookie:第一次访问/CookieServletDemo2时才添加
	      Cookie cookie=new Cookie("name","穆瑾轩from_www.mjx.com");
	      //设置cookie的生命周期
	      cookie.setMaxAge(3600);
	      //把cookie信息回写给浏览器
	      response.addCookie(cookie);
	      out.println("<form action='/CookieServletDemo3' method='post' >");
	      out.println("<input type='submit' value='创建Cookie' /><br />");
	      out.println("</form><br />");
	      out.flush();
	      out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=gbk");
		//读取cookie信息
	    Cookie cookies[]=request.getCookies();
	    PrintWriter out = response.getWriter();
	    for(int i=0;i<cookies.length;i++){
	         Cookie cookie=cookies[i];
	         out.println(cookie.getName()+"="+cookie.getValue());
	         out.println("生命周期:"+cookie.getMaxAge());
	    }
	    out.flush();
	    out.close();
	}
}

案例效果:

     我们看到Domain栏位正是我们的域名,并且不同的域名间的Cookie是不共享的。

1.3、session技术

1.3.1、什么是session

    前面我了解到Cookie是客户端技术, Session是服务器端技术,是另一种记录浏览器状态的机制。利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

    为什么需要session?Session比Cookie使用方便,Session可以解决Cookie解决不了的事情Session可以存储对象,Cookie只能存储字符串。可以把Session看做是一个容器类类似HashMap。

    session可以用来做什么:网上商城中的购物车、保存登录用户的信息、防止用户非法登录到某个页面中等等。

1.3.2、session常用API

方法描述
long getCreationTime();获取Session被创建时间
String getId();获取Session的id
long getLastAccessedTime();返回Session最后活跃的时间
ServletContext getServletContext();获取ServletContext对象
void setMaxInactiveInterval(int var1);设置Session超时时间
int getMaxInactiveInterval();获取Session超时时间
Object getAttribute(String var1);获取Session属性
Enumeration getAttributeNames();获取Session所有的属性名
void setAttribute(String var1, Object var2);设置Session属性
void removeAttribute(String var1);移除Session属性
void invalidate();销毁该Session
boolean isNew();该Session是否为新的

1.3.3、创建/读取/删除Session

1)得到session:

    HttpSession session=request.getSession();

    注: session是存在服务器的内存中,一个用户浏览器,独享一个session域对象。此方法等效于request.getSession(true),获取session,如果没有则新创建一个session。当然那就还有request.getSession(false),去获取session,如果没有则不创建。

2)得到session的ID

    session.getId()

    sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。tomcat生成的sessionid叫做jsessionid。

    tomcat的ManagerBase类提供创建sessionid的方法: 随机数+时间+jvmid

    客户端只保存sessionid到cookie中,而不会保存session,session对象的属性保存在服务器的内存中。

2)向session添加属性

    session.setAttribute(String name, Object val);

3)从session得到属性

    String name=(String) session.getAttribute(String name);

4)从session删除属性

    session.removeAttribute("username");

1.3.4、Session生命周期和有效期

session的默认生命周期是30分钟。

1)设置Session超时时间

    a)方式一:在tomcat/conf/web.xml修改配置

<!--找到这个配置:默认30分钟,超时时间修改为20分钟-->
<session-config>           
    <session-timeout>20</session-timeout>            
</session-config>

    b)方式二:在单个web应用的web.xml下去新增配置上诉配置

    c)方式三:在程序中单独设置:setMaxInactiveInterval(int var1);

    正是为超时时长(单位秒);负数表示永不超时。  

2)getMaxInactiveInterval();

    获取Session的超时时间。

    注:Session的超时时间是以最后访问时间到下此访问时的这个时间段。如果这个时间段超过了超时时间,Session就会从内存中移除。

3)invalidate();

    让当前的Session会话马上超时无效。

    注:超时无效,并不会删除Session的id,只是此Session对象无法获取Session的属性。

使用案例:

1)新建一个SessionDemo

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SessionDemo extends HttpServlet{
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  response.setContentType("text/html;charset=gbk");
		  PrintWriter out = response.getWriter();
	      out.println("<body>");
	      out.println("<iframe name='target' width='500' height='300' style='float: left;'></iframe>");
	      out.println("<div style='float: left;'>");
	      out.println("<ul style='list-style: none;'>");
	      out.println("<li><a href='/SessionDemo2?action=isNew' target='target'>Session的创建和获取(id号、是否为新创建)</a></li>");
	      out.println("<li><a href='/SessionDemo2?action=setAttribute' target='target'>Session域数据的存储</a></li>");
	      out.println("<li><a href='/SessionDemo2?action=getAttribute' target='target'>Session域数据的获取</a></li>");		
	      out.println("<li>Session的存活</li>");
	      out.println("<li>");
	      out.println("<ul style='list-style: none;'>");
	      out.println("<li><a href='/SessionDemo2?action=getMaxInactiveInterval' target='target'>获取Session的超时数据</a></li>");
	      out.println("<li><a href='/SessionDemo2?action=defaultLife' target='target'>Session的默认超时及配置</a></li>");
	      out.println("<li><a href='/SessionDemo2?action=lifeNew' target='target'>Session3秒超时销毁</a></li>");
	      out.println("<li><a href='/SessionDemo2?deleteNow=isNew' target='target'>Session马上销毁</a></li>");
	      out.println("</ul>");
	      out.println("</li>");
	      out.println("</ul>");
	      out.println("</div>");
	      out.println("</body>");
	      out.flush();
	      out.close();
	}
}

2)新建一个SessionDemo2,并配置好web.xml

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SessionDemo2 extends HttpServlet{
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String action = request.getParameter("action");
		System.out.println(action);
		doPost(request, response);
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=gbk");
		if("isNew".equals(request.getParameter("action"))) {
			 // 创建和获取Session会话对象:等效于request.getSession(true)
	        HttpSession session = request.getSession();
	        // 判断 当前Session会话,是否是新创建出来的
	        boolean isNew = session.isNew();
	        // 获取Session会话的唯一标识 id:此id由服务器创建:随机数+时间+jvmid
	        String id = session.getId();
	        response.getWriter().write("得到的Session,它的id是:" + id + " <br /> ");
	        response.getWriter().write("这个Session是否是新创建的:" + isNew + " <br /> ");
		}else if("getAttribute".equals(request.getParameter("action"))) {
			Object attribute = request.getSession().getAttribute("key1");
			response.getWriter().write("从Session中获取出key1的数据是:" + attribute);
		}else if("setAttribute".equals(request.getParameter("action"))) {
			request.getSession().setAttribute("key1", "value1");
			response.getWriter().write("已经往Session中保存了数据");
		}else if("deleteNow".equals(request.getParameter("action"))) {
			 // 先获取Session对象
	        HttpSession session = request.getSession();
	        // 让Session会话马上超时:超时并不会移除sessionid
	        session.invalidate();
	        response.getWriter().write("Session已经设置为超时(无效)");
		}else if("defaultLife".equals(request.getParameter("action"))) {
			// 获取了Session的默认超时时长
	        int maxInactiveInterval = request.getSession().getMaxInactiveInterval();
	        response.getWriter().write("Session的默认超时时长为:" + maxInactiveInterval + " 秒 ");
		}else if("lifeNew".equals(request.getParameter("action"))) {
			// 先获取Session对象
	        HttpSession session = request.getSession();
	        // 设置当前Session3秒后超时
	        session.setMaxInactiveInterval(3);
	        response.getWriter().write("当前Session已经设置为3秒后超时");
		}else if("getMaxInactiveInterval".equals(request.getParameter("action"))) {
			// 先获取Session对象
	        HttpSession session = request.getSession();
	        response.getWriter().write("当前Session的超时时间是:"+session.getMaxInactiveInterval());
		}
	}
}

案例效果:

    更换浏览器,同样能获得一个的sessionid。为什么服务器能够为不同的浏览器提供不同session?

    因为每个浏览器去访问web站点的时候,如果发出的http请求头没有带JSESSIONID头就会自动给你创建一个并返回。

    session技术底层其实是基于Cookie技术实现的。在没有当Cookie的情况下,发送请求,当request.getSession();创建了会话对象,服务器(Tomcat)就会创建一个Cookie对象,这个对象的key值是JSESSIONID。然后每次请求的时候,都会把sessionid以Cookie的形式发送给服务器。request.getSession();就会根据Cookie的id值找到之前创建好的session对象。

 1.3.5、Session应用

1)登陆验证

HttpSession session=request.getSession();
User u=(User) session.getAttribute("user");
if(u==null){
   request.setAttribute("error", "请输入用户名,密码登录");
   //如果之前没有登陆,则转发到登陆页面
   request.getRequestDispatcher("login.jsp").forward(request, response);
   return;
}

2)验证码应用

第一步:新建一个login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>

<!DOCTYPE html>
<html>
<head>
<title>login</title>
</head>
<body onload="changeCode('ImageServlet');">
	<form action="/LoginServlet" method="post">
		用户名: <input type="text" name="username"><br> 
		密码: <input type="password" name="password"><br> 
		验证码: <input type="text" name="checkcode"> 
		<a href="javascript:changeCode('ImageServlet')"><img id="codeimg"  style="width: 60px;height:20px;"><br></a>
		<br> <input type="submit" value="登录">
	</form>
</body>
<script type="text/javascript">
function changeCode(url){
	window.document.getElementById("codeimg").src=url+"?"+Math.random();
}

</script>
</html>

第二步:新建一个LoginServlet

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet{

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.getRequestDispatcher("login.jsp").forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=GBK");
	      PrintWriter out = response.getWriter();
	      //获取用户的username和userpsw和验证码
	      String username=request.getParameter("username");
	      String userpsw=request.getParameter("userpsw");
	      String checkCode=request.getParameter("checkcode");
	      String checkCode2=(String) request.getSession().getAttribute("checkcode");
	      System.out.println(checkCode+"=="+checkCode2);
	      if(checkCode!=null && checkCode.toUpperCase().equals(checkCode2)){
	    	  response.getWriter().write("登陆成功!");
	      }
	      else{
	         request.getRequestDispatcher("login.jsp").forward(request, response);
	         if(checkCode==null) {
	        	 System.out.println("验证码为空!"); 
	        	 return;
	         }
	         request.setAttribute("err", "验证码有误");
	         System.out.println("验证码有误!");
	      }
	      out.flush();
	      out.close();
	}
}

第三步:新建一个ImageServlet

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
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 ImageServlet extends HttpServlet{
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		  // 7.禁止浏览器缓存随机图片
	      response.setDateHeader("Expires", -1);
	      response.setHeader("Cache-Control", "no-cache");
	      response.setHeader("Pragma", "no-cache");
	      // 6.通知客户机以图片方式打开发送过去的数据
	      response.setHeader("Content-Type", "image/jpeg");
	      // 1.在内存中创建一副图片
	      BufferedImage image = new BufferedImage(60, 30,
	      BufferedImage.TYPE_INT_RGB);
	      // 2.向图片上写数据
	      Graphics g = image.getGraphics();
	      // 设背景色
	      g.setColor(Color.BLACK);
	      g.fillRect(0, 0, 50, 20);
	      // 3.设置写入数据的颜色和字体
	      g.setColor(Color.RED);
	      g.setFont(new Font(null, Font.BOLD, 20));
	      // 4.向图片上写数据
	      String num = makeNum();
	      // 这句话就是把随机生成的数值,保存到session
	      request.getSession().setAttribute("checkcode", num);
	      System.out.println("当前验证码:"+num);
	      // 通过session就可以直接去到随即生成的验证码了
	      g.drawString(num, 0, 20);
	      // 5.把写好数据的图片输出给浏览器
	      ImageIO.write(image, "jpg", response.getOutputStream());
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
	
	// 该函数时随机生成7位数字
   public String makeNum(){
      String str = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ";
      String s = "";
      for (int i = 0; i < 4; i++){
         int k = (int) (Math.random() * 36);
         s = s + str.charAt(k);
      }
      return s;
   }
}

案例效果:

1.3.6、总结cookie与session区别

1)存放位置

    Cookie 存在客户端的临时文件夹;

    Session 存放在服务器内存中,一个session 域对象为一个用户浏览器服务。

2)安全性

    Cookie 是以明文方式存放在客户端,安全性弱,可以通过md5方式加密再存放;

    Session 是存放在服务器内存中,所以安全性好。因为session 会占用服务器内存,因此不要向session存放过多过大的对象,会影响性能。

3)网络传送量

    Cookie 会传递信息给服务器;

    Session 的属性值不会给客户端。

4)生命周期

    Cookie的生命周期是累计时间,比如:给cookie设置setMaxAge(30,30S后失效;

    Session 的生命周期是间隔时间,比如:设置session 20min,在20min内,如果没有访问session,则session 失效。

以上是关于JavaWeb详解(第二篇)之Servlet基础简介-会话技术介绍的主要内容,如果未能解决你的问题,请参考以下文章

javaweb回顾第二篇tomcat和web程序部署

JavaWeb详解(第一篇)之Servlet基础简介

JavaWeb详解(第三篇)之Servlet基础简介-过滤器Filter&Listener监听器

DWR第二篇之逆向Ajax

JavaWeb开发之详解Servlet及Servlet容器

Javaweb编程之servlet基础