Servlet Java Web开发4 Cookie 和Session

Cookie 的概念

Cookie就是若干组键值对。

服务器在响应头中以如下格式设置cookie

l

浏览器将cookie存储在本地,在以后的访问中,在请求中以如下形式发给服务器

关键API

服务器写Cookie

Cookie c=new Cookie("id", "the id is legion");
esponse.addCookie(c);
//多个依次重复

服务器读cookie

//从请求头中获取cookie数组
Cookie[] cs=request.getCookies();
//对于数组中每一个Cookie,有getName 和getValue的方法
//分别获取键和值

例子:本例子AServlet写若干cookie,其中一个cookie有key为”id“,

BServlet试图读取该id 的值。

//AServlet Get
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        Cookie c=new Cookie("id", "the id is legion");
        response.addCookie(c);
        Cookie c2=new Cookie("something", "sskalsa");
        response.addCookie(c2);
        response.getWriter().print("i sent you an id in cookie");
        
    }

//BServlet Get
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        Cookie[] cs=request.getCookies();
        if(cs!=null) {
            for(Cookie c:cs) {
                if(c.getName().equals("id")) {
                    String str="获取ID的值为"+c.getValue();
                    response.getWriter().print(str);
                }
            }
        }
    }
View Code

 Cookie  查看和寿命

chrome://settings/content

使用setMaxAge设置cookie寿命,参数单位为秒。服务器回复格式

设置为-1,表示cookie只在内存存在。设置为0,表示通知浏览器在本地彻底删除该cookie。

 Cookie路径和语言

设置:cookie.setPath("/cookietest/servlet");

如果请求路径包含了该Cookie路径,那么就会在请求中包含该cookie。

默认路径:如果没有使用setPath,那么cookie 的默认路径算到项目名。

比如访问http://localhost:8080/HelloWeb/AServlet,设置了cookie但没有设置路径,其路径就是/HelloWeb

 

如何使得所有二级域名共享cookies

 cookie.setPath("/");   cookie.setDomain("*.XXX.com");

cookie语言问题

使用URLEncoder.encode和URLDecoder.decode

 

Sessions

一个例子:说明:登录页面

输入用户名后,以post参数的形式(在body中username=XXXX跳转到LoginServlet

没有登录访问index1.jsp提示“你还没有登录”,如果已经登录,打印出用户名。

核心API。

servlet 中使用HttpSession s=request.getSession();

然后 session.setAttribute("username",name);

index1.jsp 中使用session.getAttribute("username");

所有代码

/////index1.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>Index 1 Page</title>
</head>
<body>
  <body>
<h1>index1.jsp</h1>
<%
    String username = (String)session.getAttribute("username"); 
    if(username == null) {
        out.print("您还没有登录!"); 
    } else {
        out.print("用户名:" + username); 
    }
%>
<hr/>
<a href="/HelloWeb/index2.jsp">index2</a>
  </body>

</body>
</html>




////login.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>
</head>
<body>
<h1>login.jsp</h1>
    <hr/>
    <form action="/HelloWeb/LoginServlet" method="post">
        用户名:<input type="text" name="username" /><br/>
        <input type="submit" value="Submit"/>
    </form>

</body>
</html>

//////LoginServlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        String name = request.getParameter("username");
        if (name.equalsIgnoreCase("rightuser")) {
            HttpSession session = request.getSession();
            session.setAttribute("username", name);
            response.sendRedirect("/HelloWeb/index1.jsp");
        } else {
            response.getWriter().println("用户名错误");
        }
    }
View Code

Cookie 

浏览器第一次访问服务器,cookie没有JSESSIONID

服务器返回

以后每次浏览,request头中都携带

 

使用sessions技术实现图形验证码

 

响应处理servlet分别打印正确或者错误

 

为了简化起见,这里不考虑用户名和密码的问题,只考虑验证码是否正确

login的代码

<%@ 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>
</head>
<body>
<h1>login.jsp</h1>
    <hr/>
    
    <form action="/HelloWeb/LoginServlet" method="post">
        用户名:<input type="text" name="username" /><br/>
        密码:  <input type="password" name="password"/><br/>
        验证码:<input type="text" name="verifyCode" size=3/>
        <img id="img" src="/HelloWeb/BServlet"/>
        <a href="javascript:change()">换一张</a>
        <br/>
        <input type="submit" value="Submit"/>
    </form>
<script type="text/javascript">
function change() {
    var img=document.getElementById("img");
    img.src="/HelloWeb/BServlet?a="+new Date().getTime();
    
}
</script>
</body>
</html>

 这里关键的点:

<img id="img" src="/HelloWeb/BServlet"/>
这里BServlet 的代码,BServlet 负责使用VerifyCode类生成随机图形,及其对应的文本。
这里往session中设置了vc的值,
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        VerifyCode vc=new VerifyCode();
        BufferedImage image=vc.getImage();
        request.getSession().setAttribute("vc", vc.getText());
        VerifyCode.output(image, response.getOutputStream());
    }

在处理用户请求的LoginServlet中会提取session 中键 vc的值,将其和用户输入的文本进行比较

下面是LoginServlet的代码

protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=utf-8");
        String scode=(String)request.getSession().getAttribute("vc");
        String paramCode=request.getParameter("verifyCode");
        if(!paramCode.equals(scode)) {
            response.getWriter().print("验证码错误");
        }else {
            response.getWriter().println("验证码正确");
        }
        
    }

 

 辅助类VerifyCode的代码

package com.legion;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

public class VerifyCode {
    private int w = 70;
    private int h = 35;
     private Random r = new Random();
     // {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"}
    private String[] fontNames  = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
    // 可选字符
    private String codes  = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
    // 背景色
    private Color bgColor  = new Color(255, 255, 255);
    // 验证码上的文本
    private String text ;
    
    // 生成随机的颜色
    private Color randomColor () {
        int red = r.nextInt(150);
        int green = r.nextInt(150);
        int blue = r.nextInt(150);
        return new Color(red, green, blue);
    }
    
    // 生成随机的字体
    private Font randomFont () {
        int index = r.nextInt(fontNames.length);
        String fontName = fontNames[index];//生成随机的字体名称
        int style = r.nextInt(4);//生成随机的样式, 0(无样式), 1(粗体), 2(斜体), 3(粗体+斜体)
        int size = r.nextInt(5) + 24; //生成随机字号, 24 ~ 28
        return new Font(fontName, style, size);
    }
    
    // 画干扰线
    private void drawLine (BufferedImage image) {
        int num  = 3;//一共画3条
        Graphics2D g2 = (Graphics2D)image.getGraphics();
        for(int i = 0; i < num; i++) {//生成两个点的坐标,即4个值
            int x1 = r.nextInt(w);
            int y1 = r.nextInt(h);
            int x2 = r.nextInt(w);
            int y2 = r.nextInt(h); 
            g2.setStroke(new BasicStroke(1.5F)); 
            g2.setColor(Color.BLUE); //干扰线是蓝色
            g2.drawLine(x1, y1, x2, y2);//画线
        }
    }
    
    // 随机生成一个字符
    private char randomChar () {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }
    
    // 创建BufferedImage
    private BufferedImage createImage () {
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
        Graphics2D g2 = (Graphics2D)image.getGraphics(); 
        g2.setColor(this.bgColor);
        g2.fillRect(0, 0, w, h);
         return image;
    }
    
    // 调用这个方法得到验证码
    public BufferedImage getImage () {
        BufferedImage image = createImage();//创建图片缓冲区 
        Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境
        StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
        // 向图片中画4个字符
        for(int i = 0; i < 4; i++)  {//循环四次,每次生成一个字符
            String s = randomChar() + "";//随机生成一个字母 
            sb.append(s); //把字母添加到sb中
            float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
            g2.setFont(randomFont()); //设置随机字体
            g2.setColor(randomColor()); //设置随机颜色
            g2.drawString(s, x, h-5); //画图
        }
        this.text = sb.toString(); //把生成的字符串赋给了this.text
        drawLine(image); //添加干扰线
        return image;        
    }
    
    // 返回验证码图片上的文本
    public String getText () {
        return text;
    }
    
    // 保存图片到指定的输出流
    public static void output (BufferedImage image, OutputStream out) 
                throws IOException {
        ImageIO.write(image, "JPEG", out);
    }
}

 

posted on 2018-07-13 21:31  legion  阅读(215)  评论(0编辑  收藏  举报

导航