servlet中的cookie和session问题小结

来源:互联网 发布:js input只能输入数字 编辑:程序博客网 时间:2024/05/29 07:36

会话的概念其实很简单

用户的打开一个浏览器,点击多个超链接访问 Web 服务器中的多个资源,然后关闭浏览器的过程,称为会话。

首先要知道会话的原理

服务器与客户机数据交互问题

每个用户与服务器进行交互的过程中,各自都会有一些数据,程序要想办法保存每个用户的数据。

例如现在有一个购物网站,当用户购物的时候,我们需要将用户购买的商品记录下来,最后结账的时候为客户展现已购买的商品。在 Servlet 中有多种交互数据的

方式。

(1) ServletContext 域保存用户数据。如果是这样的话,那么在整个当前 Web 应用范围内,这个用户的数据都是被共享的。假设 A 用户购买了商品 a ,此时 B

用户拿到了 ServletContext 中的 a 数据,进行了修改,那么当 A 用户转到结账页面的时候,发现商品已经被更改了。所以这种方法是不可行的。

(2) resquest 域保存用户数据。如果使用了 request 那么我们先看一下 request 的生命周期,每当用户向服务器发送一个请求的时候,服务器都会创建一个

request 来进行处理。如果 A 用户购买了某个商品,此时再点击超链接去结账的时候,又向服务器发送了一个请求,服务器又创建了一个全新的 request ,那么

新创建的这个 request 中是不会存在 A 用户购买的商品信息的。也许你会想到用请求转发,当 A 用户购买了商品后,服务器将请求转发给结账的页面。这种方法

在技术上是可行的,但在用户体验方面是不好的。因为每当用户点击购买一个商品的时候,服务器都会转发到结账页面,用户如果想购买 100 件商品后,那么就必

须进行 100 次结账操作。所以 request 方式也是不可行的。

保存会话过程中数据的两种技术(kookie   session)

1、Cookie ,Cookie 是客户端技术,程序把每个用户的数据以 cookie 的形式写给用户各自的浏览器,当用户使用浏览器去访问 Web 服务器资源时,就会带着

各自的数据去。这样 Web 资源处理的就是用户各自的数据了。(用户各自拿着各自的数据)

(1) 浏览器向服务器发送请求,访问服务器的某个资源

(2) Servlet 以 Cookie 的形式回写给用户,让有用户自己保存数据

(3) 浏览器再访问服务器其他资源的时候,会带着 Cookie 去访问服务器,其他资源通过用户带过来的 Cookie 提取出数据,为用户服务

2、Session ,Session 是服务器端技术,利用这个技术,服务器在运行时可以为每个用户的浏览器创建一个独享的 session 对象,由于 session 是用户浏览器独

享,所以每个用户在访问 Web 资源时,可以把各自的数据放在 session 中,当用户访问服务器的时候,服务器会取出各自的 session 为其服务。(服务器为每个

用户分别保存数据)
(1) 浏览器向服务器发送请求,访问服务器的某个资源

(2) 服务器先运行 session = resquest.getSession() ,之后服务器发现如果还没有为这个用户创建 Session 对象,则为用户创建一个独享的 Session。

(3) 将用户的数据存放在这个独享的 Session 对象

(4) 当浏览器再访问其他服务器资源的时候,服务器通过 session = resquest.getSession() ,服务器发现已经存在了一个 Session 对象,那么服务器就会取出这个

Session 对象中的数据为用户服务

cookie常用 API

Cookie 的构造函数创建一个 Cookie,指定 Cookie 的名和 Cookie 的值。

向客户机输出 Cookie ,使用 response 中的 addCookie(Cookie cookie) 方法。

获取客户机 Cookie ,使用 resquest 中的 getCookies() 方法,返回的是一个 Cookie[] 数组。

setMaxAge 和 getMaxAge 方法是用于设置 Cookie 的有效期。如果没有显示的设置 Cookie 的有效期,那么这时的 Cookie 是一个会话级别的 Cookie,Cookie 会

保存在浏览器的进程所对应的那快内存区域。当会话结束了以后, Cookie 就会被删除setPath 和 getPath ,如果设置了一个目录进去,那么当浏览器访问服务器

这个目录下资源以及子目录的时候才会带着 Cookie 过去。如果没有设置 setPath 那么默认的目录为当前 Web 应用。

编程实例:记录用户上次访问时间
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        //你得到上次访问的cookie对象
        out.print("您上次访问的时间是: ");
        Cookie cookies[] = request.getCookies();
        for (int i = 0; cookies!=null && i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if("lastTime".equals(cookie.getName())){
                String lastTime = cookie.getValue();
                Date date = new Date(Long.parseLong(lastTime));
                out.println(date.toLocaleString());
            }
        }
        
        //记录这次cookie信息记录你这次访问日期
        //创建Cookie
        Cookie ck = new Cookie("lastTime", System.currentTimeMillis()+"");
        //有效日期为0时 创建cookie到会话结束 删除cookie
        ck.setMaxAge(3600);
        ck.setPath("/20111024/servlet/cookieDemo");
        //发送给你的响应
        response.addCookie(ck);
Cookie 细节

一个 Cooike 只能标识一种信息,它至少含有一个标识名称(NAME)和值(VALUE)。一个 Web 站点可以给一个 Web 浏览器发送多个 Cookie,一个浏览器也

可以存储多个 Web 站点提供的 Cookie。

浏览器一般只允许存放 300 个 Cookie,每个站点最多存放 20 个 Cookie,每个 Cookie 的大小限制为 4KB。

如果创建了一个 Cookie,并将它发送到浏览器,默认情况下它是一个会话级别的 Cookie,也就是存储在浏览器内存中。用户如果退出浏览器之后,Cookie 会被马

上删除,如果希望浏览器将该 Cookie 存储在磁盘上,则需要使用 maxAge,并给出一个以秒为单位的时间。将最大时间设为 0 则是命令浏览器删除该 Cookie。

当删除 Cookie 的时候,path 必须保持一直。

编程实例:记录用户浏览过的商品信息

基本思路

(1) 在一个首页中有两个区域,一个区域是显示商品的所有信息,并链接到商品详细信息的页面,另一个区域是显示用户浏览过的商品

(2) 当用户点击某个商品的时候,浏览器向服务器请求访问详细信息页面,并将商品的 id 号传过去。

(3) 详细信息页面通过 id 号,列出商品的详细信息。并构建一个 Cookie 传给客户机保存。response.addCookie 方法会覆盖掉以前的 Cookie ,但是 Cookie 的名

字和路径必须要一致。

(4) 当返回到商列表页面时,服务器拿到了用户带过去的 Cookie 进而显示浏览记录。

实现与数据库的连接

import cn.csdn.web.domain.Goods;

public class GoodsDaoImpl implements GoodsDao{
    //URL地址
    private static final String URL="jdbc:mysql://localhost:3306/3g?user=root&password&useUnicode=true&characterEncoding=UTF8";
    private static Connection conn;
    private static PreparedStatement pstmt;
    private static ResultSet rs;
        static{
            try {
                /*第二步:加载驱动程序*/
                Class.forName("com.mysql.jdbc.Driver");
                /*第三步:获取连接对象*/
                conn=DriverManager.getConnection(URL);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            
            }
        }
    public boolean insert(Goods entity) {
        /* 第一步:声明返回变量 */
        boolean flag = false;
        /* 第二步:获取连接对象 */
        try {
            /* 第三步:定义sql语句 */
            String sql = "insert into goods (name,price,image,remark) values(?,?,?,?)";
            /* 第四步:根据sql语句创建预处理对象 */
            pstmt = conn.prepareStatement(sql);
            /* 第五步:为占位符赋值 */
            int index = 1;
            pstmt.setObject(index++, entity.getName());
            pstmt.setObject(index++, entity.getPrice());
            pstmt.setBinaryStream(index++, entity.getImg());
            pstmt.setCharacterStream(index++, entity.getRemark());
//            pstmt.setBlob(index++,entity.getImg());
//            pstmt.setClob(index++,entity.getRemark());
            /* 第六步:执行更新 */
            int i = pstmt.executeUpdate();
            /* 第七步:判断 */
            if (i > 0) {
                flag = true;
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    //释放资源

        release(rs, pstmt);
        return flag;
    }

    private void release(ResultSet rs2, PreparedStatement pstmt2) {
        try{
        if(rs!=null){
            rs.close();}
            if(pstmt!=null){
                pstmt.close();}
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public List<Goods> findAll() {
        List<Goods> allentities=new ArrayList<Goods>();
        String sql="select id,name,price,image,remark from goods";
        try{
            pstmt=conn.prepareStatement(sql);
            rs=pstmt.executeQuery();
            while(rs.next()){
                Goods entity=new Goods();
                entity.setId(rs.getInt("id"));
                entity.setName(rs.getString("name"));
                entity.setPrice(rs.getDouble("price"));
                entity.setImg(rs.getBinaryStream("image"));
                entity.setRemark(rs.getCharacterStream("remark"));
                allentities.add(entity);
                
            }
            release(rs, pstmt);
        }catch(Exception e){
            e.printStackTrace();
        }
        return allentities;
    }

    public Goods findById(Integer id) {
        Goods entity=new Goods();
        String sql="select id,name,price,image,remark from goods where id=?";
        try{
            pstmt=conn.prepareStatement(sql);
            int index=1;
            pstmt.setInt(index++, id);
            rs=pstmt.executeQuery();
            if(rs.next()){
                entity.setId(rs.getInt("id"));
                entity.setName(rs.getString("name"));
                entity.setPrice(rs.getDouble("price"));
                entity.setImg(rs.getBinaryStream("image"));
                entity.setRemark(rs.getCharacterStream("remark"));
            }
            release(rs, pstmt);
        }catch(Exception e){
            e.printStackTrace();
        }
        return entity;
    }

}

存入商品    查询所有商品   根据id查询商品信息

下边是servlet实现功能

商品首页   列举出所有的商品

public class GoodsServlet extends HttpServlet {
    private GoodsService gService=new GoodsServiceImpl();
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id =request.getParameter("id");
        List<Goods> entities=gService.findAll();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        

        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>XXX网站的首页</TITLE></HEAD>");
        out.println("  <BODY>");
        out.println("<table border=\"2px\">");
        out.println("<tr>");
        out.println("<th>序号</th><th>名称</th><th>价格</th>");
        out.println("</tr>");
        for(Goods entity:entities){
            out.println("<tr><td>"+entity.getId()+"</td><td><a href=\"detail.do?id="+entity.getId()+"\">"+entity.getName()+"</td><td>"+entity.getPrice()+"</td></tr>");
        }
        
           
        out.println("</table>");
        out.println("  </BODY>");
        out.println("</HTML>");
        //显示浏览过的商品
        String value=null;
        Cookie cookies[]=request.getCookies();
        for (int i = 0; cookies!=null&&i < cookies.length; i++) {
            if("goodsHistory".equals(cookies[i].getName())){
                value=cookies[i].getValue();
            }
        }
                if(value!=null){
                    String ids[]=value.split("\\_");
                    out.println("显示浏览过的商品");
                    out.println("<table>");
                    out.println("<tr><th>商品名称</th></tr>");
                    for (int j = 0; j < ids.length; j++) {
                    out.println("<tr>");
                    out.println("<td>");
                    out.println("<a href=\"detail.do?id="+Integer.parseInt(ids[j])+"\">"+gService.findById(Integer.parseInt(ids[j])).getName());
                    out.println("</td>");
                    out.println("</tr>");
                    }
                    out.println("</table>");
                }
        
        
        out.flush();
        out.close();
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }

}

查询商品的结果

public class GoodsDetailServlet extends HttpServlet {

    private GoodsService gService=new GoodsServiceImpl();
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String id =request.getParameter("id");
        Integer numId=Integer.parseInt(id);
        Goods entity=gService.findById(numId);
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>XXX网站的首页</TITLE></HEAD>");
        out.println("  <BODY>");
        out.println("<table border=\"\">");
        out.println("<caption>显示本网站所有的商品信息</caption>");
        out.println("<tr>");
        out.println("<th>序号</th><th>名称</th><th>价格</th><th>图片</th><th>描述信息</th>");
        out.println("</tr>");
        
            out.println("<td>"+entity.getId()+"</td><td>"+entity.getName()+"</td><td>"+entity.getPrice()+"</td><td>"+entity.getImg()+"</td><td>"+entity.getRemark()+"</td>");
        
        out.println("</table>");
        out.println("  </BODY>");
        out.println("</HTML>");
        String value=makeCookieValue(request,id);
        Cookie cookie=new Cookie("goodsHistory", value);
        cookie.setMaxAge(60*60);
        cookie.setPath("/20111024");
        response.addCookie(cookie);
        
        out.flush();
        out.close();

    }

    
    private String makeCookieValue(HttpServletRequest request, String id) {
        //声明返回变量
        String goodsHistory=null;
        // 获取cookie
        Cookie cookies[]=request.getCookies();
        for (int i = 0; cookies!=null&&i < cookies.length; i++) {
            if("goodsHistory".equals(cookies[i].getName())){
                goodsHistory=cookies[i].getValue();
                
            }
        }
        if(goodsHistory==null){
            goodsHistory=id;
        }else{
            LinkedList<String> list=new LinkedList<String>(Arrays.asList(goodsHistory.split("\\_")));
            if(list.contains(id)){
                list.remove(id);
                list.addFirst(id);
            }else{
                if(list.size()>=3){
                    list.removeLast();
                    list.addFirst(id);
                }else{
                    list.addFirst(id);
                }
            }
        
        StringBuffer sb=new StringBuffer();
        for(String ids:list){
            sb.append(ids+"_");
        }
        sb.deleteCharAt(sb.length()-1);
        goodsHistory=sb.toString();
        }
        return goodsHistory;
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //doGet(request, response);
    }

}

Session 对象的生命周期

 用户第一次访问服务器时没有 Session ,当通过 request.getSession(); 以后,服务器才会创建一个 Session。之后 Session 对象会一直驻留在服务器的内存中。

当浏览器关闭的时候,服务器并不是马上摧毁 Session 对象,而是默认的将 Session 对象保存 30 分钟。我们可以通过两种方式修改 Session 的摧毁时间: (1) 修

改当前应用的 Web.xml 文件。在 <web-app> 元素下创建子元素(以分钟为单位):

<session-config>

 <session-timeout>2</session-config>

</session-config>

(2) 在程序中加入代码:

session.invalidate(); 通过 Session 对象摧毁,该方法会立即摧毁 Session 对象

4、Session 内部机制

 Session 的工作其实是基于 Cookie 的。当服务器创建一个 Session 的时候,会为每一个 Session 对象指定一个 ID 号,然后以 Cookie 的形式发送到客户机,让

用户再次访问服务器时,会带着有 Session ID 号的 Cookie 提交给服务器。注意,服务器会写给客户机的 Cookie 是一个会话级别的 Cookie,当浏览器关闭以

后,Cookie 被清除,所以再次开浏览器的时候,由于没有 Cookie 传递给服务器,所以服务器找不到以前的 Session 对象。

5、更改保存 Session ID 号 Cookie 的生命周期

当用户在购买商品的时候,不小心关闭了浏览器,因为先前的 Cookie 是一个会话级别的,所以 Cookie 会被摧毁。当用户再次打开浏览器的时候,先前买的商品

信息就无法获得。因此我们要手动发送 Session id号,并更改 Cookie 的有效期。

  HttpSession session=request.getSession();
        session.setAttribute("name", "aaaa");

当用户禁用 Cookie 的处理情况

 由于当用户禁用了 Cookie,所以服务器给客户机发送的 Session ID 号,客户机是收不到的。所以服务器就无法用原来的 Session 为客户机服务。(当用户的主

机名为 localhost 访问自己主机的时候,本机是不阻止接受 Cookie 的。)

解决方法:URL 重写。既然用户阻止了 Cookie 接受数据,能么我们可以通过将数据加在 URL 地址栏的后面,作为参数传给客户机。然后客户机再访问浏览器的

时候服务器依然可以获取到数据。

public class IndexServlet extends HttpServlet {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private GoodsService gService=new GoodsServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getSession();
        List<Goods> list=gService.findAll();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String url=response.encodeURL("/201110251/buy");
        for(Goods entity:list){
            out.println(entity.getName()+"<a href='"+url+"?id="+entity.getId()+"'>加入购物车</a>"+"</br>");
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
     
}

buyServlet中

public class BuyServlet extends HttpServlet {
    private GoodsService gService=new GoodsServiceImpl();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String rid=request.getParameter("id");
        Integer id=Integer.parseInt(rid);
        Goods entity=gService.findById(id);
        HttpSession session=request.getSession();
        Cookie cookie=new Cookie("JSESSIONID", session.getId());
        cookie.setMaxAge(10*60);
        cookie.setPath("/201110251");
        response.addCookie(cookie);
        List<Goods> carts=(List<Goods>) session.getAttribute("carts");
        if(carts==null){
            carts=new ArrayList<Goods>();
            session.setAttribute("carts", carts);
            
        }
        carts.add(entity);
        String url=response.encodeRedirectURL("/201110251/listcarts");
        response.sendRedirect(url);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
          doGet(request, response);
    }
   
}

细节:如果当用户没有禁用 Cookie 的时候,首次访问服务器,服务器发现客户机带了 Cookie 过来,所以服务器第二次就自动不重写 URL。如果用户即禁用了

Cookie 又在访问的过程中关闭了浏览器,那么就没有办法再次或得到服务器原来的 session。为了良好的解决为题,我们一般既要通过 Cookie 的方式保存

Session id ,又要用 URL 重写的方式保存 Session id。

购物车的实现  基本上以上都写出了   下边不写了

重复提交也是个浏览器主要的问题

服务器拒绝请求有三种可能

存储session域中的表单标识号与提交的表单标识号不同

当前用户的session中不存在表单标识号

用户提交的表单标识号中没有标识号字段

具体实现方法

页面

public class CreateFormServlet extends HttpServlet {

    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        String token=null;//makeToken();
        request.getSession().setAttribute("token",token);
        PrintWriter out=response.getWriter();
        out.println("<form action='/20111026/register.do' method='post'>");
        out.println(" 用户名:<input type='text' name='uname'/>");
        out.println("<br/>");
        out.println("密&nbsp;&nbsp;码:<input type='password' name='upass'/>");
        out.println("<br/>");
        out.println("性别:<input type='radio' name='usex' value='男'>男"+
                "<input type='radio' name='usex' value='女'>女");
        out.println("<br/>");
        out.println("<input type='text' name='uage'/>必须输入1-120之间的整数");
        out.println("<input type='hidden' name='token' value='"+token+"'/>");
        out.println("<br/>");
        out.println("<input type='submit' value='注册'>");
        out.println("<input type='reset' value='重置'/>");
        out.println("</form>");
    }

    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}
class MakeToken{
    private MakeToken(){}
    private static MakeToken tp;
    public static MakeToken getTp(){
        if(tp==null){
            tp=new MakeToken();
            
        }
        return tp;
    }
    public String makeToken() throws Exception{
        String token = System.currentTimeMillis()+new Random().nextInt(100000)+"";
        MessageDigest digest=MessageDigest.getInstance("md5");
        byte result[]=digest.digest(token.getBytes());
        BASE64Encoder encoder=new BASE64Encoder();
        token=encoder.encode(result);
        return token;
    }
    
}

servlet的实现

public class AdminInsertServlet extends HttpServlet {
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        if(isToken(request)){
            System.out.println("表单不能重复提交");
            //response.sendRedirect("/20111026/cform.do");
        }else{
        
        
        String name =request.getParameter("uname");
        String pass =request.getParameter("upass");
        String sex =request.getParameter("usex");
        String rage =request.getParameter("uage");
        Integer age=null;
        if("".equals(rage)||rage==null){
            age=null;
        }else{
            age=Integer.parseInt(rage);
        }
        Admin entity=new Admin();
        entity.setName(name);
        entity.setPass(pass);
        entity.setSex(sex);
        entity.setAge(age);
        System.out.println(entity.toString() );
        request.getSession().removeAttribute("token");
        }
    }

    
    private boolean isToken(HttpServletRequest request) {
        String rtoken=request.getParameter("token");
        if("".equals(rtoken)||rtoken==null){
            return true;
        }
        String token=(String) request.getSession().getAttribute("token");
        if(token==null){
            return true;
        }
        if(!rtoken.equals(token)){
            return true;
        }
        return false;
    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

最后为了保障用户的安全问题,一次性验证码是个解决安全问题的最佳方法

servlet中

    private AdminService aService = new AdminServiceImpl();
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String checkcode = request.getParameter("checkcode");
        if("".equals(checkcode)){
            request.setAttribute("msg","验证码为空");
            RequestDispatcher rd=request.getRequestDispatcher("/Login.jsp");
            rd.forward(request, response);
        }else{
            String ckcode=(String) request.getSession().getAttribute("ckcode");
            if(checkcode.equals(ckcode)){
                String name = request.getParameter("uname");
                String pass = request.getParameter("upass");
                Admin entity = aService.checkLogin(name,pass);
                if(entity==null){
                    request.setAttribute("msg","用户名或密码错误");
                    RequestDispatcher rd=request.getRequestDispatcher("/Login.jsp");
                    rd.forward(request, response);
                }else{
                    System.out.println(entity.toString());
                    request.getSession().setAttribute("admin", entity);
                    //response.sendRedirect("./index.jsp");
                    RequestDispatcher rd=request.getRequestDispatcher("index.jsp");
                    rd.forward(request, response);        
                }
            }else{
                request.setAttribute("msg","验证码不正确");
                RequestDispatcher rd=request.getRequestDispatcher("/Login.jsp");
                rd.forward(request, response);
            }
        }
        
        
    }

    
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

验证码的生成

/写汉字  
         String base = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";
        //写4个字
        Color c = Color.BLUE;
        g.setColor(c);
        Font font = new Font("宋体", Font.ITALIC, 20);
        g.setFont(font);
        
        StringBuffer sb = new StringBuffer();
        //产生汉字
        for(int i=0;i<4;i++){
            int location = new Random().nextInt(base.length()-1);
            char chr = base.charAt(location);
            sb.append(chr+"");
        }
        checkCode=sb.toString();
        Graphics2D gd = (Graphics2D) g;
        gd.rotate(0.05);
        //把汉字写到图片上
        g.drawString(checkCode, 10, 20);

    }

    private static void setRandomLine(Graphics g) {
        Color c = Color.GREEN;
        g.setColor(c);
        for (int i = 0; i <= 4; i++) {
            int x1 = new Random().nextInt(WIDTH);
            int y1 = new Random().nextInt(HEIGHT);

            int x2 = new Random().nextInt(WIDTH);
            int y2 = new Random().nextInt(HEIGHT);

            g.drawLine(x1, y1, x2, y2);
        }

    }

    private static  void setBorder(Graphics g) {
        Color c = Color.BLACK;
        g.setColor(c);
        g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);

    }

    private static void setBackground(Graphics g) {
        Color c = Color.WHITE;
        g.setColor(c);
        g.fillRect(0, 0, WIDTH, HEIGHT);

    }
    
    
    public static  void outImage(OutputStream os) throws IOException{
        // 2、创建图片
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, IMAGETYPE);
        // 3、得到图型
        Graphics g = image.getGraphics();
        // 4、设置图片背景色
        setBackground(g);
        // 5、向图片上写边框
        setBorder(g);
        // 6、向图片上写干扰线
        setRandomLine(g);
        // 7、向图片上写数据
        setFont(g);
        // 8、把图片写给浏览器
        ImageIO.write(image, "jpeg", os);
    }